Print this page
3087 libuuid has a lot of dependencies
@@ -19,36 +19,33 @@
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
#include <uuid/uuid.h>
#include <sys/sockio.h>
-#include <libdlpi.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "etheraddr.h"
-static boolean_t get_etheraddr(const char *linkname, void *arg);
-
/*
* get an individual arp entry
*/
-int
+static int
arp_get(uuid_node_t *node)
{
struct utsname name;
struct arpreq ar;
struct hostent *hp;
@@ -87,56 +84,57 @@
return (-1);
return (0);
}
/*
- * Name: get_ethernet_address
- *
- * Description: Obtains the system ethernet address.
- *
- * Returns: 0 on success, non-zero otherwise. The system ethernet
- * address is copied into the passed-in variable.
+ * Fake up a valid Ethernet address based on gethostid().
+ * This is likely to be unique to this machine, and that's
+ * good enough for libuuid when we can't easily get our
+ * real Ethernet address.
*/
-int
-get_ethernet_address(uuid_node_t *node)
+static int
+hostid_get(uuid_node_t *node)
{
- walker_arg_t state;
+ uint32_t hostid;
- if (arp_get(node) == 0)
- return (0);
+ if ((hostid = (uint32_t)gethostid()) == 0)
+ return (-1);
+ hostid = htonl(hostid);
/*
- * Try to get physical (ethernet) address from network interfaces.
+ * Like gen_ethernet_address(), use prefix:
+ * 8:0:... with the multicast bit set.
*/
- state.wa_addrvalid = B_FALSE;
- dlpi_walk(get_etheraddr, &state, 0);
- if (state.wa_addrvalid)
- bcopy(state.wa_etheraddr, node, state.wa_etheraddrlen);
+ node->nodeID[0] = 0x88;
+ node->nodeID[1] = 0x00;
+ (void) memcpy(node->nodeID + 2, &hostid, sizeof (hostid));
- return (state.wa_addrvalid ? 0 : -1);
+ return (0);
}
/*
- * Get the physical address via DLPI and update the flag to true upon success.
+ * Name: get_ethernet_address
+ *
+ * Description: Obtains the system ethernet address, if possible.
+ *
+ * Returns: 0 on success, non-zero otherwise. The system ethernet
+ * address is copied into the passed-in variable.
+ *
+ * Note: This does NOT need to get the REAL Ethernet address.
+ * This library only needs something that looks like an Ethernet
+ * address and that's likely to be unique to this machine. Also,
+ * we really don't want to drag in libdlpi (etc) here so this just
+ * tries an SIOCGARP ioctl, then a hostid-derived method. If all
+ * methods here fail, the caller generates an Ethernet address.
*/
-static boolean_t
-get_etheraddr(const char *linkname, void *arg)
+int
+get_ethernet_address(uuid_node_t *node)
{
- int retval;
- dlpi_handle_t dh;
- walker_arg_t *statep = arg;
- if (dlpi_open(linkname, &dh, 0) != DLPI_SUCCESS)
- return (B_FALSE);
+ if (arp_get(node) == 0)
+ return (0);
- statep->wa_etheraddrlen = DLPI_PHYSADDR_MAX;
- retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR,
- statep->wa_etheraddr, &(statep->wa_etheraddrlen));
+ if (hostid_get(node) == 0)
+ return (0);
- dlpi_close(dh);
-
- if (retval == DLPI_SUCCESS) {
- statep->wa_addrvalid = B_TRUE;
- return (B_TRUE);
- }
- return (B_FALSE);
+ return (-1);
}