1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77#ifdef HAVE_CONFIG_H
78#include <config.h>
79#endif
80
81/* Horrible Darwin/BSD hack */
82#if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)) && defined(_POSIX_C_SOURCE)
83#undef _POSIX_C_SOURCE
84#endif
85
86#include <stdio.h>
87#include <fcntl.h>
88#include <unistd.h>
89#include <string.h>
90#include <stdlib.h>
91#ifndef UUID_BUILD_STANDALONE
92#include <dce/dce.h>
93#include <dce/dce_utils.h>
94#else
95#include "uuid.h"
96#endif
97#include <sys/types.h>
98#include <sys/socket.h>
99#include <sys/ioctl.h>
100/* Bizarre hack for HP-UX ia64 where a system header
101 * makes reference to a kernel-only data structure
102 */
103#if defined(__hpux) && defined(__ia64)
104union mpinfou {};
105#endif
106#include <net/if.h>
107#ifdef HAVE_SYS_SOCKIO_H
108#include <sys/sockio.h>
109#endif
110#ifdef notdef
111#include <sys/sysctl.h>
112#endif
113#ifdef HAVE_NET_IF_DL_H
114#include <net/if_dl.h>
115#endif
116#ifdef HAVE_NET_IF_ARP_H
117#include <net/if_arp.h>
118#endif
119void dce_get_802_addr(dce_802_addr_t *addr, error_status_t *st)
120{
121	char buf[sizeof(struct ifreq) * 128];
122	struct ifconf ifc;
123	struct ifreq *ifr;
124	int s, i;
125	struct sockaddr *sa;
126#ifdef AF_LINK
127	struct sockaddr_dl *sdl;
128#endif
129#if defined(SIOCGARP)
130	struct arpreq arpreq;
131#endif
132	struct ifreq ifreq;
133
134	s = socket(AF_INET, SOCK_DGRAM, 0);
135	if (s < 0) {
136		*st = utils_s_802_cant_read;
137		return;
138	}
139
140	ifc.ifc_len = sizeof(buf);
141	ifc.ifc_buf = buf;
142	memset(buf, 0, sizeof(buf));
143
144	i = ioctl(s, SIOCGIFCONF, (char *)&ifc);
145	if (i < 0) {
146		*st = utils_s_802_cant_read;
147		close(s);
148		return;
149	}
150
151	for (i = 0; i < ifc.ifc_len; ) {
152		ifr = (struct ifreq *)&ifc.ifc_buf[i];
153		/* Initialize sa here because it is used under the next
154		 * label, and the loopback check could jump directly
155		 * to the next label.
156		 */
157#ifdef AF_LINK
158		sa = &ifr->ifr_addr;
159#else
160		sa = NULL;
161#endif
162
163#ifdef SIOCGIFFLAGS
164		/* Skip over loopback and point-to-point interfaces. */
165		memcpy(&ifreq, ifr, sizeof(ifreq));
166		if (ioctl(s, SIOCGIFFLAGS, &ifreq) == 0) {
167			if (ifreq.ifr_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) {
168			  goto next;
169			}
170		}
171#endif
172
173#ifdef AF_LINK
174		if (sa->sa_family == AF_LINK) {
175			sdl = (struct sockaddr_dl *)sa;
176			if (sdl->sdl_alen == 6) {
177				memcpy(addr->eaddr, (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, 6);
178				*st = error_status_ok;
179				close(s);
180				return;
181			}
182		}
183#endif /* AF_LINK */
184
185#if defined(SIOCGIFHWADDR)
186		memcpy(&ifreq, ifr, sizeof(ifreq));
187		if (ioctl(s, SIOCGIFHWADDR, &ifreq) == 0) {
188			memcpy(addr->eaddr, &ifreq.ifr_hwaddr.sa_data, 6);
189			*st = error_status_ok;
190			close(s);
191			return;
192		}
193#elif defined(SIOCGARP)
194		memset(&arpreq, 0, sizeof(arpreq));
195		arpreq.arp_pa = ifr->ifr_dstaddr;
196		arpreq.arp_flags = 0;
197		if (ioctl(s, SIOCGARP, &arpreq) == 0) {
198#ifdef AF_LINK
199			sdl = (struct sockaddr_dl *)&arpreq.arp_ha;
200			memcpy(addr->eaddr, (unsigned char *)&sdl->sdl_data + sdl->sdl_nlen, 6);
201#else
202			memcpy(addr->eaddr, (unsigned char*)&arpreq.arp_ha.sa_data[0], 6);
203#endif
204			*st = error_status_ok;
205			close(s);
206			return;
207		}
208#elif defined(SIOCGENADDR)
209		memcpy(&ifreq, ifr, sizeof(ifreq));
210		if (ioctl(s, SIOCGENADDR, &ifreq) == 0) {
211			memcpy(addr->eaddr, ifreq.ifr_enaddr, 6);
212			*st = error_status_ok;
213			close(s);
214			return;
215		}
216#else
217		//#error Please implement dce_get_802_addr() for your operating system
218#endif
219
220	next:
221#if !defined(__svr4__) && !defined(linux) && !defined(_HPUX) /* XXX FixMe to be portable */
222		if (sa && sa->sa_len > sizeof(ifr->ifr_addr)) {
223			i += sizeof(ifr->ifr_name) + sa->sa_len;
224		} else
225#endif
226			i += sizeof(*ifr);
227
228	}
229
230	{
231	    unsigned int seed = 1;
232	    unsigned char* buf = (unsigned char*) addr->eaddr;
233	    int i;
234
235	    for (i = 0; i < 6; i++)
236	    {
237		buf[i] = rand_r(&seed);
238	    }
239
240	    close(s);
241	    return;
242	}
243
244	*st = utils_s_802_cant_read;
245	close(s);
246	return;
247}
248