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);
 }