]>
Commit | Line | Data |
---|---|---|
7ba0088d A |
1 | /* $KAME: if.c,v 1.17 2001/01/21 15:27:30 itojun Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
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 the project nor the names of its contributors | |
16 | * may be used to endorse or promote products derived from this software | |
17 | * without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | |
7ba0088d A |
30 | */ |
31 | ||
32 | #include <sys/param.h> | |
33 | #include <sys/socket.h> | |
34 | #include <sys/sysctl.h> | |
35 | #include <sys/ioctl.h> | |
36 | #include <net/if.h> | |
37 | #include <net/if_types.h> | |
7af5ce03 | 38 | #include <net/ethernet.h> |
7ba0088d | 39 | #include <ifaddrs.h> |
7ba0088d A |
40 | #include <net/route.h> |
41 | #include <net/if_dl.h> | |
42 | #include <netinet/in.h> | |
43 | #include <netinet/icmp6.h> | |
7ba0088d A |
44 | #include <unistd.h> |
45 | #include <errno.h> | |
46 | #include <stdlib.h> | |
47 | #include <string.h> | |
7ba0088d A |
48 | #include "rtadvd.h" |
49 | #include "if.h" | |
50 | ||
51 | #define ROUNDUP(a, size) \ | |
52 | (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) | |
53 | ||
54 | #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ | |
55 | ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ | |
9c859447 A |
56 | sizeof(uint32_t)) :\ |
57 | sizeof(uint32_t))) | |
7ba0088d | 58 | |
3219cf53 A |
59 | /* Interface list */ |
60 | TAILQ_HEAD(ifilist_head_t, ifinfo); | |
61 | struct ifilist_head_t ifilist = TAILQ_HEAD_INITIALIZER(ifilist); | |
7ba0088d A |
62 | size_t ifblock_size; |
63 | char *ifblock; | |
64 | ||
7af5ce03 | 65 | static void get_iflist(char **buf, size_t *size); |
3219cf53 A |
66 | static void parse_iflist(char *buf, size_t bufsize); |
67 | static void purge_iflist(); | |
7ba0088d A |
68 | |
69 | static void | |
70 | get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) | |
71 | { | |
72 | int i; | |
73 | ||
74 | for (i = 0; i < RTAX_MAX; i++) { | |
75 | if (addrs & (1 << i)) { | |
76 | rti_info[i] = sa; | |
77 | NEXT_SA(sa); | |
78 | } | |
79 | else | |
80 | rti_info[i] = NULL; | |
81 | } | |
82 | } | |
83 | ||
84 | struct sockaddr_dl * | |
85 | if_nametosdl(char *name) | |
86 | { | |
87 | int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; | |
88 | char *buf, *next, *lim; | |
89 | size_t len; | |
90 | struct if_msghdr *ifm; | |
91 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | |
89c4ed63 | 92 | struct sockaddr_dl *sdl = NULL, *ret_sdl = NULL; |
7ba0088d A |
93 | |
94 | if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) | |
95 | return(NULL); | |
96 | if ((buf = malloc(len)) == NULL) | |
97 | return(NULL); | |
7af5ce03 A |
98 | if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { |
99 | free(buf); | |
100 | return(NULL); | |
101 | } | |
7ba0088d A |
102 | |
103 | lim = buf + len; | |
104 | for (next = buf; next < lim; next += ifm->ifm_msglen) { | |
105 | ifm = (struct if_msghdr *)next; | |
106 | if (ifm->ifm_type == RTM_IFINFO) { | |
107 | sa = (struct sockaddr *)(ifm + 1); | |
108 | get_rtaddrs(ifm->ifm_addrs, sa, rti_info); | |
109 | if ((sa = rti_info[RTAX_IFP]) != NULL) { | |
110 | if (sa->sa_family == AF_LINK) { | |
111 | sdl = (struct sockaddr_dl *)sa; | |
112 | if (strlen(name) != sdl->sdl_nlen) | |
113 | continue; /* not same len */ | |
114 | if (strncmp(&sdl->sdl_data[0], | |
115 | name, | |
116 | sdl->sdl_nlen) == 0) { | |
117 | break; | |
118 | } | |
119 | } | |
120 | } | |
121 | } | |
122 | } | |
123 | if (next == lim) { | |
124 | /* search failed */ | |
7af5ce03 A |
125 | free(buf); |
126 | return(NULL); | |
7ba0088d A |
127 | } |
128 | ||
89c4ed63 | 129 | if (sdl == NULL || (ret_sdl = malloc(sdl->sdl_len)) == NULL) |
b8dff150 | 130 | goto end; |
7ba0088d | 131 | memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); |
b8dff150 A |
132 | |
133 | end: | |
134 | free(buf); | |
7af5ce03 | 135 | return(ret_sdl); |
7ba0088d A |
136 | } |
137 | ||
138 | int | |
139 | if_getmtu(char *name) | |
140 | { | |
141 | struct ifaddrs *ifap, *ifa; | |
142 | struct if_data *ifd; | |
9c859447 | 143 | int mtu = 0; |
7ba0088d A |
144 | |
145 | if (getifaddrs(&ifap) < 0) | |
146 | return(0); | |
147 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |
148 | if (strcmp(ifa->ifa_name, name) == 0) { | |
149 | ifd = ifa->ifa_data; | |
150 | if (ifd) | |
151 | mtu = ifd->ifi_mtu; | |
152 | break; | |
153 | } | |
154 | } | |
155 | freeifaddrs(ifap); | |
156 | ||
157 | #ifdef SIOCGIFMTU /* XXX: this ifdef may not be necessary */ | |
158 | if (mtu == 0) { | |
159 | struct ifreq ifr; | |
160 | int s; | |
161 | ||
162 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) | |
163 | return(0); | |
164 | ||
165 | ifr.ifr_addr.sa_family = AF_INET6; | |
e0b07f2d | 166 | strlcpy(ifr.ifr_name, name, |
7ba0088d A |
167 | sizeof(ifr.ifr_name)); |
168 | if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) { | |
169 | close(s); | |
170 | return(0); | |
171 | } | |
172 | close(s); | |
173 | ||
174 | mtu = ifr.ifr_mtu; | |
175 | } | |
176 | #endif | |
177 | ||
178 | return(mtu); | |
179 | } | |
180 | ||
181 | /* give interface index and its old flags, then new flags returned */ | |
182 | int | |
183 | if_getflags(int ifindex, int oifflags) | |
184 | { | |
185 | struct ifreq ifr; | |
186 | int s; | |
187 | ||
188 | if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | |
3219cf53 | 189 | errorlog("<%s> socket: %s", __func__, |
7ba0088d A |
190 | strerror(errno)); |
191 | return (oifflags & ~IFF_UP); | |
192 | } | |
193 | ||
194 | if_indextoname(ifindex, ifr.ifr_name); | |
195 | if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | |
3219cf53 | 196 | errorlog("<%s> ioctl:SIOCGIFFLAGS: failed for %s", |
7af5ce03 | 197 | __func__, ifr.ifr_name); |
7ba0088d A |
198 | close(s); |
199 | return (oifflags & ~IFF_UP); | |
200 | } | |
201 | close(s); | |
202 | return (ifr.ifr_flags); | |
203 | } | |
204 | ||
205 | #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) | |
206 | int | |
207 | lladdropt_length(struct sockaddr_dl *sdl) | |
208 | { | |
7af5ce03 A |
209 | switch (sdl->sdl_type) { |
210 | case IFT_ETHER: | |
211 | return(ROUNDUP8(ETHER_ADDR_LEN + 2)); | |
212 | default: | |
213 | return(0); | |
7ba0088d A |
214 | } |
215 | } | |
216 | ||
217 | void | |
218 | lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) | |
219 | { | |
220 | char *addr; | |
221 | ||
222 | ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ | |
223 | ||
7af5ce03 A |
224 | switch (sdl->sdl_type) { |
225 | case IFT_ETHER: | |
226 | ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; | |
227 | addr = (char *)(ndopt + 1); | |
228 | memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); | |
229 | break; | |
230 | default: | |
3219cf53 | 231 | errorlog("<%s> unsupported link type(%d)", |
7af5ce03 A |
232 | __func__, sdl->sdl_type); |
233 | exit(1); | |
7ba0088d A |
234 | } |
235 | ||
236 | return; | |
237 | } | |
238 | ||
239 | int | |
240 | rtbuf_len() | |
241 | { | |
242 | size_t len; | |
243 | ||
244 | int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0}; | |
245 | ||
246 | if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) | |
247 | return(-1); | |
248 | ||
249 | return(len); | |
250 | } | |
251 | ||
252 | #define FILTER_MATCH(type, filter) ((0x1 << type) & filter) | |
253 | #define SIN6(s) ((struct sockaddr_in6 *)(s)) | |
254 | #define SDL(s) ((struct sockaddr_dl *)(s)) | |
255 | char * | |
256 | get_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter) | |
257 | { | |
258 | struct rt_msghdr *rtm; | |
259 | struct ifa_msghdr *ifam; | |
260 | struct sockaddr *sa, *dst, *gw, *ifa, *rti_info[RTAX_MAX]; | |
261 | ||
262 | *lenp = 0; | |
263 | for (rtm = (struct rt_msghdr *)buf; | |
264 | rtm < (struct rt_msghdr *)lim; | |
265 | rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) { | |
266 | /* just for safety */ | |
267 | if (!rtm->rtm_msglen) { | |
3219cf53 | 268 | errorlog("<%s> rtm_msglen is 0 " |
7af5ce03 | 269 | "(buf=%p lim=%p rtm=%p)", __func__, |
7ba0088d A |
270 | buf, lim, rtm); |
271 | break; | |
272 | } | |
273 | if (FILTER_MATCH(rtm->rtm_type, filter) == 0) { | |
274 | continue; | |
275 | } | |
276 | ||
277 | switch (rtm->rtm_type) { | |
278 | case RTM_GET: | |
279 | case RTM_ADD: | |
280 | case RTM_DELETE: | |
281 | /* address related checks */ | |
282 | sa = (struct sockaddr *)(rtm + 1); | |
283 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |
284 | if ((dst = rti_info[RTAX_DST]) == NULL || | |
285 | dst->sa_family != AF_INET6) | |
286 | continue; | |
287 | ||
288 | if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) || | |
289 | IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr)) | |
290 | continue; | |
291 | ||
292 | if ((gw = rti_info[RTAX_GATEWAY]) == NULL || | |
293 | gw->sa_family != AF_LINK) | |
294 | continue; | |
295 | if (ifindex && SDL(gw)->sdl_index != ifindex) | |
296 | continue; | |
297 | ||
298 | if (rti_info[RTAX_NETMASK] == NULL) | |
299 | continue; | |
300 | ||
301 | /* found */ | |
302 | *lenp = rtm->rtm_msglen; | |
303 | return (char *)rtm; | |
304 | /* NOTREACHED */ | |
305 | case RTM_NEWADDR: | |
306 | case RTM_DELADDR: | |
307 | ifam = (struct ifa_msghdr *)rtm; | |
308 | ||
309 | /* address related checks */ | |
310 | sa = (struct sockaddr *)(ifam + 1); | |
311 | get_rtaddrs(ifam->ifam_addrs, sa, rti_info); | |
312 | if ((ifa = rti_info[RTAX_IFA]) == NULL || | |
313 | (ifa->sa_family != AF_INET && | |
314 | ifa->sa_family != AF_INET6)) | |
315 | continue; | |
316 | ||
317 | if (ifa->sa_family == AF_INET6 && | |
318 | (IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) || | |
319 | IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr))) | |
320 | continue; | |
321 | ||
322 | if (ifindex && ifam->ifam_index != ifindex) | |
323 | continue; | |
324 | ||
325 | /* found */ | |
326 | *lenp = ifam->ifam_msglen; | |
327 | return (char *)rtm; | |
328 | /* NOTREACHED */ | |
329 | case RTM_IFINFO: | |
330 | /* found */ | |
331 | *lenp = rtm->rtm_msglen; | |
332 | return (char *)rtm; | |
333 | /* NOTREACHED */ | |
334 | } | |
335 | } | |
336 | ||
337 | return (char *)rtm; | |
338 | } | |
339 | #undef FILTER_MATCH | |
340 | ||
341 | struct in6_addr * | |
342 | get_addr(char *buf) | |
343 | { | |
344 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
345 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | |
346 | ||
347 | sa = (struct sockaddr *)(rtm + 1); | |
348 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |
349 | ||
350 | return(&SIN6(rti_info[RTAX_DST])->sin6_addr); | |
351 | } | |
352 | ||
353 | int | |
354 | get_rtm_ifindex(char *buf) | |
355 | { | |
356 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
357 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | |
358 | ||
359 | sa = (struct sockaddr *)(rtm + 1); | |
360 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |
361 | ||
362 | return(((struct sockaddr_dl *)rti_info[RTAX_GATEWAY])->sdl_index); | |
363 | } | |
364 | ||
365 | int | |
366 | get_ifm_ifindex(char *buf) | |
367 | { | |
368 | struct if_msghdr *ifm = (struct if_msghdr *)buf; | |
369 | ||
370 | return ((int)ifm->ifm_index); | |
371 | } | |
372 | ||
373 | int | |
374 | get_ifam_ifindex(char *buf) | |
375 | { | |
376 | struct ifa_msghdr *ifam = (struct ifa_msghdr *)buf; | |
377 | ||
378 | return ((int)ifam->ifam_index); | |
379 | } | |
380 | ||
381 | int | |
382 | get_ifm_flags(char *buf) | |
383 | { | |
384 | struct if_msghdr *ifm = (struct if_msghdr *)buf; | |
385 | ||
386 | return (ifm->ifm_flags); | |
387 | } | |
388 | ||
389 | int | |
390 | get_prefixlen(char *buf) | |
391 | { | |
392 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
393 | struct sockaddr *sa, *rti_info[RTAX_MAX]; | |
394 | u_char *p, *lim; | |
395 | ||
396 | sa = (struct sockaddr *)(rtm + 1); | |
397 | get_rtaddrs(rtm->rtm_addrs, sa, rti_info); | |
398 | sa = rti_info[RTAX_NETMASK]; | |
399 | ||
400 | p = (u_char *)(&SIN6(sa)->sin6_addr); | |
401 | lim = (u_char *)sa + sa->sa_len; | |
402 | return prefixlen(p, lim); | |
403 | } | |
404 | ||
405 | int | |
406 | prefixlen(u_char *p, u_char *lim) | |
407 | { | |
408 | int masklen; | |
409 | ||
410 | for (masklen = 0; p < lim; p++) { | |
411 | switch (*p) { | |
412 | case 0xff: | |
413 | masklen += 8; | |
414 | break; | |
415 | case 0xfe: | |
416 | masklen += 7; | |
417 | break; | |
418 | case 0xfc: | |
419 | masklen += 6; | |
420 | break; | |
421 | case 0xf8: | |
422 | masklen += 5; | |
423 | break; | |
424 | case 0xf0: | |
425 | masklen += 4; | |
426 | break; | |
427 | case 0xe0: | |
428 | masklen += 3; | |
429 | break; | |
430 | case 0xc0: | |
431 | masklen += 2; | |
432 | break; | |
433 | case 0x80: | |
434 | masklen += 1; | |
435 | break; | |
436 | case 0x00: | |
437 | break; | |
438 | default: | |
439 | return(-1); | |
440 | } | |
441 | } | |
442 | ||
443 | return(masklen); | |
444 | } | |
445 | ||
446 | int | |
447 | rtmsg_type(char *buf) | |
448 | { | |
449 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
450 | ||
451 | return(rtm->rtm_type); | |
452 | } | |
453 | ||
454 | int | |
455 | rtmsg_len(char *buf) | |
456 | { | |
457 | struct rt_msghdr *rtm = (struct rt_msghdr *)buf; | |
458 | ||
459 | return(rtm->rtm_msglen); | |
460 | } | |
461 | ||
462 | int | |
463 | ifmsg_len(char *buf) | |
464 | { | |
465 | struct if_msghdr *ifm = (struct if_msghdr *)buf; | |
466 | ||
467 | return(ifm->ifm_msglen); | |
468 | } | |
469 | ||
470 | /* | |
471 | * alloc buffer and get if_msghdrs block from kernel, | |
472 | * and put them into the buffer | |
473 | */ | |
474 | static void | |
475 | get_iflist(char **buf, size_t *size) | |
476 | { | |
477 | int mib[6]; | |
478 | ||
479 | mib[0] = CTL_NET; | |
480 | mib[1] = PF_ROUTE; | |
481 | mib[2] = 0; | |
482 | mib[3] = AF_INET6; | |
483 | mib[4] = NET_RT_IFLIST; | |
484 | mib[5] = 0; | |
485 | ||
486 | if (sysctl(mib, 6, NULL, size, NULL, 0) < 0) { | |
3219cf53 | 487 | errorlog("<%s> sysctl: iflist size get failed", |
7af5ce03 | 488 | __func__); |
7ba0088d A |
489 | exit(1); |
490 | } | |
491 | if ((*buf = malloc(*size)) == NULL) { | |
3219cf53 | 492 | errorlog("<%s> malloc failed", __func__); |
7ba0088d A |
493 | exit(1); |
494 | } | |
495 | if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) { | |
3219cf53 | 496 | errorlog("<%s> sysctl: iflist get failed", |
7af5ce03 | 497 | __func__); |
7ba0088d A |
498 | exit(1); |
499 | } | |
500 | return; | |
501 | } | |
502 | ||
3219cf53 A |
503 | struct if_msghdr * |
504 | get_interface_entry(int if_index) | |
505 | { | |
506 | struct ifinfo *ifi = NULL; | |
507 | struct if_msghdr *ifm = NULL; | |
508 | ||
509 | TAILQ_FOREACH(ifi, &ifilist, ifi_next) { | |
510 | if (if_index == ifi->ifm->ifm_index) { | |
511 | ifm = ifi->ifm; | |
512 | break; | |
513 | } | |
514 | } | |
515 | return ifm; | |
516 | } | |
517 | ||
7ba0088d A |
518 | /* |
519 | * alloc buffer and parse if_msghdrs block passed as arg, | |
520 | * and init the buffer as list of pointers ot each of the if_msghdr. | |
521 | */ | |
522 | static void | |
3219cf53 | 523 | parse_iflist(char *buf, size_t bufsize) |
7ba0088d | 524 | { |
7ba0088d A |
525 | struct if_msghdr *ifm; |
526 | struct ifa_msghdr *ifam; | |
527 | char *lim; | |
528 | ||
7ba0088d A |
529 | lim = buf + bufsize; |
530 | for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) { | |
531 | if (ifm->ifm_msglen == 0) { | |
3219cf53 | 532 | errorlog("<%s> ifm_msglen is 0 " |
7af5ce03 | 533 | "(buf=%p lim=%p ifm=%p)", __func__, |
7ba0088d A |
534 | buf, lim, ifm); |
535 | return; | |
536 | } | |
537 | ||
538 | if (ifm->ifm_type == RTM_IFINFO) { | |
3219cf53 A |
539 | struct ifinfo *ifi = NULL; |
540 | ||
541 | if (get_interface_entry(ifm->ifm_index) != NULL) { | |
542 | debuglog("Interface entry is already present for " | |
543 | "interface index: %d. Skipping.", ifm->ifm_index); | |
544 | continue; | |
545 | } | |
546 | ||
547 | ELM_MALLOC(ifi, exit(1)); | |
548 | ifi->ifm = ifm; | |
549 | TAILQ_INSERT_TAIL(&ifilist, ifi, ifi_next); | |
7ba0088d | 550 | } else { |
3219cf53 | 551 | errorlog("out of sync parsing NET_RT_IFLIST\n" |
7ba0088d A |
552 | "expected %d, got %d\n msglen = %d\n" |
553 | "buf:%p, ifm:%p, lim:%p\n", | |
554 | RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen, | |
555 | buf, ifm, lim); | |
556 | exit (1); | |
557 | } | |
558 | for (ifam = (struct ifa_msghdr *) | |
559 | ((char *)ifm + ifm->ifm_msglen); | |
560 | ifam < (struct ifa_msghdr *)lim; | |
561 | ifam = (struct ifa_msghdr *) | |
562 | ((char *)ifam + ifam->ifam_msglen)) { | |
563 | /* just for safety */ | |
564 | if (!ifam->ifam_msglen) { | |
3219cf53 | 565 | errorlog("<%s> ifa_msglen is 0 " |
7af5ce03 | 566 | "(buf=%p lim=%p ifam=%p)", __func__, |
7ba0088d A |
567 | buf, lim, ifam); |
568 | return; | |
569 | } | |
570 | if (ifam->ifam_type != RTM_NEWADDR) | |
571 | break; | |
572 | } | |
573 | ifm = (struct if_msghdr *)ifam; | |
574 | } | |
575 | } | |
576 | ||
3219cf53 A |
577 | static void |
578 | purge_iflist() | |
579 | { | |
580 | struct ifinfo *ifi = NULL; | |
581 | if (!TAILQ_EMPTY(&ifilist)) { | |
582 | while ((ifi = TAILQ_FIRST(&ifilist)) != NULL) { | |
583 | TAILQ_REMOVE(&ifilist, ifi, ifi_next); | |
584 | free(ifi); | |
585 | } | |
586 | } | |
587 | } | |
588 | ||
7ba0088d A |
589 | void |
590 | init_iflist() | |
591 | { | |
3219cf53 A |
592 | purge_iflist(); |
593 | ||
7ba0088d A |
594 | if (ifblock) { |
595 | free(ifblock); | |
596 | ifblock_size = 0; | |
597 | } | |
3219cf53 | 598 | |
7ba0088d A |
599 | /* get iflist block from kernel */ |
600 | get_iflist(&ifblock, &ifblock_size); | |
601 | ||
602 | /* make list of pointers to each if_msghdr */ | |
3219cf53 | 603 | parse_iflist(ifblock, ifblock_size); |
7ba0088d | 604 | } |