18e7409edSHajimu UMEMOTO /* $KAME: if.c,v 1.27 2003/10/05 00:09:36 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_types.h> 427d56d374SYoshinobu Inoue #include <net/route.h> 437d56d374SYoshinobu Inoue #include <net/if_dl.h> 447d56d374SYoshinobu Inoue #include <net/if_media.h> 457d56d374SYoshinobu Inoue #include <net/ethernet.h> 467d56d374SYoshinobu Inoue #include <netinet/in.h> 477d56d374SYoshinobu Inoue #include <netinet/icmp6.h> 487d56d374SYoshinobu Inoue 497d56d374SYoshinobu Inoue #include <netinet6/in6_var.h> 50eb87e699SHiroki Sato #include <netinet6/nd6.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 637d56d374SYoshinobu Inoue static int ifsock; 647d56d374SYoshinobu Inoue 65784bddbcSKevin Lo static int get_llflag(const char *); 66784bddbcSKevin Lo static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 677d56d374SYoshinobu Inoue 687d56d374SYoshinobu Inoue int 698e7409edSHajimu UMEMOTO ifinit(void) 707d56d374SYoshinobu Inoue { 71259df286SKris Kennaway ifsock = rssock; 727d56d374SYoshinobu Inoue 737d56d374SYoshinobu Inoue return(0); 747d56d374SYoshinobu Inoue } 757d56d374SYoshinobu Inoue 767d56d374SYoshinobu Inoue int 777d56d374SYoshinobu Inoue interface_up(char *name) 787d56d374SYoshinobu Inoue { 797d56d374SYoshinobu Inoue struct ifreq ifr; 80eb87e699SHiroki Sato struct in6_ndireq nd; 81259df286SKris Kennaway int llflag; 82eb87e699SHiroki Sato int s; 837d56d374SYoshinobu Inoue 84eb87e699SHiroki Sato memset(&ifr, 0, sizeof(ifr)); 85*dc47112fSDon Lewis strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 86eb87e699SHiroki Sato memset(&nd, 0, sizeof(nd)); 87eb87e699SHiroki Sato strlcpy(nd.ifname, name, sizeof(nd.ifname)); 887d56d374SYoshinobu Inoue 897d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 901533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s", 917d56d374SYoshinobu Inoue strerror(errno)); 927d56d374SYoshinobu Inoue return (-1); 937d56d374SYoshinobu Inoue } 947d56d374SYoshinobu Inoue if (!(ifr.ifr_flags & IFF_UP)) { 957d56d374SYoshinobu Inoue ifr.ifr_flags |= IFF_UP; 96fa19f9beSHajimu UMEMOTO if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 971533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 987d56d374SYoshinobu Inoue "ioctl(SIOCSIFFLAGS): %s", strerror(errno)); 997d56d374SYoshinobu Inoue return (-1); 1007d56d374SYoshinobu Inoue } 101eb87e699SHiroki Sato if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 102eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s", 103eb87e699SHiroki Sato strerror(errno)); 104eb87e699SHiroki Sato return (-1); 105eb87e699SHiroki Sato } 106eb87e699SHiroki Sato if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 107eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s", 108eb87e699SHiroki Sato strerror(errno)); 109eb87e699SHiroki Sato close(s); 110eb87e699SHiroki Sato return (-1); 111eb87e699SHiroki Sato } 1127d56d374SYoshinobu Inoue 1131533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name); 1147d56d374SYoshinobu Inoue 115eb87e699SHiroki Sato if (nd.ndi.flags & ND6_IFF_IFDISABLED) { 116eb87e699SHiroki Sato if (Fflag) { 117eb87e699SHiroki Sato nd.ndi.flags &= ~ND6_IFF_IFDISABLED; 118eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 119eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 120eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 121eb87e699SHiroki Sato strerror(errno)); 122eb87e699SHiroki Sato close(s); 123eb87e699SHiroki Sato return (-1); 124eb87e699SHiroki Sato } 125eb87e699SHiroki Sato } else { 126eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 127eb87e699SHiroki Sato "%s is disabled.", name); 128eb87e699SHiroki Sato close(s); 129eb87e699SHiroki Sato return (-1); 130eb87e699SHiroki Sato } 131eb87e699SHiroki Sato } 132eb87e699SHiroki Sato if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) { 133eb87e699SHiroki Sato if (Fflag) { 134eb87e699SHiroki Sato nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV; 135eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 136eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 137eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 138eb87e699SHiroki Sato strerror(errno)); 139eb87e699SHiroki Sato close(s); 140eb87e699SHiroki Sato return (-1); 141eb87e699SHiroki Sato } 142eb87e699SHiroki Sato } else { 143eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 144eb87e699SHiroki Sato "%s does not accept Router Advertisement.", name); 145eb87e699SHiroki Sato close(s); 146eb87e699SHiroki Sato return (-1); 147eb87e699SHiroki Sato } 148eb87e699SHiroki Sato } 149eb87e699SHiroki Sato close(s); 150eb87e699SHiroki Sato 151259df286SKris Kennaway llflag = get_llflag(name); 152259df286SKris Kennaway if (llflag < 0) { 1531533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, 154259df286SKris Kennaway "get_llflag() failed, anyway I'll try"); 155db82af41SHiroki Sato return (0); 1567d56d374SYoshinobu Inoue } 1577d56d374SYoshinobu Inoue 158259df286SKris Kennaway if (!(llflag & IN6_IFF_NOTREADY)) { 159fa19f9beSHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is ready", name); 1607d56d374SYoshinobu Inoue return (0); 161259df286SKris Kennaway } else { 162259df286SKris Kennaway if (llflag & IN6_IFF_TENTATIVE) { 1631533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is tentative", 1647d56d374SYoshinobu Inoue name); 165db82af41SHiroki Sato return (IFS_TENTATIVE); 1667d56d374SYoshinobu Inoue } 167259df286SKris Kennaway if (llflag & IN6_IFF_DUPLICATED) 1681533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is duplicated", 1697d56d374SYoshinobu Inoue name); 170db82af41SHiroki Sato return (-1); 1717d56d374SYoshinobu Inoue } 1727d56d374SYoshinobu Inoue } 1737d56d374SYoshinobu Inoue 1747d56d374SYoshinobu Inoue int 1757d56d374SYoshinobu Inoue interface_status(struct ifinfo *ifinfo) 1767d56d374SYoshinobu Inoue { 1777d56d374SYoshinobu Inoue char *ifname = ifinfo->ifname; 1787d56d374SYoshinobu Inoue struct ifreq ifr; 1797d56d374SYoshinobu Inoue struct ifmediareq ifmr; 1807d56d374SYoshinobu Inoue 1817d56d374SYoshinobu Inoue /* get interface flags */ 1827d56d374SYoshinobu Inoue memset(&ifr, 0, sizeof(ifr)); 183*dc47112fSDon Lewis strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1847d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 1851533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s", 1867d56d374SYoshinobu Inoue ifname, strerror(errno)); 1877d56d374SYoshinobu Inoue return (-1); 1887d56d374SYoshinobu Inoue } 1897d56d374SYoshinobu Inoue /* 1907d56d374SYoshinobu Inoue * if one of UP and RUNNING flags is dropped, 1917d56d374SYoshinobu Inoue * the interface is not active. 1927d56d374SYoshinobu Inoue */ 193db82af41SHiroki Sato if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1947d56d374SYoshinobu Inoue goto inactive; 1957d56d374SYoshinobu Inoue /* Next, check carrier on the interface, if possible */ 1967d56d374SYoshinobu Inoue if (!ifinfo->mediareqok) 1977d56d374SYoshinobu Inoue goto active; 1987d56d374SYoshinobu Inoue memset(&ifmr, 0, sizeof(ifmr)); 199*dc47112fSDon Lewis strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 2007d56d374SYoshinobu Inoue 2017d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 2027d56d374SYoshinobu Inoue if (errno != EINVAL) { 2031533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, 2047d56d374SYoshinobu Inoue "ioctl(SIOCGIFMEDIA) on %s: %s", 2057d56d374SYoshinobu Inoue ifname, strerror(errno)); 2067d56d374SYoshinobu Inoue return(-1); 2077d56d374SYoshinobu Inoue } 2087d56d374SYoshinobu Inoue /* 2097d56d374SYoshinobu Inoue * EINVAL simply means that the interface does not support 2107d56d374SYoshinobu Inoue * the SIOCGIFMEDIA ioctl. We regard it alive. 2117d56d374SYoshinobu Inoue */ 2127d56d374SYoshinobu Inoue ifinfo->mediareqok = 0; 2137d56d374SYoshinobu Inoue goto active; 2147d56d374SYoshinobu Inoue } 2157d56d374SYoshinobu Inoue 2167d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_AVALID) { 2177d56d374SYoshinobu Inoue switch (ifmr.ifm_active & IFM_NMASK) { 2187d56d374SYoshinobu Inoue case IFM_ETHER: 219131033d5SHajimu UMEMOTO case IFM_IEEE80211: 2207d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_ACTIVE) 2217d56d374SYoshinobu Inoue goto active; 2227d56d374SYoshinobu Inoue else 2237d56d374SYoshinobu Inoue goto inactive; 2247d56d374SYoshinobu Inoue break; 2257d56d374SYoshinobu Inoue default: 2267d56d374SYoshinobu Inoue goto inactive; 2277d56d374SYoshinobu Inoue } 2287d56d374SYoshinobu Inoue } 2297d56d374SYoshinobu Inoue 2307d56d374SYoshinobu Inoue inactive: 2317d56d374SYoshinobu Inoue return (0); 2327d56d374SYoshinobu Inoue 2337d56d374SYoshinobu Inoue active: 2347d56d374SYoshinobu Inoue return (1); 2357d56d374SYoshinobu Inoue } 2367d56d374SYoshinobu Inoue 2377d56d374SYoshinobu Inoue #define ROUNDUP(a, size) \ 2387d56d374SYoshinobu Inoue (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 2397d56d374SYoshinobu Inoue 2407d56d374SYoshinobu Inoue #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 2417d56d374SYoshinobu Inoue ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 242fa19f9beSHajimu UMEMOTO sizeof(u_long)) : sizeof(u_long))) 2437d56d374SYoshinobu Inoue #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 2447d56d374SYoshinobu Inoue 2457d56d374SYoshinobu Inoue int 2467d56d374SYoshinobu Inoue lladdropt_length(struct sockaddr_dl *sdl) 2477d56d374SYoshinobu Inoue { 2487d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2497d56d374SYoshinobu Inoue case IFT_ETHER: 25033841545SHajimu UMEMOTO case IFT_IEEE80211: 2517d56d374SYoshinobu Inoue return (ROUNDUP8(ETHER_ADDR_LEN + 2)); 2527d56d374SYoshinobu Inoue default: 2537d56d374SYoshinobu Inoue return (0); 2547d56d374SYoshinobu Inoue } 2557d56d374SYoshinobu Inoue } 2567d56d374SYoshinobu Inoue 2577d56d374SYoshinobu Inoue void 2587d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2597d56d374SYoshinobu Inoue { 2607d56d374SYoshinobu Inoue char *addr; 2617d56d374SYoshinobu Inoue 2627d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2637d56d374SYoshinobu Inoue 2647d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2657d56d374SYoshinobu Inoue case IFT_ETHER: 26633841545SHajimu UMEMOTO case IFT_IEEE80211: 2677d56d374SYoshinobu Inoue ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 2687d56d374SYoshinobu Inoue addr = (char *)(ndopt + 1); 2697d56d374SYoshinobu Inoue memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 2707d56d374SYoshinobu Inoue break; 2717d56d374SYoshinobu Inoue default: 2721533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 2737d56d374SYoshinobu Inoue "unsupported link type(%d)", sdl->sdl_type); 2747d56d374SYoshinobu Inoue exit(1); 2757d56d374SYoshinobu Inoue } 2767d56d374SYoshinobu Inoue 2777d56d374SYoshinobu Inoue return; 2787d56d374SYoshinobu Inoue } 2797d56d374SYoshinobu Inoue 2807d56d374SYoshinobu Inoue struct sockaddr_dl * 2817d56d374SYoshinobu Inoue if_nametosdl(char *name) 2827d56d374SYoshinobu Inoue { 283f74237f5SHiroki Sato int mib[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 2847d56d374SYoshinobu Inoue char *buf, *next, *lim; 2857d56d374SYoshinobu Inoue size_t len; 2867d56d374SYoshinobu Inoue struct if_msghdr *ifm; 2877d56d374SYoshinobu Inoue struct sockaddr *sa, *rti_info[RTAX_MAX]; 2887d56d374SYoshinobu Inoue struct sockaddr_dl *sdl = NULL, *ret_sdl; 2897d56d374SYoshinobu Inoue 290f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) < 0) 2917d56d374SYoshinobu Inoue return(NULL); 2927d56d374SYoshinobu Inoue if ((buf = malloc(len)) == NULL) 2937d56d374SYoshinobu Inoue return(NULL); 294f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) < 0) { 2957d56d374SYoshinobu Inoue free(buf); 2967d56d374SYoshinobu Inoue return (NULL); 2977d56d374SYoshinobu Inoue } 2987d56d374SYoshinobu Inoue 2997d56d374SYoshinobu Inoue lim = buf + len; 3007d56d374SYoshinobu Inoue for (next = buf; next < lim; next += ifm->ifm_msglen) { 301a678ca23SHiroki Sato ifm = (struct if_msghdr *)(void *)next; 3027d56d374SYoshinobu Inoue if (ifm->ifm_type == RTM_IFINFO) { 3037d56d374SYoshinobu Inoue sa = (struct sockaddr *)(ifm + 1); 3047d56d374SYoshinobu Inoue get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 3057d56d374SYoshinobu Inoue if ((sa = rti_info[RTAX_IFP]) != NULL) { 3067d56d374SYoshinobu Inoue if (sa->sa_family == AF_LINK) { 307a678ca23SHiroki Sato sdl = (struct sockaddr_dl *)(void *)sa; 308259df286SKris Kennaway if (strlen(name) != sdl->sdl_nlen) 309259df286SKris Kennaway continue; /* not same len */ 3107d56d374SYoshinobu Inoue if (strncmp(&sdl->sdl_data[0], 3117d56d374SYoshinobu Inoue name, 3127d56d374SYoshinobu Inoue sdl->sdl_nlen) == 0) { 3137d56d374SYoshinobu Inoue break; 3147d56d374SYoshinobu Inoue } 3157d56d374SYoshinobu Inoue } 3167d56d374SYoshinobu Inoue } 3177d56d374SYoshinobu Inoue } 3187d56d374SYoshinobu Inoue } 3197d56d374SYoshinobu Inoue if (next == lim) { 3207d56d374SYoshinobu Inoue /* search failed */ 3217d56d374SYoshinobu Inoue free(buf); 3227d56d374SYoshinobu Inoue return (NULL); 3237d56d374SYoshinobu Inoue } 3247d56d374SYoshinobu Inoue 3254b8b545eSSUZUKI Shinsuke if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) { 3264b8b545eSSUZUKI Shinsuke free(buf); 3277d56d374SYoshinobu Inoue return (NULL); 3284b8b545eSSUZUKI Shinsuke } 3297d56d374SYoshinobu Inoue memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); 3307d56d374SYoshinobu Inoue 33133841545SHajimu UMEMOTO free(buf); 3327d56d374SYoshinobu Inoue return (ret_sdl); 3337d56d374SYoshinobu Inoue } 3347d56d374SYoshinobu Inoue 3357d56d374SYoshinobu Inoue int 3367d56d374SYoshinobu Inoue getinet6sysctl(int code) 3377d56d374SYoshinobu Inoue { 3387d56d374SYoshinobu Inoue int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 3397d56d374SYoshinobu Inoue int value; 3407d56d374SYoshinobu Inoue size_t size; 3417d56d374SYoshinobu Inoue 3427d56d374SYoshinobu Inoue mib[3] = code; 3437d56d374SYoshinobu Inoue size = sizeof(value); 344f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), &value, &size, NULL, 0) < 0) 345db82af41SHiroki Sato return (-1); 3467d56d374SYoshinobu Inoue else 347db82af41SHiroki Sato return (value); 3487d56d374SYoshinobu Inoue } 3497d56d374SYoshinobu Inoue 350fcdaee31SHajimu UMEMOTO int 351fcdaee31SHajimu UMEMOTO setinet6sysctl(int code, int newval) 352fcdaee31SHajimu UMEMOTO { 353fcdaee31SHajimu UMEMOTO int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 354fcdaee31SHajimu UMEMOTO int value; 355fcdaee31SHajimu UMEMOTO size_t size; 356fcdaee31SHajimu UMEMOTO 357fcdaee31SHajimu UMEMOTO mib[3] = code; 358fcdaee31SHajimu UMEMOTO size = sizeof(value); 359f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), &value, &size, 360fcdaee31SHajimu UMEMOTO &newval, sizeof(newval)) < 0) 361db82af41SHiroki Sato return (-1); 362fcdaee31SHajimu UMEMOTO else 363db82af41SHiroki Sato return (value); 364fcdaee31SHajimu UMEMOTO } 365fcdaee31SHajimu UMEMOTO 3667d56d374SYoshinobu Inoue /*------------------------------------------------------------*/ 3677d56d374SYoshinobu Inoue 368259df286SKris Kennaway /* get ia6_flags for link-local addr on if. returns -1 on error. */ 3697d56d374SYoshinobu Inoue static int 370259df286SKris Kennaway get_llflag(const char *name) 3717d56d374SYoshinobu Inoue { 372259df286SKris Kennaway struct ifaddrs *ifap, *ifa; 373259df286SKris Kennaway struct in6_ifreq ifr6; 374259df286SKris Kennaway struct sockaddr_in6 *sin6; 375259df286SKris Kennaway int s; 3767d56d374SYoshinobu Inoue 377259df286SKris Kennaway if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { 3781533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s", 379259df286SKris Kennaway strerror(errno)); 3807d56d374SYoshinobu Inoue exit(1); 3817d56d374SYoshinobu Inoue } 382259df286SKris Kennaway if (getifaddrs(&ifap) != 0) { 383fa19f9beSHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "getifaddrs: %s", 384259df286SKris Kennaway strerror(errno)); 385259df286SKris Kennaway exit(1); 3867d56d374SYoshinobu Inoue } 3877d56d374SYoshinobu Inoue 388259df286SKris Kennaway for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 389fa19f9beSHajimu UMEMOTO if (strlen(ifa->ifa_name) != strlen(name) || 390fa19f9beSHajimu UMEMOTO strncmp(ifa->ifa_name, name, strlen(name)) != 0) 391259df286SKris Kennaway continue; 392259df286SKris Kennaway if (ifa->ifa_addr->sa_family != AF_INET6) 393259df286SKris Kennaway continue; 394a678ca23SHiroki Sato sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr; 395259df286SKris Kennaway if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 396259df286SKris Kennaway continue; 397259df286SKris Kennaway 398259df286SKris Kennaway memset(&ifr6, 0, sizeof(ifr6)); 399*dc47112fSDon Lewis strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 400259df286SKris Kennaway memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len); 401259df286SKris Kennaway if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 4021533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 403259df286SKris Kennaway "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno)); 404259df286SKris Kennaway exit(1); 4057d56d374SYoshinobu Inoue } 4067d56d374SYoshinobu Inoue 407259df286SKris Kennaway freeifaddrs(ifap); 408259df286SKris Kennaway close(s); 409db82af41SHiroki Sato return (ifr6.ifr_ifru.ifru_flags6); 4107d56d374SYoshinobu Inoue } 4117d56d374SYoshinobu Inoue 412259df286SKris Kennaway freeifaddrs(ifap); 413259df286SKris Kennaway close(s); 414db82af41SHiroki Sato return (-1); 4157d56d374SYoshinobu Inoue } 4167d56d374SYoshinobu Inoue 417fa19f9beSHajimu UMEMOTO 4187d56d374SYoshinobu Inoue static void 4197d56d374SYoshinobu Inoue get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 4207d56d374SYoshinobu Inoue { 4217d56d374SYoshinobu Inoue int i; 4227d56d374SYoshinobu Inoue 4237d56d374SYoshinobu Inoue for (i = 0; i < RTAX_MAX; i++) { 4247d56d374SYoshinobu Inoue if (addrs & (1 << i)) { 4257d56d374SYoshinobu Inoue rti_info[i] = sa; 4267d56d374SYoshinobu Inoue NEXT_SA(sa); 427fa19f9beSHajimu UMEMOTO } else 4287d56d374SYoshinobu Inoue rti_info[i] = NULL; 4297d56d374SYoshinobu Inoue } 4307d56d374SYoshinobu Inoue } 431