146283Sdfr/* $NetBSD: if.c,v 1.20 2011/12/11 20:44:44 christos Exp $ */ 246283Sdfr/* $KAME: if.c,v 1.36 2004/11/30 22:32:01 suz Exp $ */ 346283Sdfr 446283Sdfr/* 546283Sdfr * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 646283Sdfr * All rights reserved. 746283Sdfr * 846283Sdfr * Redistribution and use in source and binary forms, with or without 946283Sdfr * modification, are permitted provided that the following conditions 1046283Sdfr * are met: 1146283Sdfr * 1. Redistributions of source code must retain the above copyright 1246283Sdfr * notice, this list of conditions and the following disclaimer. 1346283Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1446283Sdfr * notice, this list of conditions and the following disclaimer in the 1546283Sdfr * documentation and/or other materials provided with the distribution. 1646283Sdfr * 3. Neither the name of the project nor the names of its contributors 1746283Sdfr * may be used to endorse or promote products derived from this software 1846283Sdfr * without specific prior written permission. 1946283Sdfr * 2046283Sdfr * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2146283Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2246283Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2346283Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2446283Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2546283Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2646283Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2746283Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2846283Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2946283Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3046283Sdfr * SUCH DAMAGE. 3146283Sdfr */ 3246283Sdfr 3346283Sdfr#include <sys/param.h> 3446283Sdfr#include <sys/socket.h> 3546283Sdfr#include <sys/sysctl.h> 3646283Sdfr#include <sys/ioctl.h> 3746283Sdfr#include <net/if.h> 3846283Sdfr#include <net/if_types.h> 3946283Sdfr#include <ifaddrs.h> 4046283Sdfr#include <net/if_ether.h> 4146283Sdfr#include <net/route.h> 4246283Sdfr#include <net/if_dl.h> 4346283Sdfr#include <netinet/in.h> 4446283Sdfr#include <netinet/icmp6.h> 4546283Sdfr#include <unistd.h> 4646283Sdfr#include <errno.h> 4746283Sdfr#include <stdlib.h> 4846283Sdfr#include <string.h> 4946283Sdfr#include <syslog.h> 5046283Sdfr#include "rtadvd.h" 5146283Sdfr#include "if.h" 5246283Sdfr 5346283Sdfr#ifndef RT_ROUNDUP 5446283Sdfr#define RT_ROUNDUP(a) \ 5546283Sdfr ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 5646283Sdfr#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) 5746283Sdfr#endif 5846283Sdfr 5946283Sdfrstruct if_msghdr **iflist; 6046283Sdfrint iflist_init_ok; 6146283Sdfrsize_t ifblock_size; 6246283Sdfrchar *ifblock; 6346283Sdfr 6446283Sdfrstatic void get_iflist(char **buf, size_t *size); 6546283Sdfrstatic void parse_iflist(struct if_msghdr ***ifmlist_p, char *buf, 6646283Sdfr size_t bufsize); 6746283Sdfr 6846283Sdfrstatic void 6946283Sdfrget_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 7046283Sdfr{ 7146283Sdfr int i; 7246283Sdfr 7346283Sdfr for (i = 0; i < RTAX_MAX; i++) { 7446283Sdfr if (addrs & (1 << i)) { 7546283Sdfr rti_info[i] = sa; 7646283Sdfr RT_ADVANCE(sa, sa); 7746283Sdfr } 7846283Sdfr else 7946283Sdfr rti_info[i] = NULL; 8046283Sdfr } 8146283Sdfr} 8246283Sdfr 8346283Sdfrstruct sockaddr_dl * 8446283Sdfrif_nametosdl(const char *name) 8546283Sdfr{ 8646283Sdfr struct ifaddrs *ifap, *ifa; 8746283Sdfr struct sockaddr_dl *sdl; 8846283Sdfr 8946283Sdfr if (getifaddrs(&ifap) != 0) 9046283Sdfr return (NULL); 9146283Sdfr 9246283Sdfr for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 9346283Sdfr if (strcmp(ifa->ifa_name, name) != 0) 9446283Sdfr continue; 9546283Sdfr if (ifa->ifa_addr->sa_family != AF_LINK) 9646283Sdfr continue; 9746283Sdfr 9846283Sdfr sdl = malloc(ifa->ifa_addr->sa_len); 9946283Sdfr if (!sdl) 10046283Sdfr continue; /*XXX*/ 10146283Sdfr 10246283Sdfr memcpy(sdl, ifa->ifa_addr, ifa->ifa_addr->sa_len); 10346283Sdfr freeifaddrs(ifap); 10446283Sdfr return (sdl); 10546283Sdfr } 10646283Sdfr 10746283Sdfr freeifaddrs(ifap); 10846283Sdfr return (NULL); 10946283Sdfr} 11046283Sdfr 11146283Sdfrint 11246283Sdfrif_getmtu(const char *name) 11346283Sdfr{ 11446283Sdfr struct ifaddrs *ifap, *ifa; 11546283Sdfr struct if_data *ifd; 11646283Sdfr u_long mtu = 0; 11746283Sdfr 11846283Sdfr if (getifaddrs(&ifap) < 0) 11946283Sdfr return(0); 12046283Sdfr for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 12146283Sdfr if (strcmp(ifa->ifa_name, name) == 0) { 12246283Sdfr ifd = ifa->ifa_data; 12346283Sdfr if (ifd) 12446283Sdfr mtu = ifd->ifi_mtu; 12546283Sdfr break; 12646283Sdfr } 12746283Sdfr } 12846283Sdfr freeifaddrs(ifap); 12946283Sdfr 13046283Sdfr#ifdef SIOCGIFMTU /* XXX: this ifdef may not be necessary */ 13146283Sdfr if (mtu == 0) { 13246283Sdfr struct ifreq ifr; 13346283Sdfr int s; 13446283Sdfr 13546283Sdfr if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 13646283Sdfr return(0); 13746283Sdfr 13846283Sdfr ifr.ifr_addr.sa_family = AF_INET6; 13946283Sdfr strncpy(ifr.ifr_name, name, 14046283Sdfr sizeof(ifr.ifr_name)); 14146283Sdfr if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { 14246283Sdfr close(s); 14346283Sdfr return(0); 14446283Sdfr } 14546283Sdfr close(s); 14646283Sdfr 14746283Sdfr mtu = ifr.ifr_mtu; 14846283Sdfr } 14946283Sdfr#endif 15046283Sdfr 15146283Sdfr return(mtu); 15246283Sdfr} 15346283Sdfr 15446283Sdfr/* give interface index and its old flags, then new flags returned */ 15546283Sdfrint 15646283Sdfrif_getflags(int ifindex, int oifflags) 15746283Sdfr{ 15846283Sdfr struct ifreq ifr; 15946283Sdfr int s; 16046283Sdfr 16146283Sdfr if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 16246283Sdfr syslog(LOG_ERR, "<%s> socket: %s", __func__, 16346283Sdfr strerror(errno)); 16446283Sdfr return (oifflags & ~IFF_UP); 16546283Sdfr } 16646283Sdfr 16746283Sdfr if_indextoname(ifindex, ifr.ifr_name); 16846283Sdfr if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { 16946283Sdfr syslog(LOG_ERR, "<%s> ioctl:SIOCGIFFLAGS: failed for %s", 17046283Sdfr __func__, ifr.ifr_name); 17146283Sdfr close(s); 17246283Sdfr return (oifflags & ~IFF_UP); 17346283Sdfr } 17446283Sdfr close(s); 17546283Sdfr return (ifr.ifr_flags); 17646283Sdfr} 17746283Sdfr 17846283Sdfr#define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 17946283Sdfrint 18046283Sdfrlladdropt_length(struct sockaddr_dl *sdl) 18146283Sdfr{ 18246283Sdfr switch (sdl->sdl_type) { 18346283Sdfr case IFT_ETHER: 18446283Sdfr case IFT_FDDI: 18546283Sdfr return(ROUNDUP8(ETHER_ADDR_LEN + 2)); 18646283Sdfr default: 18746283Sdfr return(0); 18846283Sdfr } 18946283Sdfr} 19046283Sdfr 19146283Sdfrvoid 19246283Sdfrlladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 19346283Sdfr{ 19446283Sdfr char *addr; 19546283Sdfr 19646283Sdfr ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 19746283Sdfr 19846283Sdfr switch (sdl->sdl_type) { 19946283Sdfr case IFT_ETHER: 20046283Sdfr case IFT_FDDI: 20146283Sdfr ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 20246283Sdfr addr = (char *)(ndopt + 1); 20346283Sdfr memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 20446283Sdfr break; 20546283Sdfr default: 20646283Sdfr syslog(LOG_ERR, "<%s> unsupported link type(%d)", 20746283Sdfr __func__, sdl->sdl_type); 20846283Sdfr exit(1); 20946283Sdfr } 21046283Sdfr 21146283Sdfr return; 21246283Sdfr} 21346283Sdfr 21446283Sdfr#define FILTER_MATCH(type, filter) ((0x1 << type) & filter) 21546283Sdfr#define SIN6(s) ((struct sockaddr_in6 *)(s)) 21646283Sdfr#define SDL(s) ((struct sockaddr_dl *)(s)) 21746283Sdfrchar * 21846283Sdfrget_next_msg(char *buf, char *lim, int ifindex, size_t *lenp, int filter) 21946283Sdfr{ 22046283Sdfr struct rt_msghdr *rtm; 22146283Sdfr struct ifa_msghdr *ifam; 22246283Sdfr struct sockaddr *sa, *dst, *gw, *ifa, *rti_info[RTAX_MAX]; 22346283Sdfr 22446283Sdfr *lenp = 0; 22546283Sdfr for (rtm = (struct rt_msghdr *)buf; 22646283Sdfr rtm < (struct rt_msghdr *)lim; 22746283Sdfr rtm = (struct rt_msghdr *)(((char *)rtm) + rtm->rtm_msglen)) { 22846283Sdfr /* just for safety */ 22946283Sdfr if (!rtm->rtm_msglen) { 23046283Sdfr syslog(LOG_WARNING, "<%s> rtm_msglen is 0 " 23146283Sdfr "(buf=%p lim=%p rtm=%p)", __func__, 23246283Sdfr buf, lim, rtm); 23346283Sdfr break; 23446283Sdfr } 23546283Sdfr if (FILTER_MATCH(rtm->rtm_type, filter) == 0) { 23646283Sdfr continue; 23746283Sdfr } 23846283Sdfr 23946283Sdfr switch (rtm->rtm_type) { 24046283Sdfr case RTM_GET: 24146283Sdfr case RTM_ADD: 24246283Sdfr case RTM_DELETE: 24346283Sdfr /* address related checks */ 24446283Sdfr sa = (struct sockaddr *)(rtm + 1); 24546283Sdfr get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 24646283Sdfr if ((dst = rti_info[RTAX_DST]) == NULL || 24746283Sdfr dst->sa_family != AF_INET6) 24846283Sdfr continue; 24946283Sdfr 25046283Sdfr if (IN6_IS_ADDR_LINKLOCAL(&SIN6(dst)->sin6_addr) || 25146283Sdfr IN6_IS_ADDR_MULTICAST(&SIN6(dst)->sin6_addr)) 25246283Sdfr continue; 25346283Sdfr 25446283Sdfr if ((gw = rti_info[RTAX_GATEWAY]) == NULL || 25546283Sdfr gw->sa_family != AF_LINK) 25646283Sdfr continue; 25746283Sdfr if (ifindex && SDL(gw)->sdl_index != ifindex) 25846283Sdfr continue; 25946283Sdfr 26046283Sdfr if (rti_info[RTAX_NETMASK] == NULL) 26146283Sdfr continue; 262130803Smarcel 26346283Sdfr /* found */ 26446283Sdfr *lenp = rtm->rtm_msglen; 26546283Sdfr return (char *)rtm; 26646283Sdfr /* NOTREACHED */ 26746283Sdfr case RTM_NEWADDR: 26846283Sdfr case RTM_DELADDR: 26946283Sdfr ifam = (struct ifa_msghdr *)rtm; 27046283Sdfr 27146283Sdfr /* address related checks */ 27246283Sdfr sa = (struct sockaddr *)(ifam + 1); 27346283Sdfr get_rtaddrs(ifam->ifam_addrs, sa, rti_info); 27446283Sdfr if ((ifa = rti_info[RTAX_IFA]) == NULL || 27546283Sdfr (ifa->sa_family != AF_INET && 27646283Sdfr ifa->sa_family != AF_INET6)) 27746283Sdfr continue; 27846283Sdfr 27946283Sdfr if (ifa->sa_family == AF_INET6 && 28046283Sdfr (IN6_IS_ADDR_LINKLOCAL(&SIN6(ifa)->sin6_addr) || 28146283Sdfr IN6_IS_ADDR_MULTICAST(&SIN6(ifa)->sin6_addr))) 28246283Sdfr continue; 28346283Sdfr 28446283Sdfr if (ifindex && ifam->ifam_index != ifindex) 28546283Sdfr continue; 28646283Sdfr 28746283Sdfr /* found */ 28846283Sdfr *lenp = ifam->ifam_msglen; 28946283Sdfr return (char *)rtm; 29046283Sdfr /* NOTREACHED */ 29146283Sdfr case RTM_IFINFO: 29246283Sdfr /* found */ 29346283Sdfr *lenp = rtm->rtm_msglen; 29446283Sdfr return (char *)rtm; 29546283Sdfr /* NOTREACHED */ 29646283Sdfr } 29746283Sdfr } 29846283Sdfr 29946283Sdfr return (char *)rtm; 30046283Sdfr} 30146283Sdfr#undef FILTER_MATCH 30246283Sdfr 30346283Sdfrstruct in6_addr * 30446283Sdfrget_addr(char *buf) 30546283Sdfr{ 30646283Sdfr struct rt_msghdr *rtm = (struct rt_msghdr *)buf; 30746283Sdfr struct sockaddr *sa, *rti_info[RTAX_MAX]; 30846283Sdfr 30946283Sdfr sa = (struct sockaddr *)(rtm + 1); 31046283Sdfr get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 31146283Sdfr 31246283Sdfr return(&SIN6(rti_info[RTAX_DST])->sin6_addr); 31346283Sdfr} 31446283Sdfr 31546283Sdfrint 31646283Sdfrget_rtm_ifindex(char *buf) 31746283Sdfr{ 31846283Sdfr struct rt_msghdr *rtm = (struct rt_msghdr *)buf; 31946283Sdfr struct sockaddr *sa, *rti_info[RTAX_MAX]; 32046283Sdfr 32146283Sdfr sa = (struct sockaddr *)(rtm + 1); 32246283Sdfr get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 32346283Sdfr 32446283Sdfr return(((struct sockaddr_dl *)rti_info[RTAX_GATEWAY])->sdl_index); 32546283Sdfr} 32646283Sdfr 32746283Sdfrint 32846283Sdfrget_ifm_ifindex(char *buf) 32946283Sdfr{ 33046283Sdfr struct if_msghdr *ifm = (struct if_msghdr *)buf; 33146283Sdfr 33246283Sdfr return ((int)ifm->ifm_index); 33346283Sdfr} 33446283Sdfr 33546283Sdfrint 33646283Sdfrget_ifam_ifindex(char *buf) 33746283Sdfr{ 33846283Sdfr struct ifa_msghdr *ifam = (struct ifa_msghdr *)buf; 33946283Sdfr 34046283Sdfr return ((int)ifam->ifam_index); 34146283Sdfr} 34246283Sdfr 34346283Sdfrint 34446283Sdfrget_ifm_flags(char *buf) 34546283Sdfr{ 34646283Sdfr struct if_msghdr *ifm = (struct if_msghdr *)buf; 34746283Sdfr 34846283Sdfr return (ifm->ifm_flags); 34946283Sdfr} 35046283Sdfr 35146283Sdfrint 35246283Sdfrget_prefixlen(char *buf) 35346283Sdfr{ 35446283Sdfr struct rt_msghdr *rtm = (struct rt_msghdr *)buf; 35546283Sdfr struct sockaddr *sa, *rti_info[RTAX_MAX]; 35646283Sdfr unsigned char *p, *lim; 35746283Sdfr 35846283Sdfr sa = (struct sockaddr *)(rtm + 1); 35946283Sdfr get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 36046283Sdfr sa = rti_info[RTAX_NETMASK]; 36146283Sdfr 36246283Sdfr p = (unsigned char *)(&SIN6(sa)->sin6_addr); 36346283Sdfr lim = (unsigned char *)sa + sa->sa_len; 36446283Sdfr return prefixlen(p, lim); 36546283Sdfr} 36646283Sdfr 36746283Sdfrint 36846283Sdfrprefixlen(const unsigned char *p, const unsigned char *lim) 36946283Sdfr{ 37046283Sdfr int masklen; 37146283Sdfr 37246283Sdfr for (masklen = 0; p < lim; p++) { 37346283Sdfr switch (*p) { 37446283Sdfr case 0xff: 37546283Sdfr masklen += 8; 37646283Sdfr break; 37746283Sdfr case 0xfe: 37846283Sdfr masklen += 7; 37946283Sdfr break; 38046283Sdfr case 0xfc: 38146283Sdfr masklen += 6; 38246283Sdfr break; 38346283Sdfr case 0xf8: 38446283Sdfr masklen += 5; 38546283Sdfr break; 38646283Sdfr case 0xf0: 38746283Sdfr masklen += 4; 38846283Sdfr break; 38946283Sdfr case 0xe0: 39046283Sdfr masklen += 3; 39146283Sdfr break; 39246283Sdfr case 0xc0: 39346283Sdfr masklen += 2; 39446283Sdfr break; 39546283Sdfr case 0x80: 39646283Sdfr masklen += 1; 39746283Sdfr break; 39846283Sdfr case 0x00: 39946283Sdfr break; 40046283Sdfr default: 40146283Sdfr return(-1); 40246283Sdfr } 40346283Sdfr } 40446283Sdfr 40546283Sdfr return(masklen); 40646283Sdfr} 40746283Sdfr 40846283Sdfrint 40946283Sdfrrtmsg_type(char *buf) 41046283Sdfr{ 41146283Sdfr struct rt_msghdr *rtm = (struct rt_msghdr *)buf; 41246283Sdfr 41346283Sdfr return(rtm->rtm_type); 41446283Sdfr} 41546283Sdfr 41646283Sdfrint 41746283Sdfrrtmsg_len(char *buf) 41846283Sdfr{ 41946283Sdfr struct rt_msghdr *rtm = (struct rt_msghdr *)buf; 42046283Sdfr 42146283Sdfr return(rtm->rtm_msglen); 42246283Sdfr} 42346283Sdfr 42446283Sdfrint 42546283Sdfrifmsg_len(char *buf) 42646283Sdfr{ 42746283Sdfr struct if_msghdr *ifm = (struct if_msghdr *)buf; 42846283Sdfr 42946283Sdfr return(ifm->ifm_msglen); 43046283Sdfr} 43146283Sdfr 43246283Sdfr/* 43346283Sdfr * alloc buffer and get if_msghdrs block from kernel, 43446283Sdfr * and put them into the buffer 43546283Sdfr */ 43646283Sdfrstatic void 43746283Sdfrget_iflist(char **buf, size_t *size) 43846283Sdfr{ 43946283Sdfr int mib[6]; 44046283Sdfr 44146283Sdfr mib[0] = CTL_NET; 44246283Sdfr mib[1] = PF_ROUTE; 44346283Sdfr mib[2] = 0; 44446283Sdfr mib[3] = AF_INET6; 44546283Sdfr mib[4] = NET_RT_IFLIST; 44646283Sdfr mib[5] = 0; 44746283Sdfr 44846283Sdfr if (sysctl(mib, 6, NULL, size, NULL, 0) < 0) { 44946283Sdfr syslog(LOG_ERR, "<%s> sysctl: iflist size get failed", 45046283Sdfr __func__); 45146283Sdfr exit(1); 45246283Sdfr } 45346283Sdfr if ((*buf = malloc(*size)) == NULL) { 45446283Sdfr syslog(LOG_ERR, "<%s> malloc failed", __func__); 45546283Sdfr exit(1); 45646283Sdfr } 45746283Sdfr if (sysctl(mib, 6, *buf, size, NULL, 0) < 0) { 45846283Sdfr syslog(LOG_ERR, "<%s> sysctl: iflist get failed", 45946283Sdfr __func__); 46046283Sdfr exit(1); 46146283Sdfr } 46246283Sdfr return; 46346283Sdfr} 46446283Sdfr 46546283Sdfr/* 46646283Sdfr * alloc buffer and parse if_msghdrs block passed as arg, 46746283Sdfr * and init the buffer as list of pointers ot each of the if_msghdr. 46846283Sdfr */ 46946283Sdfrstatic void 47046283Sdfrparse_iflist(struct if_msghdr ***ifmlist_p, char *buf, size_t bufsize) 47146283Sdfr{ 47246283Sdfr int iflentry_size, malloc_size; 47346283Sdfr struct if_msghdr *ifm; 47446283Sdfr struct ifa_msghdr *ifam; 47546283Sdfr char *lim; 47646283Sdfr 47746283Sdfr /* 47846283Sdfr * Estimate least size of an iflist entry, to be obtained from kernel. 47946283Sdfr * Should add sizeof(sockaddr) ?? 48046283Sdfr */ 48146283Sdfr iflentry_size = sizeof(struct if_msghdr); 48246283Sdfr /* roughly estimate max list size of pointers to each if_msghdr */ 48346283Sdfr malloc_size = (bufsize/iflentry_size) * sizeof(void *); 48446283Sdfr if ((*ifmlist_p = (struct if_msghdr **)malloc(malloc_size)) == NULL) { 48546283Sdfr syslog(LOG_ERR, "<%s> malloc failed", __func__); 48646283Sdfr exit(1); 48746283Sdfr } 48846283Sdfr 48946283Sdfr lim = buf + bufsize; 49046283Sdfr for (ifm = (struct if_msghdr *)buf; ifm < (struct if_msghdr *)lim;) { 49146283Sdfr if (ifm->ifm_msglen == 0) { 49246283Sdfr syslog(LOG_WARNING, "<%s> ifm_msglen is 0 " 49346283Sdfr "(buf=%p lim=%p ifm=%p)", __func__, 49446283Sdfr buf, lim, ifm); 49546283Sdfr return; 49646283Sdfr } 49798944Sobrien 49846283Sdfr if (ifm->ifm_type == RTM_IFINFO) { 49946283Sdfr (*ifmlist_p)[ifm->ifm_index] = ifm; 50046283Sdfr } else { 50146283Sdfr syslog(LOG_ERR, "out of sync parsing NET_RT_IFLIST\n" 50246283Sdfr "expected %d, got %d\n msglen = %d\n" 50346283Sdfr "buf:%p, ifm:%p, lim:%p\n", 50446283Sdfr RTM_IFINFO, ifm->ifm_type, ifm->ifm_msglen, 50546283Sdfr buf, ifm, lim); 50646283Sdfr exit (1); 50746283Sdfr } 50846283Sdfr for (ifam = (struct ifa_msghdr *) 50946283Sdfr ((char *)ifm + ifm->ifm_msglen); 51046283Sdfr ifam < (struct ifa_msghdr *)lim; 51146283Sdfr ifam = (struct ifa_msghdr *) 51246283Sdfr ((char *)ifam + ifam->ifam_msglen)) { 51346283Sdfr /* just for safety */ 51446283Sdfr if (!ifam->ifam_msglen) { 51546283Sdfr syslog(LOG_WARNING, "<%s> ifa_msglen is 0 " 51646283Sdfr "(buf=%p lim=%p ifam=%p)", __func__, 51746283Sdfr buf, lim, ifam); 51846283Sdfr return; 51946283Sdfr } 52046283Sdfr if (ifam->ifam_type != RTM_NEWADDR) 52146283Sdfr break; 52246283Sdfr } 52346283Sdfr ifm = (struct if_msghdr *)ifam; 52446283Sdfr } 52546283Sdfr} 52646283Sdfr 52746283Sdfrvoid 52846283Sdfrinit_iflist() 52946283Sdfr{ 53046283Sdfr if (ifblock) { 53146283Sdfr free(ifblock); 53246283Sdfr ifblock_size = 0; 53346283Sdfr } 53446283Sdfr if (iflist) 53546283Sdfr free(iflist); 53646283Sdfr /* get iflist block from kernel */ 53746283Sdfr get_iflist(&ifblock, &ifblock_size); 53846283Sdfr 53946283Sdfr /* make list of pointers to each if_msghdr */ 54046283Sdfr parse_iflist(&iflist, ifblock, ifblock_size); 54146283Sdfr} 54246283Sdfr