]>
git.saurik.com Git - apple/libinfo.git/blob - gen.subproj/getifaddrs.c
9522032c1db2043b7267486f2f9ba50e976dc262
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__)
81 getifaddrs(struct ifaddrs
**pif
)
91 struct ifaddrs
*cif
= 0;
93 struct rt_msghdr
*rtm
;
94 struct if_msghdr
*ifm
;
95 struct ifa_msghdr
*ifam
;
96 struct sockaddr_dl
*dl
;
98 struct ifaddrs
*ifa
, *ift
;
100 #else /* NET_RT_IFLIST */
106 #endif /* NET_RT_IFLIST */
115 mib
[2] = 0; /* protocol */
116 mib
[3] = 0; /* wildcard address family */
117 mib
[4] = NET_RT_IFLIST
;
118 mib
[5] = 0; /* no flags */
119 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
121 if ((buf
= malloc(needed
)) == NULL
)
123 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0) {
128 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
129 rtm
= (struct rt_msghdr
*)next
;
130 if (rtm
->rtm_version
!= RTM_VERSION
)
132 switch (rtm
->rtm_type
) {
134 ifm
= (struct if_msghdr
*)rtm
;
135 if (ifm
->ifm_addrs
& RTA_IFP
) {
136 index
= ifm
->ifm_index
;
138 dl
= (struct sockaddr_dl
*)(ifm
+ 1);
139 dcnt
+= SA_RLEN((struct sockaddr
*)dl
) +
142 dcnt
+= sizeof(ifm
->ifm_data
);
143 #endif /* HAVE_IFM_DATA */
144 ncnt
+= dl
->sdl_nlen
+ 1;
150 ifam
= (struct ifa_msghdr
*)rtm
;
151 if (index
&& ifam
->ifam_index
!= index
)
152 abort(); /* this cannot happen */
154 #define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
155 if (index
== 0 || (ifam
->ifam_addrs
& RTA_MASKS
) == 0)
157 p
= (char *)(ifam
+ 1);
159 #ifdef HAVE_IFAM_DATA
160 dcnt
+= sizeof(ifam
->ifam_data
) + ALIGNBYTES
;
161 #endif /* HAVE_IFAM_DATA */
162 /* Scan to look for length of address */
164 for (p0
= p
, i
= 0; i
< RTAX_MAX
; i
++) {
165 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
168 sa
= (struct sockaddr
*)p
;
176 for (p
= p0
, i
= 0; i
< RTAX_MAX
; i
++) {
177 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
180 sa
= (struct sockaddr
*)p
;
182 if (i
== RTAX_NETMASK
&& SA_LEN(sa
) == 0)
191 #else /* NET_RT_IFLIST */
193 ifc
.ifc_len
= sizeof(buf
);
195 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
197 i
= ioctl(sock
, SIOCGIFCONF
, (char *)&ifc
);
203 lifr
= (struct ifreq
*)&ifc
.ifc_buf
[ifc
.ifc_len
];
211 ncnt
+= sizeof(ifr
->ifr_name
) + 1;
213 ifr
= (struct ifreq
*)(((char *)sa
) + SA_LEN(sa
));
215 #endif /* NET_RT_IFLIST */
217 if (icnt
+ dcnt
+ ncnt
== 1) {
222 data
= malloc(sizeof(struct ifaddrs
) * icnt
+ dcnt
+ ncnt
);
228 ifa
= (struct ifaddrs
*)data
;
229 data
+= sizeof(struct ifaddrs
) * icnt
;
232 memset(ifa
, 0, sizeof(struct ifaddrs
) * icnt
);
237 for (next
= buf
; next
< buf
+ needed
; next
+= rtm
->rtm_msglen
) {
238 rtm
= (struct rt_msghdr
*)next
;
239 if (rtm
->rtm_version
!= RTM_VERSION
)
241 switch (rtm
->rtm_type
) {
243 ifm
= (struct if_msghdr
*)rtm
;
244 if (ifm
->ifm_addrs
& RTA_IFP
) {
245 index
= ifm
->ifm_index
;
246 dl
= (struct sockaddr_dl
*)(ifm
+ 1);
249 ift
->ifa_name
= names
;
250 ift
->ifa_flags
= (int)ifm
->ifm_flags
;
251 memcpy(names
, dl
->sdl_data
, dl
->sdl_nlen
);
252 names
[dl
->sdl_nlen
] = 0;
253 names
+= dl
->sdl_nlen
+ 1;
255 ift
->ifa_addr
= (struct sockaddr
*)data
;
256 memcpy(data
, dl
, SA_LEN((struct sockaddr
*)dl
));
257 data
+= SA_RLEN((struct sockaddr
*)dl
);
260 /* ifm_data needs to be aligned */
261 ift
->ifa_data
= data
= (void *)ALIGN(data
);
262 memcpy(data
, &ifm
->ifm_data
, sizeof(ifm
->ifm_data
));
263 data
+= sizeof(ifm
->ifm_data
);
264 #else /* HAVE_IFM_DATA */
265 ift
->ifa_data
= NULL
;
266 #endif /* HAVE_IFM_DATA */
268 ift
= (ift
->ifa_next
= ift
+ 1);
274 ifam
= (struct ifa_msghdr
*)rtm
;
275 if (index
&& ifam
->ifam_index
!= index
)
276 abort(); /* this cannot happen */
278 if (index
== 0 || (ifam
->ifam_addrs
& RTA_MASKS
) == 0)
280 ift
->ifa_name
= cif
->ifa_name
;
281 ift
->ifa_flags
= cif
->ifa_flags
;
282 ift
->ifa_data
= NULL
;
283 p
= (char *)(ifam
+ 1);
284 /* Scan to look for length of address */
286 for (p0
= p
, i
= 0; i
< RTAX_MAX
; i
++) {
287 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
290 sa
= (struct sockaddr
*)p
;
298 for (p
= p0
, i
= 0; i
< RTAX_MAX
; i
++) {
299 if ((RTA_MASKS
& ifam
->ifam_addrs
& (1 << i
))
302 sa
= (struct sockaddr
*)p
;
306 ift
->ifa_addr
= (struct sockaddr
*)data
;
307 memcpy(data
, p
, len
);
313 (struct sockaddr
*)data
;
314 if (SA_LEN(sa
) == 0) {
315 memset(data
, 0, alen
);
319 memcpy(data
, p
, len
);
325 (struct sockaddr
*)data
;
326 memcpy(data
, p
, len
);
333 #ifdef HAVE_IFAM_DATA
334 /* ifam_data needs to be aligned */
335 ift
->ifa_data
= data
= (void *)ALIGN(data
);
336 memcpy(data
, &ifam
->ifam_data
, sizeof(ifam
->ifam_data
));
337 data
+= sizeof(ifam
->ifam_data
);
338 #endif /* HAVE_IFAM_DATA */
340 ift
= (ift
->ifa_next
= ift
+ 1);
346 #else /* NET_RT_IFLIST */
348 lifr
= (struct ifreq
*)&ifc
.ifc_buf
[ifc
.ifc_len
];
353 ift
->ifa_name
= names
;
354 names
[sizeof(ifr
->ifr_name
)] = 0;
355 strncpy(names
, ifr
->ifr_name
, sizeof(ifr
->ifr_name
));
359 ift
->ifa_addr
= (struct sockaddr
*)data
;
361 memcpy(data
, sa
, SA_LEN(sa
));
364 ifr
= (struct ifreq
*)(((char *)sa
) + SA_LEN(sa
));
365 ift
= (ift
->ifa_next
= ift
+ 1);
367 #endif /* NET_RT_IFLIST */
369 ift
->ifa_next
= NULL
;
379 freeifaddrs(struct ifaddrs
*ifp
)