1804c83d4SKris Kennaway /* $KAME$ */ 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> 41259df286SKris Kennaway #if defined(__FreeBSD__) && __FreeBSD__ >= 3 427d56d374SYoshinobu Inoue #include <net/if_var.h> 43259df286SKris Kennaway #endif /* __FreeBSD__ >= 3 */ 447d56d374SYoshinobu Inoue #include <net/if_types.h> 457d56d374SYoshinobu Inoue #include <net/route.h> 467d56d374SYoshinobu Inoue #include <net/if_dl.h> 477d56d374SYoshinobu Inoue #include <net/if_media.h> 48259df286SKris Kennaway #ifdef __FreeBSD__ 497d56d374SYoshinobu Inoue # include <net/ethernet.h> 50259df286SKris Kennaway #endif 51259df286SKris Kennaway #ifdef __NetBSD__ 52259df286SKris Kennaway #include <net/if_ether.h> 53259df286SKris Kennaway #endif 54259df286SKris Kennaway #if defined(__bsdi__) || defined(__OpenBSD__) 55259df286SKris Kennaway # include <netinet/in.h> 56259df286SKris Kennaway # include <netinet/if_ether.h> 57259df286SKris Kennaway #endif 587d56d374SYoshinobu Inoue #include <netinet/in.h> 597d56d374SYoshinobu Inoue #include <netinet/icmp6.h> 607d56d374SYoshinobu Inoue 617d56d374SYoshinobu Inoue #include <netinet6/in6_var.h> 627d56d374SYoshinobu Inoue 637d56d374SYoshinobu Inoue #include <stdio.h> 647d56d374SYoshinobu Inoue #include <unistd.h> 657d56d374SYoshinobu Inoue #include <stdlib.h> 667d56d374SYoshinobu Inoue #include <syslog.h> 677d56d374SYoshinobu Inoue #include <string.h> 687d56d374SYoshinobu Inoue #include <fcntl.h> 697d56d374SYoshinobu Inoue #include <errno.h> 707d56d374SYoshinobu Inoue #include <limits.h> 71259df286SKris Kennaway #ifdef HAVE_GETIFADDRS 72259df286SKris Kennaway #include <ifaddrs.h> 73259df286SKris Kennaway #endif 747d56d374SYoshinobu Inoue 757d56d374SYoshinobu Inoue #include "rtsold.h" 767d56d374SYoshinobu Inoue 77259df286SKris Kennaway extern int rssock; 787d56d374SYoshinobu Inoue static int ifsock; 797d56d374SYoshinobu Inoue 80259df286SKris Kennaway static int get_llflag __P((const char *name)); 81259df286SKris Kennaway #ifndef HAVE_GETIFADDRS 82259df286SKris Kennaway static unsigned int if_maxindex __P((void)); 83259df286SKris Kennaway #endif 847d56d374SYoshinobu Inoue static void get_rtaddrs __P((int addrs, struct sockaddr *sa, 857d56d374SYoshinobu Inoue struct sockaddr **rti_info)); 867d56d374SYoshinobu Inoue 877d56d374SYoshinobu Inoue int 887d56d374SYoshinobu Inoue ifinit() 897d56d374SYoshinobu Inoue { 90259df286SKris Kennaway ifsock = rssock; 917d56d374SYoshinobu Inoue 927d56d374SYoshinobu Inoue return(0); 937d56d374SYoshinobu Inoue } 947d56d374SYoshinobu Inoue 957d56d374SYoshinobu Inoue int 967d56d374SYoshinobu Inoue interface_up(char *name) 977d56d374SYoshinobu Inoue { 987d56d374SYoshinobu Inoue struct ifreq ifr; 99259df286SKris Kennaway int llflag; 1007d56d374SYoshinobu Inoue 1017d56d374SYoshinobu Inoue strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1027d56d374SYoshinobu Inoue 1037d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 1047d56d374SYoshinobu Inoue warnmsg(LOG_WARNING, __FUNCTION__, "ioctl(SIOCGIFFLAGS): %s", 1057d56d374SYoshinobu Inoue strerror(errno)); 1067d56d374SYoshinobu Inoue return(-1); 1077d56d374SYoshinobu Inoue } 1087d56d374SYoshinobu Inoue if (!(ifr.ifr_flags & IFF_UP)) { 1097d56d374SYoshinobu Inoue ifr.ifr_flags |= IFF_UP; 1107d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { 1117d56d374SYoshinobu Inoue warnmsg(LOG_ERR, __FUNCTION__, 1127d56d374SYoshinobu Inoue "ioctl(SIOCSIFFLAGS): %s", strerror(errno)); 1137d56d374SYoshinobu Inoue } 1147d56d374SYoshinobu Inoue return(-1); 1157d56d374SYoshinobu Inoue } 1167d56d374SYoshinobu Inoue 1177d56d374SYoshinobu Inoue warnmsg(LOG_DEBUG, __FUNCTION__, "checking if %s is ready...", name); 1187d56d374SYoshinobu Inoue 119259df286SKris Kennaway llflag = get_llflag(name); 120259df286SKris Kennaway if (llflag < 0) { 1217d56d374SYoshinobu Inoue warnmsg(LOG_WARNING, __FUNCTION__, 122259df286SKris Kennaway "get_llflag() failed, anyway I'll try"); 1237d56d374SYoshinobu Inoue return 0; 1247d56d374SYoshinobu Inoue } 1257d56d374SYoshinobu Inoue 126259df286SKris Kennaway if (!(llflag & IN6_IFF_NOTREADY)) { 1277d56d374SYoshinobu Inoue warnmsg(LOG_DEBUG, __FUNCTION__, 1287d56d374SYoshinobu Inoue "%s is ready", name); 1297d56d374SYoshinobu Inoue return(0); 130259df286SKris Kennaway } else { 131259df286SKris Kennaway if (llflag & IN6_IFF_TENTATIVE) { 1327d56d374SYoshinobu Inoue warnmsg(LOG_DEBUG, __FUNCTION__, "%s is tentative", 1337d56d374SYoshinobu Inoue name); 1347d56d374SYoshinobu Inoue return IFS_TENTATIVE; 1357d56d374SYoshinobu Inoue } 136259df286SKris Kennaway if (llflag & IN6_IFF_DUPLICATED) 1377d56d374SYoshinobu Inoue warnmsg(LOG_DEBUG, __FUNCTION__, "%s is duplicated", 1387d56d374SYoshinobu Inoue name); 1397d56d374SYoshinobu Inoue return -1; 1407d56d374SYoshinobu Inoue } 1417d56d374SYoshinobu Inoue } 1427d56d374SYoshinobu Inoue 1437d56d374SYoshinobu Inoue int 1447d56d374SYoshinobu Inoue interface_status(struct ifinfo *ifinfo) 1457d56d374SYoshinobu Inoue { 1467d56d374SYoshinobu Inoue char *ifname = ifinfo->ifname; 1477d56d374SYoshinobu Inoue struct ifreq ifr; 1487d56d374SYoshinobu Inoue struct ifmediareq ifmr; 1497d56d374SYoshinobu Inoue 1507d56d374SYoshinobu Inoue /* get interface flags */ 1517d56d374SYoshinobu Inoue memset(&ifr, 0, sizeof(ifr)); 1527d56d374SYoshinobu Inoue strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1537d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 1547d56d374SYoshinobu Inoue warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGIFFLAGS) on %s: %s", 1557d56d374SYoshinobu Inoue ifname, strerror(errno)); 1567d56d374SYoshinobu Inoue return(-1); 1577d56d374SYoshinobu Inoue } 1587d56d374SYoshinobu Inoue /* 1597d56d374SYoshinobu Inoue * if one of UP and RUNNING flags is dropped, 1607d56d374SYoshinobu Inoue * the interface is not active. 1617d56d374SYoshinobu Inoue */ 1627d56d374SYoshinobu Inoue if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 1637d56d374SYoshinobu Inoue goto inactive; 1647d56d374SYoshinobu Inoue } 1657d56d374SYoshinobu Inoue 1667d56d374SYoshinobu Inoue /* Next, check carrier on the interface, if possible */ 1677d56d374SYoshinobu Inoue if (!ifinfo->mediareqok) 1687d56d374SYoshinobu Inoue goto active; 1697d56d374SYoshinobu Inoue memset(&ifmr, 0, sizeof(ifmr)); 1707d56d374SYoshinobu Inoue strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 1717d56d374SYoshinobu Inoue 1727d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1737d56d374SYoshinobu Inoue if (errno != EINVAL) { 1747d56d374SYoshinobu Inoue warnmsg(LOG_DEBUG, __FUNCTION__, 1757d56d374SYoshinobu Inoue "ioctl(SIOCGIFMEDIA) on %s: %s", 1767d56d374SYoshinobu Inoue ifname, strerror(errno)); 1777d56d374SYoshinobu Inoue return(-1); 1787d56d374SYoshinobu Inoue } 1797d56d374SYoshinobu Inoue /* 1807d56d374SYoshinobu Inoue * EINVAL simply means that the interface does not support 1817d56d374SYoshinobu Inoue * the SIOCGIFMEDIA ioctl. We regard it alive. 1827d56d374SYoshinobu Inoue */ 1837d56d374SYoshinobu Inoue ifinfo->mediareqok = 0; 1847d56d374SYoshinobu Inoue goto active; 1857d56d374SYoshinobu Inoue } 1867d56d374SYoshinobu Inoue 1877d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_AVALID) { 1887d56d374SYoshinobu Inoue switch(ifmr.ifm_active & IFM_NMASK) { 1897d56d374SYoshinobu Inoue case IFM_ETHER: 1907d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_ACTIVE) 1917d56d374SYoshinobu Inoue goto active; 1927d56d374SYoshinobu Inoue else 1937d56d374SYoshinobu Inoue goto inactive; 1947d56d374SYoshinobu Inoue break; 1957d56d374SYoshinobu Inoue default: 1967d56d374SYoshinobu Inoue goto inactive; 1977d56d374SYoshinobu Inoue } 1987d56d374SYoshinobu Inoue } 1997d56d374SYoshinobu Inoue 2007d56d374SYoshinobu Inoue inactive: 2017d56d374SYoshinobu Inoue return(0); 2027d56d374SYoshinobu Inoue 2037d56d374SYoshinobu Inoue active: 2047d56d374SYoshinobu Inoue return(1); 2057d56d374SYoshinobu Inoue } 2067d56d374SYoshinobu Inoue 2077d56d374SYoshinobu Inoue #define ROUNDUP(a, size) \ 2087d56d374SYoshinobu Inoue (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 2097d56d374SYoshinobu Inoue 2107d56d374SYoshinobu Inoue #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 2117d56d374SYoshinobu Inoue ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 2127d56d374SYoshinobu Inoue sizeof(u_long)) :\ 2137d56d374SYoshinobu Inoue sizeof(u_long))) 2147d56d374SYoshinobu Inoue #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 2157d56d374SYoshinobu Inoue 2167d56d374SYoshinobu Inoue int 2177d56d374SYoshinobu Inoue lladdropt_length(struct sockaddr_dl *sdl) 2187d56d374SYoshinobu Inoue { 2197d56d374SYoshinobu Inoue switch(sdl->sdl_type) { 2207d56d374SYoshinobu Inoue case IFT_ETHER: 2217d56d374SYoshinobu Inoue return(ROUNDUP8(ETHER_ADDR_LEN + 2)); 2227d56d374SYoshinobu Inoue default: 2237d56d374SYoshinobu Inoue return(0); 2247d56d374SYoshinobu Inoue } 2257d56d374SYoshinobu Inoue } 2267d56d374SYoshinobu Inoue 2277d56d374SYoshinobu Inoue void 2287d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2297d56d374SYoshinobu Inoue { 2307d56d374SYoshinobu Inoue char *addr; 2317d56d374SYoshinobu Inoue 2327d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2337d56d374SYoshinobu Inoue 2347d56d374SYoshinobu Inoue switch(sdl->sdl_type) { 2357d56d374SYoshinobu Inoue case IFT_ETHER: 2367d56d374SYoshinobu Inoue ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 2377d56d374SYoshinobu Inoue addr = (char *)(ndopt + 1); 2387d56d374SYoshinobu Inoue memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 2397d56d374SYoshinobu Inoue break; 2407d56d374SYoshinobu Inoue default: 2417d56d374SYoshinobu Inoue warnmsg(LOG_ERR, __FUNCTION__, 2427d56d374SYoshinobu Inoue "unsupported link type(%d)", sdl->sdl_type); 2437d56d374SYoshinobu Inoue exit(1); 2447d56d374SYoshinobu Inoue } 2457d56d374SYoshinobu Inoue 2467d56d374SYoshinobu Inoue return; 2477d56d374SYoshinobu Inoue } 2487d56d374SYoshinobu Inoue 2497d56d374SYoshinobu Inoue struct sockaddr_dl * 2507d56d374SYoshinobu Inoue if_nametosdl(char *name) 2517d56d374SYoshinobu Inoue { 2527d56d374SYoshinobu Inoue int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 2537d56d374SYoshinobu Inoue char *buf, *next, *lim; 2547d56d374SYoshinobu Inoue size_t len; 2557d56d374SYoshinobu Inoue struct if_msghdr *ifm; 2567d56d374SYoshinobu Inoue struct sockaddr *sa, *rti_info[RTAX_MAX]; 2577d56d374SYoshinobu Inoue struct sockaddr_dl *sdl = NULL, *ret_sdl; 2587d56d374SYoshinobu Inoue 2597d56d374SYoshinobu Inoue if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 2607d56d374SYoshinobu Inoue return(NULL); 2617d56d374SYoshinobu Inoue if ((buf = malloc(len)) == NULL) 2627d56d374SYoshinobu Inoue return(NULL); 2637d56d374SYoshinobu Inoue if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 2647d56d374SYoshinobu Inoue free(buf); 2657d56d374SYoshinobu Inoue return(NULL); 2667d56d374SYoshinobu Inoue } 2677d56d374SYoshinobu Inoue 2687d56d374SYoshinobu Inoue lim = buf + len; 2697d56d374SYoshinobu Inoue for (next = buf; next < lim; next += ifm->ifm_msglen) { 2707d56d374SYoshinobu Inoue ifm = (struct if_msghdr *)next; 2717d56d374SYoshinobu Inoue if (ifm->ifm_type == RTM_IFINFO) { 2727d56d374SYoshinobu Inoue sa = (struct sockaddr *)(ifm + 1); 2737d56d374SYoshinobu Inoue get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 2747d56d374SYoshinobu Inoue if ((sa = rti_info[RTAX_IFP]) != NULL) { 2757d56d374SYoshinobu Inoue if (sa->sa_family == AF_LINK) { 2767d56d374SYoshinobu Inoue sdl = (struct sockaddr_dl *)sa; 277259df286SKris Kennaway if (strlen(name) != sdl->sdl_nlen) 278259df286SKris Kennaway continue; /* not same len */ 2797d56d374SYoshinobu Inoue if (strncmp(&sdl->sdl_data[0], 2807d56d374SYoshinobu Inoue name, 2817d56d374SYoshinobu Inoue sdl->sdl_nlen) == 0) { 2827d56d374SYoshinobu Inoue break; 2837d56d374SYoshinobu Inoue } 2847d56d374SYoshinobu Inoue } 2857d56d374SYoshinobu Inoue } 2867d56d374SYoshinobu Inoue } 2877d56d374SYoshinobu Inoue } 2887d56d374SYoshinobu Inoue if (next == lim) { 2897d56d374SYoshinobu Inoue /* search failed */ 2907d56d374SYoshinobu Inoue free(buf); 2917d56d374SYoshinobu Inoue return(NULL); 2927d56d374SYoshinobu Inoue } 2937d56d374SYoshinobu Inoue 2947d56d374SYoshinobu Inoue if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) 2957d56d374SYoshinobu Inoue return(NULL); 2967d56d374SYoshinobu Inoue memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); 2977d56d374SYoshinobu Inoue 2987d56d374SYoshinobu Inoue return(ret_sdl); 2997d56d374SYoshinobu Inoue } 3007d56d374SYoshinobu Inoue 3017d56d374SYoshinobu Inoue int 3027d56d374SYoshinobu Inoue getinet6sysctl(int code) 3037d56d374SYoshinobu Inoue { 3047d56d374SYoshinobu Inoue int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 3057d56d374SYoshinobu Inoue int value; 3067d56d374SYoshinobu Inoue size_t size; 3077d56d374SYoshinobu Inoue 3087d56d374SYoshinobu Inoue mib[3] = code; 3097d56d374SYoshinobu Inoue size = sizeof(value); 3107d56d374SYoshinobu Inoue if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) < 0) 3117d56d374SYoshinobu Inoue return -1; 3127d56d374SYoshinobu Inoue else 3137d56d374SYoshinobu Inoue return value; 3147d56d374SYoshinobu Inoue } 3157d56d374SYoshinobu Inoue 3167d56d374SYoshinobu Inoue /*------------------------------------------------------------*/ 3177d56d374SYoshinobu Inoue 318259df286SKris Kennaway /* get ia6_flags for link-local addr on if. returns -1 on error. */ 3197d56d374SYoshinobu Inoue static int 320259df286SKris Kennaway get_llflag(const char *name) 3217d56d374SYoshinobu Inoue { 322259df286SKris Kennaway #ifdef HAVE_GETIFADDRS 323259df286SKris Kennaway struct ifaddrs *ifap, *ifa; 324259df286SKris Kennaway struct in6_ifreq ifr6; 325259df286SKris Kennaway struct sockaddr_in6 *sin6; 326259df286SKris Kennaway int s; 3277d56d374SYoshinobu Inoue 328259df286SKris Kennaway if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { 329259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, "socket(SOCK_DGRAM): %s", 330259df286SKris Kennaway strerror(errno)); 3317d56d374SYoshinobu Inoue exit(1); 3327d56d374SYoshinobu Inoue } 333259df286SKris Kennaway if (getifaddrs(&ifap) != 0) { 334259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, "etifaddrs: %s", 335259df286SKris Kennaway strerror(errno)); 336259df286SKris Kennaway exit(1); 3377d56d374SYoshinobu Inoue } 3387d56d374SYoshinobu Inoue 339259df286SKris Kennaway for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 340259df286SKris Kennaway if (strlen(ifa->ifa_name) != strlen(name) 341259df286SKris Kennaway || strncmp(ifa->ifa_name, name, strlen(name)) != 0) 342259df286SKris Kennaway continue; 343259df286SKris Kennaway if (ifa->ifa_addr->sa_family != AF_INET6) 344259df286SKris Kennaway continue; 345259df286SKris Kennaway sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 346259df286SKris Kennaway if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 347259df286SKris Kennaway continue; 348259df286SKris Kennaway 349259df286SKris Kennaway memset(&ifr6, 0, sizeof(ifr6)); 350259df286SKris Kennaway strcpy(ifr6.ifr_name, name); 351259df286SKris Kennaway memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len); 352259df286SKris Kennaway if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 353259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, 354259df286SKris Kennaway "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno)); 355259df286SKris Kennaway exit(1); 3567d56d374SYoshinobu Inoue } 3577d56d374SYoshinobu Inoue 358259df286SKris Kennaway freeifaddrs(ifap); 359259df286SKris Kennaway close(s); 360259df286SKris Kennaway return ifr6.ifr_ifru.ifru_flags6; 3617d56d374SYoshinobu Inoue } 3627d56d374SYoshinobu Inoue 363259df286SKris Kennaway freeifaddrs(ifap); 364259df286SKris Kennaway close(s); 3657d56d374SYoshinobu Inoue return -1; 366259df286SKris Kennaway #else 367259df286SKris Kennaway int s; 368259df286SKris Kennaway unsigned int maxif; 369259df286SKris Kennaway struct ifreq *iflist; 370259df286SKris Kennaway struct ifconf ifconf; 371259df286SKris Kennaway struct ifreq *ifr, *ifr_end; 372259df286SKris Kennaway struct sockaddr_in6 *sin6; 373259df286SKris Kennaway struct in6_ifreq ifr6; 374259df286SKris Kennaway 375259df286SKris Kennaway maxif = if_maxindex() + 1; 376259df286SKris Kennaway iflist = (struct ifreq *)malloc(maxif * BUFSIZ); /* XXX */ 377259df286SKris Kennaway if (iflist == NULL) { 378259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, "not enough core"); 379259df286SKris Kennaway exit(1); 3807d56d374SYoshinobu Inoue } 3817d56d374SYoshinobu Inoue 382259df286SKris Kennaway if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { 383259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, "socket(SOCK_DGRAM): %s", 384259df286SKris Kennaway strerror(errno)); 385259df286SKris Kennaway exit(1); 386259df286SKris Kennaway } 387259df286SKris Kennaway memset(&ifconf, 0, sizeof(ifconf)); 388259df286SKris Kennaway ifconf.ifc_req = iflist; 389259df286SKris Kennaway ifconf.ifc_len = maxif * BUFSIZ; /* XXX */ 390259df286SKris Kennaway if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) { 391259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGIFCONF): %s", 392259df286SKris Kennaway strerror(errno)); 393259df286SKris Kennaway exit(1); 394259df286SKris Kennaway } 395259df286SKris Kennaway 396259df286SKris Kennaway /* Look for this interface in the list */ 397259df286SKris Kennaway ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len); 398259df286SKris Kennaway for (ifr = ifconf.ifc_req; 399259df286SKris Kennaway ifr < ifr_end; 400259df286SKris Kennaway ifr = (struct ifreq *) ((char *) &ifr->ifr_addr 401259df286SKris Kennaway + ifr->ifr_addr.sa_len)) { 402259df286SKris Kennaway if (strlen(ifr->ifr_name) != strlen(name) 403259df286SKris Kennaway || strncmp(ifr->ifr_name, name, strlen(name)) != 0) 404259df286SKris Kennaway continue; 405259df286SKris Kennaway if (ifr->ifr_addr.sa_family != AF_INET6) 406259df286SKris Kennaway continue; 407259df286SKris Kennaway sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr; 408259df286SKris Kennaway if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 409259df286SKris Kennaway continue; 410259df286SKris Kennaway 411259df286SKris Kennaway memset(&ifr6, 0, sizeof(ifr6)); 412259df286SKris Kennaway strcpy(ifr6.ifr_name, name); 413259df286SKris Kennaway memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len); 414259df286SKris Kennaway if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 415259df286SKris Kennaway warnmsg(LOG_ERR, __FUNCTION__, 416259df286SKris Kennaway "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno)); 417259df286SKris Kennaway exit(1); 418259df286SKris Kennaway } 419259df286SKris Kennaway 420259df286SKris Kennaway free(iflist); 421259df286SKris Kennaway close(s); 422259df286SKris Kennaway return ifr6.ifr_ifru.ifru_flags6; 423259df286SKris Kennaway } 424259df286SKris Kennaway 425259df286SKris Kennaway free(iflist); 426259df286SKris Kennaway close(s); 427259df286SKris Kennaway return -1; 428259df286SKris Kennaway #endif 429259df286SKris Kennaway } 430259df286SKris Kennaway 431259df286SKris Kennaway #ifndef HAVE_GETIFADDRS 432259df286SKris Kennaway static unsigned int 433259df286SKris Kennaway if_maxindex() 434259df286SKris Kennaway { 435259df286SKris Kennaway struct if_nameindex *p, *p0; 436259df286SKris Kennaway unsigned int max = 0; 437259df286SKris Kennaway 438259df286SKris Kennaway p0 = if_nameindex(); 439259df286SKris Kennaway for (p = p0; p && p->if_index && p->if_name; p++) { 440259df286SKris Kennaway if (max < p->if_index) 441259df286SKris Kennaway max = p->if_index; 442259df286SKris Kennaway } 443259df286SKris Kennaway if_freenameindex(p0); 444259df286SKris Kennaway return max; 445259df286SKris Kennaway } 446259df286SKris Kennaway #endif 447259df286SKris Kennaway 4487d56d374SYoshinobu Inoue static void 4497d56d374SYoshinobu Inoue get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 4507d56d374SYoshinobu Inoue { 4517d56d374SYoshinobu Inoue int i; 4527d56d374SYoshinobu Inoue 4537d56d374SYoshinobu Inoue for (i = 0; i < RTAX_MAX; i++) { 4547d56d374SYoshinobu Inoue if (addrs & (1 << i)) { 4557d56d374SYoshinobu Inoue rti_info[i] = sa; 4567d56d374SYoshinobu Inoue NEXT_SA(sa); 4577d56d374SYoshinobu Inoue } 4587d56d374SYoshinobu Inoue else 4597d56d374SYoshinobu Inoue rti_info[i] = NULL; 4607d56d374SYoshinobu Inoue } 4617d56d374SYoshinobu Inoue } 462