1131033d5SHajimu UMEMOTO /* $KAME: if.c,v 1.26 2003/05/15 14:38:56 itojun Exp $ */ 2804c83d4SKris Kennaway 37d56d374SYoshinobu Inoue /* 47d56d374SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 57d56d374SYoshinobu Inoue * All rights reserved. 67d56d374SYoshinobu Inoue * 77d56d374SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 87d56d374SYoshinobu Inoue * modification, are permitted provided that the following conditions 97d56d374SYoshinobu Inoue * are met: 107d56d374SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 117d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 127d56d374SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 137d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 147d56d374SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 157d56d374SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 167d56d374SYoshinobu Inoue * may be used to endorse or promote products derived from this software 177d56d374SYoshinobu Inoue * without specific prior written permission. 187d56d374SYoshinobu Inoue * 197d56d374SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 207d56d374SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 217d56d374SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 227d56d374SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 237d56d374SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 247d56d374SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 257d56d374SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 267d56d374SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 277d56d374SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 287d56d374SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 297d56d374SYoshinobu Inoue * SUCH DAMAGE. 307d56d374SYoshinobu Inoue * 317d56d374SYoshinobu Inoue * $FreeBSD$ 327d56d374SYoshinobu Inoue */ 337d56d374SYoshinobu Inoue 347d56d374SYoshinobu Inoue #include <sys/param.h> 357d56d374SYoshinobu Inoue #include <sys/socket.h> 367d56d374SYoshinobu Inoue #include <sys/sysctl.h> 377d56d374SYoshinobu Inoue #include <sys/ioctl.h> 38804c83d4SKris Kennaway #include <sys/queue.h> 397d56d374SYoshinobu Inoue 407d56d374SYoshinobu Inoue #include <net/if.h> 417d56d374SYoshinobu Inoue #include <net/if_var.h> 427d56d374SYoshinobu Inoue #include <net/if_types.h> 437d56d374SYoshinobu Inoue #include <net/route.h> 447d56d374SYoshinobu Inoue #include <net/if_dl.h> 457d56d374SYoshinobu Inoue #include <net/if_media.h> 467d56d374SYoshinobu Inoue #include <net/ethernet.h> 477d56d374SYoshinobu Inoue #include <netinet/in.h> 487d56d374SYoshinobu Inoue #include <netinet/icmp6.h> 497d56d374SYoshinobu Inoue 507d56d374SYoshinobu Inoue #include <netinet6/in6_var.h> 517d56d374SYoshinobu Inoue 527d56d374SYoshinobu Inoue #include <stdio.h> 537d56d374SYoshinobu Inoue #include <unistd.h> 547d56d374SYoshinobu Inoue #include <stdlib.h> 557d56d374SYoshinobu Inoue #include <syslog.h> 567d56d374SYoshinobu Inoue #include <string.h> 577d56d374SYoshinobu Inoue #include <fcntl.h> 587d56d374SYoshinobu Inoue #include <errno.h> 597d56d374SYoshinobu Inoue #include <limits.h> 60259df286SKris Kennaway #include <ifaddrs.h> 617d56d374SYoshinobu Inoue #include "rtsold.h" 627d56d374SYoshinobu Inoue 63259df286SKris Kennaway extern int rssock; 647d56d374SYoshinobu Inoue static int ifsock; 657d56d374SYoshinobu Inoue 66131033d5SHajimu UMEMOTO static int get_llflag __P((const char *)); 67131033d5SHajimu UMEMOTO static void get_rtaddrs __P((int, struct sockaddr *, struct sockaddr **)); 687d56d374SYoshinobu Inoue 697d56d374SYoshinobu Inoue int 707d56d374SYoshinobu Inoue ifinit() 717d56d374SYoshinobu Inoue { 72259df286SKris Kennaway ifsock = rssock; 737d56d374SYoshinobu Inoue 747d56d374SYoshinobu Inoue return(0); 757d56d374SYoshinobu Inoue } 767d56d374SYoshinobu Inoue 777d56d374SYoshinobu Inoue int 787d56d374SYoshinobu Inoue interface_up(char *name) 797d56d374SYoshinobu Inoue { 807d56d374SYoshinobu Inoue struct ifreq ifr; 81259df286SKris Kennaway int llflag; 827d56d374SYoshinobu Inoue 837d56d374SYoshinobu Inoue strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 847d56d374SYoshinobu Inoue 857d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 861533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s", 877d56d374SYoshinobu Inoue strerror(errno)); 887d56d374SYoshinobu Inoue return(-1); 897d56d374SYoshinobu Inoue } 907d56d374SYoshinobu Inoue if (!(ifr.ifr_flags & IFF_UP)) { 917d56d374SYoshinobu Inoue ifr.ifr_flags |= IFF_UP; 92fa19f9beSHajimu UMEMOTO if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 931533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 947d56d374SYoshinobu Inoue "ioctl(SIOCSIFFLAGS): %s", strerror(errno)); 957d56d374SYoshinobu Inoue return(-1); 967d56d374SYoshinobu Inoue } 977d56d374SYoshinobu Inoue 981533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name); 997d56d374SYoshinobu Inoue 100259df286SKris Kennaway llflag = get_llflag(name); 101259df286SKris Kennaway if (llflag < 0) { 1021533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, 103259df286SKris Kennaway "get_llflag() failed, anyway I'll try"); 1047d56d374SYoshinobu Inoue return 0; 1057d56d374SYoshinobu Inoue } 1067d56d374SYoshinobu Inoue 107259df286SKris Kennaway if (!(llflag & IN6_IFF_NOTREADY)) { 108fa19f9beSHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is ready", name); 1097d56d374SYoshinobu Inoue return(0); 110259df286SKris Kennaway } else { 111259df286SKris Kennaway if (llflag & IN6_IFF_TENTATIVE) { 1121533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is tentative", 1137d56d374SYoshinobu Inoue name); 1147d56d374SYoshinobu Inoue return IFS_TENTATIVE; 1157d56d374SYoshinobu Inoue } 116259df286SKris Kennaway if (llflag & IN6_IFF_DUPLICATED) 1171533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is duplicated", 1187d56d374SYoshinobu Inoue name); 1197d56d374SYoshinobu Inoue return -1; 1207d56d374SYoshinobu Inoue } 1217d56d374SYoshinobu Inoue } 1227d56d374SYoshinobu Inoue 1237d56d374SYoshinobu Inoue int 1247d56d374SYoshinobu Inoue interface_status(struct ifinfo *ifinfo) 1257d56d374SYoshinobu Inoue { 1267d56d374SYoshinobu Inoue char *ifname = ifinfo->ifname; 1277d56d374SYoshinobu Inoue struct ifreq ifr; 1287d56d374SYoshinobu Inoue struct ifmediareq ifmr; 1297d56d374SYoshinobu Inoue 1307d56d374SYoshinobu Inoue /* get interface flags */ 1317d56d374SYoshinobu Inoue memset(&ifr, 0, sizeof(ifr)); 1327d56d374SYoshinobu Inoue strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1337d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 1341533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s", 1357d56d374SYoshinobu Inoue ifname, strerror(errno)); 1367d56d374SYoshinobu Inoue return(-1); 1377d56d374SYoshinobu Inoue } 1387d56d374SYoshinobu Inoue /* 1397d56d374SYoshinobu Inoue * if one of UP and RUNNING flags is dropped, 1407d56d374SYoshinobu Inoue * the interface is not active. 1417d56d374SYoshinobu Inoue */ 1427d56d374SYoshinobu Inoue if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 1437d56d374SYoshinobu Inoue goto inactive; 1447d56d374SYoshinobu Inoue } 1457d56d374SYoshinobu Inoue 1467d56d374SYoshinobu Inoue /* Next, check carrier on the interface, if possible */ 1477d56d374SYoshinobu Inoue if (!ifinfo->mediareqok) 1487d56d374SYoshinobu Inoue goto active; 1497d56d374SYoshinobu Inoue memset(&ifmr, 0, sizeof(ifmr)); 1507d56d374SYoshinobu Inoue strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 1517d56d374SYoshinobu Inoue 1527d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1537d56d374SYoshinobu Inoue if (errno != EINVAL) { 1541533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, 1557d56d374SYoshinobu Inoue "ioctl(SIOCGIFMEDIA) on %s: %s", 1567d56d374SYoshinobu Inoue ifname, strerror(errno)); 1577d56d374SYoshinobu Inoue return(-1); 1587d56d374SYoshinobu Inoue } 1597d56d374SYoshinobu Inoue /* 1607d56d374SYoshinobu Inoue * EINVAL simply means that the interface does not support 1617d56d374SYoshinobu Inoue * the SIOCGIFMEDIA ioctl. We regard it alive. 1627d56d374SYoshinobu Inoue */ 1637d56d374SYoshinobu Inoue ifinfo->mediareqok = 0; 1647d56d374SYoshinobu Inoue goto active; 1657d56d374SYoshinobu Inoue } 1667d56d374SYoshinobu Inoue 1677d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_AVALID) { 1687d56d374SYoshinobu Inoue switch (ifmr.ifm_active & IFM_NMASK) { 1697d56d374SYoshinobu Inoue case IFM_ETHER: 170131033d5SHajimu UMEMOTO case IFM_IEEE80211: 1717d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_ACTIVE) 1727d56d374SYoshinobu Inoue goto active; 1737d56d374SYoshinobu Inoue else 1747d56d374SYoshinobu Inoue goto inactive; 1757d56d374SYoshinobu Inoue break; 1767d56d374SYoshinobu Inoue default: 1777d56d374SYoshinobu Inoue goto inactive; 1787d56d374SYoshinobu Inoue } 1797d56d374SYoshinobu Inoue } 1807d56d374SYoshinobu Inoue 1817d56d374SYoshinobu Inoue inactive: 1827d56d374SYoshinobu Inoue return(0); 1837d56d374SYoshinobu Inoue 1847d56d374SYoshinobu Inoue active: 1857d56d374SYoshinobu Inoue return(1); 1867d56d374SYoshinobu Inoue } 1877d56d374SYoshinobu Inoue 1887d56d374SYoshinobu Inoue #define ROUNDUP(a, size) \ 1897d56d374SYoshinobu Inoue (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 1907d56d374SYoshinobu Inoue 1917d56d374SYoshinobu Inoue #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 1927d56d374SYoshinobu Inoue ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 193fa19f9beSHajimu UMEMOTO sizeof(u_long)) : sizeof(u_long))) 1947d56d374SYoshinobu Inoue #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 1957d56d374SYoshinobu Inoue 1967d56d374SYoshinobu Inoue int 1977d56d374SYoshinobu Inoue lladdropt_length(struct sockaddr_dl *sdl) 1987d56d374SYoshinobu Inoue { 1997d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2007d56d374SYoshinobu Inoue case IFT_ETHER: 20133841545SHajimu UMEMOTO #ifdef IFT_IEEE80211 20233841545SHajimu UMEMOTO case IFT_IEEE80211: 20333841545SHajimu UMEMOTO #endif 2047d56d374SYoshinobu Inoue return(ROUNDUP8(ETHER_ADDR_LEN + 2)); 2057d56d374SYoshinobu Inoue default: 2067d56d374SYoshinobu Inoue return(0); 2077d56d374SYoshinobu Inoue } 2087d56d374SYoshinobu Inoue } 2097d56d374SYoshinobu Inoue 2107d56d374SYoshinobu Inoue void 2117d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2127d56d374SYoshinobu Inoue { 2137d56d374SYoshinobu Inoue char *addr; 2147d56d374SYoshinobu Inoue 2157d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2167d56d374SYoshinobu Inoue 2177d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2187d56d374SYoshinobu Inoue case IFT_ETHER: 21933841545SHajimu UMEMOTO #ifdef IFT_IEEE80211 22033841545SHajimu UMEMOTO case IFT_IEEE80211: 22133841545SHajimu UMEMOTO #endif 2227d56d374SYoshinobu Inoue ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 2237d56d374SYoshinobu Inoue addr = (char *)(ndopt + 1); 2247d56d374SYoshinobu Inoue memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 2257d56d374SYoshinobu Inoue break; 2267d56d374SYoshinobu Inoue default: 2271533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 2287d56d374SYoshinobu Inoue "unsupported link type(%d)", sdl->sdl_type); 2297d56d374SYoshinobu Inoue exit(1); 2307d56d374SYoshinobu Inoue } 2317d56d374SYoshinobu Inoue 2327d56d374SYoshinobu Inoue return; 2337d56d374SYoshinobu Inoue } 2347d56d374SYoshinobu Inoue 2357d56d374SYoshinobu Inoue struct sockaddr_dl * 2367d56d374SYoshinobu Inoue if_nametosdl(char *name) 2377d56d374SYoshinobu Inoue { 2387d56d374SYoshinobu Inoue int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 2397d56d374SYoshinobu Inoue char *buf, *next, *lim; 2407d56d374SYoshinobu Inoue size_t len; 2417d56d374SYoshinobu Inoue struct if_msghdr *ifm; 2427d56d374SYoshinobu Inoue struct sockaddr *sa, *rti_info[RTAX_MAX]; 2437d56d374SYoshinobu Inoue struct sockaddr_dl *sdl = NULL, *ret_sdl; 2447d56d374SYoshinobu Inoue 2457d56d374SYoshinobu Inoue if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 2467d56d374SYoshinobu Inoue return(NULL); 2477d56d374SYoshinobu Inoue if ((buf = malloc(len)) == NULL) 2487d56d374SYoshinobu Inoue return(NULL); 2497d56d374SYoshinobu Inoue if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 2507d56d374SYoshinobu Inoue free(buf); 2517d56d374SYoshinobu Inoue return(NULL); 2527d56d374SYoshinobu Inoue } 2537d56d374SYoshinobu Inoue 2547d56d374SYoshinobu Inoue lim = buf + len; 2557d56d374SYoshinobu Inoue for (next = buf; next < lim; next += ifm->ifm_msglen) { 2567d56d374SYoshinobu Inoue ifm = (struct if_msghdr *)next; 2577d56d374SYoshinobu Inoue if (ifm->ifm_type == RTM_IFINFO) { 2587d56d374SYoshinobu Inoue sa = (struct sockaddr *)(ifm + 1); 2597d56d374SYoshinobu Inoue get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 2607d56d374SYoshinobu Inoue if ((sa = rti_info[RTAX_IFP]) != NULL) { 2617d56d374SYoshinobu Inoue if (sa->sa_family == AF_LINK) { 2627d56d374SYoshinobu Inoue sdl = (struct sockaddr_dl *)sa; 263259df286SKris Kennaway if (strlen(name) != sdl->sdl_nlen) 264259df286SKris Kennaway continue; /* not same len */ 2657d56d374SYoshinobu Inoue if (strncmp(&sdl->sdl_data[0], 2667d56d374SYoshinobu Inoue name, 2677d56d374SYoshinobu Inoue sdl->sdl_nlen) == 0) { 2687d56d374SYoshinobu Inoue break; 2697d56d374SYoshinobu Inoue } 2707d56d374SYoshinobu Inoue } 2717d56d374SYoshinobu Inoue } 2727d56d374SYoshinobu Inoue } 2737d56d374SYoshinobu Inoue } 2747d56d374SYoshinobu Inoue if (next == lim) { 2757d56d374SYoshinobu Inoue /* search failed */ 2767d56d374SYoshinobu Inoue free(buf); 2777d56d374SYoshinobu Inoue return(NULL); 2787d56d374SYoshinobu Inoue } 2797d56d374SYoshinobu Inoue 2807d56d374SYoshinobu Inoue if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) 2817d56d374SYoshinobu Inoue return(NULL); 2827d56d374SYoshinobu Inoue memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); 2837d56d374SYoshinobu Inoue 28433841545SHajimu UMEMOTO free(buf); 2857d56d374SYoshinobu Inoue return(ret_sdl); 2867d56d374SYoshinobu Inoue } 2877d56d374SYoshinobu Inoue 2887d56d374SYoshinobu Inoue int 2897d56d374SYoshinobu Inoue getinet6sysctl(int code) 2907d56d374SYoshinobu Inoue { 2917d56d374SYoshinobu Inoue int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 2927d56d374SYoshinobu Inoue int value; 2937d56d374SYoshinobu Inoue size_t size; 2947d56d374SYoshinobu Inoue 2957d56d374SYoshinobu Inoue mib[3] = code; 2967d56d374SYoshinobu Inoue size = sizeof(value); 2977d56d374SYoshinobu Inoue if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) < 0) 2987d56d374SYoshinobu Inoue return -1; 2997d56d374SYoshinobu Inoue else 3007d56d374SYoshinobu Inoue return value; 3017d56d374SYoshinobu Inoue } 3027d56d374SYoshinobu Inoue 3037d56d374SYoshinobu Inoue /*------------------------------------------------------------*/ 3047d56d374SYoshinobu Inoue 305259df286SKris Kennaway /* get ia6_flags for link-local addr on if. returns -1 on error. */ 3067d56d374SYoshinobu Inoue static int 307259df286SKris Kennaway get_llflag(const char *name) 3087d56d374SYoshinobu Inoue { 309259df286SKris Kennaway struct ifaddrs *ifap, *ifa; 310259df286SKris Kennaway struct in6_ifreq ifr6; 311259df286SKris Kennaway struct sockaddr_in6 *sin6; 312259df286SKris Kennaway int s; 3137d56d374SYoshinobu Inoue 314259df286SKris Kennaway if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { 3151533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s", 316259df286SKris Kennaway strerror(errno)); 3177d56d374SYoshinobu Inoue exit(1); 3187d56d374SYoshinobu Inoue } 319259df286SKris Kennaway if (getifaddrs(&ifap) != 0) { 320fa19f9beSHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "getifaddrs: %s", 321259df286SKris Kennaway strerror(errno)); 322259df286SKris Kennaway exit(1); 3237d56d374SYoshinobu Inoue } 3247d56d374SYoshinobu Inoue 325259df286SKris Kennaway for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 326fa19f9beSHajimu UMEMOTO if (strlen(ifa->ifa_name) != strlen(name) || 327fa19f9beSHajimu UMEMOTO strncmp(ifa->ifa_name, name, strlen(name)) != 0) 328259df286SKris Kennaway continue; 329259df286SKris Kennaway if (ifa->ifa_addr->sa_family != AF_INET6) 330259df286SKris Kennaway continue; 331259df286SKris Kennaway sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 332259df286SKris Kennaway if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 333259df286SKris Kennaway continue; 334259df286SKris Kennaway 335259df286SKris Kennaway memset(&ifr6, 0, sizeof(ifr6)); 336131033d5SHajimu UMEMOTO strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 337259df286SKris Kennaway memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len); 338259df286SKris Kennaway if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 3391533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 340259df286SKris Kennaway "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno)); 341259df286SKris Kennaway exit(1); 3427d56d374SYoshinobu Inoue } 3437d56d374SYoshinobu Inoue 344259df286SKris Kennaway freeifaddrs(ifap); 345259df286SKris Kennaway close(s); 346259df286SKris Kennaway return ifr6.ifr_ifru.ifru_flags6; 3477d56d374SYoshinobu Inoue } 3487d56d374SYoshinobu Inoue 349259df286SKris Kennaway freeifaddrs(ifap); 350259df286SKris Kennaway close(s); 3517d56d374SYoshinobu Inoue return -1; 3527d56d374SYoshinobu Inoue } 3537d56d374SYoshinobu Inoue 354fa19f9beSHajimu UMEMOTO 3557d56d374SYoshinobu Inoue static void 3567d56d374SYoshinobu Inoue get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 3577d56d374SYoshinobu Inoue { 3587d56d374SYoshinobu Inoue int i; 3597d56d374SYoshinobu Inoue 3607d56d374SYoshinobu Inoue for (i = 0; i < RTAX_MAX; i++) { 3617d56d374SYoshinobu Inoue if (addrs & (1 << i)) { 3627d56d374SYoshinobu Inoue rti_info[i] = sa; 3637d56d374SYoshinobu Inoue NEXT_SA(sa); 364fa19f9beSHajimu UMEMOTO } else 3657d56d374SYoshinobu Inoue rti_info[i] = NULL; 3667d56d374SYoshinobu Inoue } 3677d56d374SYoshinobu Inoue } 368