]>
git.saurik.com Git - apple/libinfo.git/blob - gen.subproj/getifaddrs.c
2 * Copyright (c) 1995, 1999
3 * Berkeley Software Design, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
12 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
15 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform
27 * try-and-error for region size.
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
34 #include <sys/param.h>
35 #include <net/route.h>
36 #include <sys/sysctl.h>
37 #include <net/if_dl.h>
46 #define SA_LEN(sa) sizeof(struct sockaddr)
50 #define SA_LEN(sa) (sa)->sa_len
53 #define SALIGN (sizeof(long) - 1)
54 #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
58 * On systems with a routing socket, ALIGNBYTES should match the value
59 * that the kernel uses when building the messages.
61 #define ALIGNBYTES XXX
64 #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
67 #if _BSDI_VERSION >= 199701
71 #if _BSDI_VERSION >= 199802
72 /* ifam_data is very specific to recent versions of bsdi */
73 #define HAVE_IFAM_DATA
76 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
85 getifaddrs(struct ifaddrs
**pif
)
95 struct ifaddrs
*cif
= 0;
97 struct rt_msghdr
*rtm
;
98 struct if_msghdr
*ifm
;
99 struct ifa_msghdr
*ifam
;
100 struct sockaddr_dl
*dl
;
102 struct ifaddrs
*ifa
, *ift
;
104 #else /* NET_RT_IFLIST */
110 #endif /* NET_RT_IFLIST */
119 mib
[2] = 0; /* protocol */
120 mib
[3] = 0; /* wildcard address family */
121 mib
[4] = NET_RT_IFLIST
;
122 mib
[5] = 0; /* no flags */
123 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
125 if ((buf
= malloc(needed
)) == NULL
)
127 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0) {
132 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
133 rtm
= (struct rt_msghdr
*)next
;
134 if (rtm
->rtm_version
!= RTM_VERSION
)
136 switch (rtm
->rtm_type
) {
138 ifm
= (struct if_msghdr
*)rtm
;
139 if (ifm
->ifm_addrs
& RTA_IFP
) {
140 index
= ifm
->ifm_index
;
142 dl
= (struct sockaddr_dl
*)(ifm
+ 1);
143 dcnt
+= SA_RLEN((struct sockaddr
*)dl
) +
146 dcnt
+= sizeof(ifm
->ifm_data
);
147 #endif /* HAVE_IFM_DATA */
148 ncnt
+= dl
->sdl_nlen
+ 1;
154 ifam
= (struct ifa_msghdr
*)rtm
;
155 if (index
&& ifam
->ifam_index
!= index
)
156 abort(); /* this cannot happen */
158 #define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
159 if (index
== 0 || (ifam
->ifam_addrs
& RTA_MASKS
) == 0)
161 p
= (char *)(ifam
+ 1);
163 #ifdef HAVE_IFAM_DATA
164 dcnt
+= sizeof(ifam
->ifam_data
) + ALIGNBYTES
;
165 #endif /* HAVE_IFAM_DATA */
166 /* Scan to look for length of address */
168 for (p0
= p
, i
= 0; i
< RTAX_MAX
; i
++) {
169 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
172 sa
= (struct sockaddr
*)p
;
180 for (p
= p0
, i
= 0; i
< RTAX_MAX
; i
++) {
181 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
184 sa
= (struct sockaddr
*)p
;
186 if (i
== RTAX_NETMASK
&& SA_LEN(sa
) == 0)
195 #else /* NET_RT_IFLIST */
197 ifc
.ifc_len
= sizeof(buf
);
199 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
201 i
= ioctl(sock
, SIOCGIFCONF
, (char *)&ifc
);
207 lifr
= (struct ifreq
*)&ifc
.ifc_buf
[ifc
.ifc_len
];
215 ncnt
+= sizeof(ifr
->ifr_name
) + 1;
217 ifr
= (struct ifreq
*)(((char *)sa
) + SA_LEN(sa
));
219 #endif /* NET_RT_IFLIST */
221 if (icnt
+ dcnt
+ ncnt
== 1) {
226 data
= malloc(sizeof(struct ifaddrs
) * icnt
+ dcnt
+ ncnt
);
232 ifa
= (struct ifaddrs
*)data
;
233 data
+= sizeof(struct ifaddrs
) * icnt
;
236 memset(ifa
, 0, sizeof(struct ifaddrs
) * icnt
);
241 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
242 rtm
= (struct rt_msghdr
*)next
;
243 if (rtm
->rtm_version
!= RTM_VERSION
)
245 switch (rtm
->rtm_type
) {
247 ifm
= (struct if_msghdr
*)rtm
;
248 if (ifm
->ifm_addrs
& RTA_IFP
) {
249 index
= ifm
->ifm_index
;
250 dl
= (struct sockaddr_dl
*)(ifm
+ 1);
253 ift
->ifa_name
= names
;
254 ift
->ifa_flags
= (int)ifm
->ifm_flags
;
255 memcpy(names
, dl
->sdl_data
, dl
->sdl_nlen
);
256 names
[dl
->sdl_nlen
] = 0;
257 names
+= dl
->sdl_nlen
+ 1;
259 ift
->ifa_addr
= (struct sockaddr
*)data
;
260 memcpy(data
, dl
, SA_LEN((struct sockaddr
*)dl
));
261 data
+= SA_RLEN((struct sockaddr
*)dl
);
264 /* ifm_data needs to be aligned */
265 ift
->ifa_data
= data
= (void *)ALIGN(data
);
266 memcpy(data
, &ifm
->ifm_data
, sizeof(ifm
->ifm_data
));
267 data
+= sizeof(ifm
->ifm_data
);
268 #else /* HAVE_IFM_DATA */
269 ift
->ifa_data
= NULL
;
270 #endif /* HAVE_IFM_DATA */
272 ift
= (ift
->ifa_next
= ift
+ 1);
278 ifam
= (struct ifa_msghdr
*)rtm
;
279 if (index
&& ifam
->ifam_index
!= index
)
280 abort(); /* this cannot happen */
282 if (index
== 0 || (ifam
->ifam_addrs
& RTA_MASKS
) == 0)
284 ift
->ifa_name
= cif
->ifa_name
;
285 ift
->ifa_flags
= cif
->ifa_flags
;
286 ift
->ifa_data
= NULL
;
287 p
= (char *)(ifam
+ 1);
288 /* Scan to look for length of address */
290 for (p0
= p
, i
= 0; i
< RTAX_MAX
; i
++) {
291 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
294 sa
= (struct sockaddr
*)p
;
302 for (p
= p0
, i
= 0; i
< RTAX_MAX
; i
++) {
303 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
306 sa
= (struct sockaddr
*)p
;
310 ift
->ifa_addr
= (struct sockaddr
*)data
;
311 memcpy(data
, p
, len
);
317 (struct sockaddr
*)data
;
318 if (SA_LEN(sa
) == 0) {
319 memset(data
, 0, alen
);
323 memcpy(data
, p
, len
);
329 (struct sockaddr
*)data
;
330 memcpy(data
, p
, len
);
337 #ifdef HAVE_IFAM_DATA
338 /* ifam_data needs to be aligned */
339 ift
->ifa_data
= data
= (void *)ALIGN(data
);
340 memcpy(data
, &ifam
->ifam_data
, sizeof(ifam
->ifam_data
));
341 data
+= sizeof(ifam
->ifam_data
);
342 #endif /* HAVE_IFAM_DATA */
344 ift
= (ift
->ifa_next
= ift
+ 1);
350 #else /* NET_RT_IFLIST */
352 lifr
= (struct ifreq
*)&ifc
.ifc_buf
[ifc
.ifc_len
];
357 ift
->ifa_name
= names
;
358 names
[sizeof(ifr
->ifr_name
)] = 0;
359 strncpy(names
, ifr
->ifr_name
, sizeof(ifr
->ifr_name
));
363 ift
->ifa_addr
= (struct sockaddr
*)data
;
365 memcpy(data
, sa
, SA_LEN(sa
));
368 ifr
= (struct ifreq
*)(((char *)sa
) + SA_LEN(sa
));
369 ift
= (ift
->ifa_next
= ift
+ 1);
371 #endif /* NET_RT_IFLIST */
373 ift
->ifa_next
= NULL
;
383 freeifaddrs(struct ifaddrs
*ifp
)