/* ** OSSP uuid - Universally Unique Identifier ** Copyright (c) 2004-2008 Ralf S. Engelschall ** Copyright (c) 2004-2008 The OSSP Project ** ** This file is part of OSSP uuid, a library for the generation ** of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** uuid_mac.c: Media Access Control (MAC) resolver implementation */ /* own headers (part (1/2) */ #include "uuid_ac.h" /* system headers */ #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_SOCKIO_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_NET_IF_H #include #endif #ifdef HAVE_NET_IF_DL_H #include #endif #ifdef HAVE_NET_IF_ARP_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_IFADDRS_H #include #endif /* own headers (part (1/2) */ #include "uuid_mac.h" #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE (/*lint -save -e506*/ !FALSE /*lint -restore*/) #endif /* return the Media Access Control (MAC) address of the FIRST network interface card (NIC) */ int mac_address(unsigned char *data_ptr, size_t data_len) { /* sanity check arguments */ if (data_ptr == NULL || data_len < MAC_LEN) return FALSE; #if defined(HAVE_IFADDRS_H) && defined(HAVE_NET_IF_DL_H) && defined(HAVE_GETIFADDRS) /* use getifaddrs(3) on BSD class platforms (xxxBSD, MacOS X, etc) */ { struct ifaddrs *ifap; struct ifaddrs *ifap_head; const struct sockaddr_dl *sdl; unsigned char *ucp; int i; if (getifaddrs(&ifap_head) < 0) return FALSE; for (ifap = ifap_head; ifap != NULL; ifap = ifap->ifa_next) { if (ifap->ifa_addr != NULL && ifap->ifa_addr->sa_family == AF_LINK) { sdl = (const struct sockaddr_dl *)(void *)ifap->ifa_addr; ucp = (unsigned char *)(sdl->sdl_data + sdl->sdl_nlen); if (sdl->sdl_alen > 0) { for (i = 0; i < MAC_LEN && i < sdl->sdl_alen; i++, ucp++) data_ptr[i] = (unsigned char)(*ucp & 0xff); freeifaddrs(ifap_head); return TRUE; } } } freeifaddrs(ifap_head); } #endif #if defined(HAVE_NET_IF_H) && defined(SIOCGIFHWADDR) /* use SIOCGIFHWADDR ioctl(2) on Linux class platforms */ { struct ifreq ifr; struct sockaddr *sa; int s; int i; if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) return FALSE; sprintf(ifr.ifr_name, "eth0"); if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { close(s); return FALSE; } sa = (struct sockaddr *)&ifr.ifr_addr; for (i = 0; i < MAC_LEN; i++) data_ptr[i] = (unsigned char)(sa->sa_data[i] & 0xff); close(s); return TRUE; } #endif #if defined(SIOCGARP) /* use SIOCGARP ioctl(2) on SVR4 class platforms (Solaris, etc) */ { char hostname[MAXHOSTNAMELEN]; struct hostent *he; struct arpreq ar; struct sockaddr_in *sa; int s; int i; if (gethostname(hostname, sizeof(hostname)) < 0) return FALSE; if ((he = gethostbyname(hostname)) == NULL) return FALSE; if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) return FALSE; memset(&ar, 0, sizeof(ar)); sa = (struct sockaddr_in *)((void *)&(ar.arp_pa)); sa->sin_family = AF_INET; memcpy(&(sa->sin_addr), *(he->h_addr_list), sizeof(struct in_addr)); if (ioctl(s, SIOCGARP, &ar) < 0) { close(s); return FALSE; } close(s); if (!(ar.arp_flags & ATF_COM)) return FALSE; for (i = 0; i < MAC_LEN; i++) data_ptr[i] = (unsigned char)(ar.arp_ha.sa_data[i] & 0xff); return TRUE; } #endif return FALSE; }