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_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> 51eb87e699SHiroki Sato #include <netinet6/nd6.h> 527d56d374SYoshinobu Inoue 537d56d374SYoshinobu Inoue #include <stdio.h> 547d56d374SYoshinobu Inoue #include <unistd.h> 557d56d374SYoshinobu Inoue #include <stdlib.h> 567d56d374SYoshinobu Inoue #include <syslog.h> 577d56d374SYoshinobu Inoue #include <string.h> 587d56d374SYoshinobu Inoue #include <fcntl.h> 597d56d374SYoshinobu Inoue #include <errno.h> 607d56d374SYoshinobu Inoue #include <limits.h> 61259df286SKris Kennaway #include <ifaddrs.h> 627d56d374SYoshinobu Inoue #include "rtsold.h" 637d56d374SYoshinobu Inoue 64259df286SKris Kennaway extern int rssock; 657d56d374SYoshinobu Inoue static int ifsock; 667d56d374SYoshinobu Inoue 67784bddbcSKevin Lo static int get_llflag(const char *); 68784bddbcSKevin Lo static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 697d56d374SYoshinobu Inoue 707d56d374SYoshinobu Inoue int 718e7409edSHajimu UMEMOTO ifinit(void) 727d56d374SYoshinobu Inoue { 73259df286SKris Kennaway ifsock = rssock; 747d56d374SYoshinobu Inoue 757d56d374SYoshinobu Inoue return(0); 767d56d374SYoshinobu Inoue } 777d56d374SYoshinobu Inoue 787d56d374SYoshinobu Inoue int 797d56d374SYoshinobu Inoue interface_up(char *name) 807d56d374SYoshinobu Inoue { 817d56d374SYoshinobu Inoue struct ifreq ifr; 82eb87e699SHiroki Sato struct in6_ndireq nd; 83259df286SKris Kennaway int llflag; 84eb87e699SHiroki Sato int s; 857d56d374SYoshinobu Inoue 86eb87e699SHiroki Sato memset(&ifr, 0, sizeof(ifr)); 8796316581SHajimu UMEMOTO strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 88eb87e699SHiroki Sato memset(&nd, 0, sizeof(nd)); 89eb87e699SHiroki Sato strlcpy(nd.ifname, name, sizeof(nd.ifname)); 907d56d374SYoshinobu Inoue 917d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 921533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s", 937d56d374SYoshinobu Inoue strerror(errno)); 947d56d374SYoshinobu Inoue return (-1); 957d56d374SYoshinobu Inoue } 967d56d374SYoshinobu Inoue if (!(ifr.ifr_flags & IFF_UP)) { 977d56d374SYoshinobu Inoue ifr.ifr_flags |= IFF_UP; 98fa19f9beSHajimu UMEMOTO if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 991533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 1007d56d374SYoshinobu Inoue "ioctl(SIOCSIFFLAGS): %s", strerror(errno)); 1017d56d374SYoshinobu Inoue return (-1); 1027d56d374SYoshinobu Inoue } 103eb87e699SHiroki Sato if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 104eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s", 105eb87e699SHiroki Sato strerror(errno)); 106eb87e699SHiroki Sato return (-1); 107eb87e699SHiroki Sato } 108eb87e699SHiroki Sato if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 109eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s", 110eb87e699SHiroki Sato strerror(errno)); 111eb87e699SHiroki Sato close(s); 112eb87e699SHiroki Sato return (-1); 113eb87e699SHiroki Sato } 1147d56d374SYoshinobu Inoue 1151533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name); 1167d56d374SYoshinobu Inoue 117eb87e699SHiroki Sato if (nd.ndi.flags & ND6_IFF_IFDISABLED) { 118eb87e699SHiroki Sato if (Fflag) { 119eb87e699SHiroki Sato nd.ndi.flags &= ~ND6_IFF_IFDISABLED; 120eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 121eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 122eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 123eb87e699SHiroki Sato strerror(errno)); 124eb87e699SHiroki Sato close(s); 125eb87e699SHiroki Sato return (-1); 126eb87e699SHiroki Sato } 127eb87e699SHiroki Sato } else { 128eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 129eb87e699SHiroki Sato "%s is disabled.", name); 130eb87e699SHiroki Sato close(s); 131eb87e699SHiroki Sato return (-1); 132eb87e699SHiroki Sato } 133eb87e699SHiroki Sato } 134eb87e699SHiroki Sato if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) { 135eb87e699SHiroki Sato if (Fflag) { 136eb87e699SHiroki Sato nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV; 137eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 138eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 139eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 140eb87e699SHiroki Sato strerror(errno)); 141eb87e699SHiroki Sato close(s); 142eb87e699SHiroki Sato return (-1); 143eb87e699SHiroki Sato } 144eb87e699SHiroki Sato } else { 145eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 146eb87e699SHiroki Sato "%s does not accept Router Advertisement.", name); 147eb87e699SHiroki Sato close(s); 148eb87e699SHiroki Sato return (-1); 149eb87e699SHiroki Sato } 150eb87e699SHiroki Sato } 151eb87e699SHiroki Sato close(s); 152eb87e699SHiroki Sato 153259df286SKris Kennaway llflag = get_llflag(name); 154259df286SKris Kennaway if (llflag < 0) { 1551533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, 156259df286SKris Kennaway "get_llflag() failed, anyway I'll try"); 157*db82af41SHiroki Sato return (0); 1587d56d374SYoshinobu Inoue } 1597d56d374SYoshinobu Inoue 160259df286SKris Kennaway if (!(llflag & IN6_IFF_NOTREADY)) { 161fa19f9beSHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is ready", name); 1627d56d374SYoshinobu Inoue return (0); 163259df286SKris Kennaway } else { 164259df286SKris Kennaway if (llflag & IN6_IFF_TENTATIVE) { 1651533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is tentative", 1667d56d374SYoshinobu Inoue name); 167*db82af41SHiroki Sato return (IFS_TENTATIVE); 1687d56d374SYoshinobu Inoue } 169259df286SKris Kennaway if (llflag & IN6_IFF_DUPLICATED) 1701533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is duplicated", 1717d56d374SYoshinobu Inoue name); 172*db82af41SHiroki Sato return (-1); 1737d56d374SYoshinobu Inoue } 1747d56d374SYoshinobu Inoue } 1757d56d374SYoshinobu Inoue 1767d56d374SYoshinobu Inoue int 1777d56d374SYoshinobu Inoue interface_status(struct ifinfo *ifinfo) 1787d56d374SYoshinobu Inoue { 1797d56d374SYoshinobu Inoue char *ifname = ifinfo->ifname; 1807d56d374SYoshinobu Inoue struct ifreq ifr; 1817d56d374SYoshinobu Inoue struct ifmediareq ifmr; 1827d56d374SYoshinobu Inoue 1837d56d374SYoshinobu Inoue /* get interface flags */ 1847d56d374SYoshinobu Inoue memset(&ifr, 0, sizeof(ifr)); 18596316581SHajimu UMEMOTO strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1867d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 1871533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s", 1887d56d374SYoshinobu Inoue ifname, strerror(errno)); 1897d56d374SYoshinobu Inoue return (-1); 1907d56d374SYoshinobu Inoue } 1917d56d374SYoshinobu Inoue /* 1927d56d374SYoshinobu Inoue * if one of UP and RUNNING flags is dropped, 1937d56d374SYoshinobu Inoue * the interface is not active. 1947d56d374SYoshinobu Inoue */ 195*db82af41SHiroki Sato if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 1967d56d374SYoshinobu Inoue goto inactive; 1977d56d374SYoshinobu Inoue /* Next, check carrier on the interface, if possible */ 1987d56d374SYoshinobu Inoue if (!ifinfo->mediareqok) 1997d56d374SYoshinobu Inoue goto active; 2007d56d374SYoshinobu Inoue memset(&ifmr, 0, sizeof(ifmr)); 20196316581SHajimu UMEMOTO strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 2027d56d374SYoshinobu Inoue 2037d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 2047d56d374SYoshinobu Inoue if (errno != EINVAL) { 2051533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, 2067d56d374SYoshinobu Inoue "ioctl(SIOCGIFMEDIA) on %s: %s", 2077d56d374SYoshinobu Inoue ifname, strerror(errno)); 2087d56d374SYoshinobu Inoue return(-1); 2097d56d374SYoshinobu Inoue } 2107d56d374SYoshinobu Inoue /* 2117d56d374SYoshinobu Inoue * EINVAL simply means that the interface does not support 2127d56d374SYoshinobu Inoue * the SIOCGIFMEDIA ioctl. We regard it alive. 2137d56d374SYoshinobu Inoue */ 2147d56d374SYoshinobu Inoue ifinfo->mediareqok = 0; 2157d56d374SYoshinobu Inoue goto active; 2167d56d374SYoshinobu Inoue } 2177d56d374SYoshinobu Inoue 2187d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_AVALID) { 2197d56d374SYoshinobu Inoue switch (ifmr.ifm_active & IFM_NMASK) { 2207d56d374SYoshinobu Inoue case IFM_ETHER: 221131033d5SHajimu UMEMOTO case IFM_IEEE80211: 2227d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_ACTIVE) 2237d56d374SYoshinobu Inoue goto active; 2247d56d374SYoshinobu Inoue else 2257d56d374SYoshinobu Inoue goto inactive; 2267d56d374SYoshinobu Inoue break; 2277d56d374SYoshinobu Inoue default: 2287d56d374SYoshinobu Inoue goto inactive; 2297d56d374SYoshinobu Inoue } 2307d56d374SYoshinobu Inoue } 2317d56d374SYoshinobu Inoue 2327d56d374SYoshinobu Inoue inactive: 2337d56d374SYoshinobu Inoue return (0); 2347d56d374SYoshinobu Inoue 2357d56d374SYoshinobu Inoue active: 2367d56d374SYoshinobu Inoue return (1); 2377d56d374SYoshinobu Inoue } 2387d56d374SYoshinobu Inoue 2397d56d374SYoshinobu Inoue #define ROUNDUP(a, size) \ 2407d56d374SYoshinobu Inoue (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 2417d56d374SYoshinobu Inoue 2427d56d374SYoshinobu Inoue #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 2437d56d374SYoshinobu Inoue ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 244fa19f9beSHajimu UMEMOTO sizeof(u_long)) : sizeof(u_long))) 2457d56d374SYoshinobu Inoue #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 2467d56d374SYoshinobu Inoue 2477d56d374SYoshinobu Inoue int 2487d56d374SYoshinobu Inoue lladdropt_length(struct sockaddr_dl *sdl) 2497d56d374SYoshinobu Inoue { 2507d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2517d56d374SYoshinobu Inoue case IFT_ETHER: 25233841545SHajimu UMEMOTO #ifdef IFT_IEEE80211 25333841545SHajimu UMEMOTO case IFT_IEEE80211: 25433841545SHajimu UMEMOTO #endif 2557d56d374SYoshinobu Inoue return (ROUNDUP8(ETHER_ADDR_LEN + 2)); 2567d56d374SYoshinobu Inoue default: 2577d56d374SYoshinobu Inoue return (0); 2587d56d374SYoshinobu Inoue } 2597d56d374SYoshinobu Inoue } 2607d56d374SYoshinobu Inoue 2617d56d374SYoshinobu Inoue void 2627d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2637d56d374SYoshinobu Inoue { 2647d56d374SYoshinobu Inoue char *addr; 2657d56d374SYoshinobu Inoue 2667d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2677d56d374SYoshinobu Inoue 2687d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2697d56d374SYoshinobu Inoue case IFT_ETHER: 27033841545SHajimu UMEMOTO #ifdef IFT_IEEE80211 27133841545SHajimu UMEMOTO case IFT_IEEE80211: 27233841545SHajimu UMEMOTO #endif 2737d56d374SYoshinobu Inoue ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 2747d56d374SYoshinobu Inoue addr = (char *)(ndopt + 1); 2757d56d374SYoshinobu Inoue memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 2767d56d374SYoshinobu Inoue break; 2777d56d374SYoshinobu Inoue default: 2781533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 2797d56d374SYoshinobu Inoue "unsupported link type(%d)", sdl->sdl_type); 2807d56d374SYoshinobu Inoue exit(1); 2817d56d374SYoshinobu Inoue } 2827d56d374SYoshinobu Inoue 2837d56d374SYoshinobu Inoue return; 2847d56d374SYoshinobu Inoue } 2857d56d374SYoshinobu Inoue 2867d56d374SYoshinobu Inoue struct sockaddr_dl * 2877d56d374SYoshinobu Inoue if_nametosdl(char *name) 2887d56d374SYoshinobu Inoue { 2897d56d374SYoshinobu Inoue int mib[6] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 2907d56d374SYoshinobu Inoue char *buf, *next, *lim; 2917d56d374SYoshinobu Inoue size_t len; 2927d56d374SYoshinobu Inoue struct if_msghdr *ifm; 2937d56d374SYoshinobu Inoue struct sockaddr *sa, *rti_info[RTAX_MAX]; 2947d56d374SYoshinobu Inoue struct sockaddr_dl *sdl = NULL, *ret_sdl; 2957d56d374SYoshinobu Inoue 2967d56d374SYoshinobu Inoue if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 2977d56d374SYoshinobu Inoue return(NULL); 2987d56d374SYoshinobu Inoue if ((buf = malloc(len)) == NULL) 2997d56d374SYoshinobu Inoue return(NULL); 3007d56d374SYoshinobu Inoue if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 3017d56d374SYoshinobu Inoue free(buf); 3027d56d374SYoshinobu Inoue return (NULL); 3037d56d374SYoshinobu Inoue } 3047d56d374SYoshinobu Inoue 3057d56d374SYoshinobu Inoue lim = buf + len; 3067d56d374SYoshinobu Inoue for (next = buf; next < lim; next += ifm->ifm_msglen) { 3077d56d374SYoshinobu Inoue ifm = (struct if_msghdr *)next; 3087d56d374SYoshinobu Inoue if (ifm->ifm_type == RTM_IFINFO) { 3097d56d374SYoshinobu Inoue sa = (struct sockaddr *)(ifm + 1); 3107d56d374SYoshinobu Inoue get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 3117d56d374SYoshinobu Inoue if ((sa = rti_info[RTAX_IFP]) != NULL) { 3127d56d374SYoshinobu Inoue if (sa->sa_family == AF_LINK) { 3137d56d374SYoshinobu Inoue sdl = (struct sockaddr_dl *)sa; 314259df286SKris Kennaway if (strlen(name) != sdl->sdl_nlen) 315259df286SKris Kennaway continue; /* not same len */ 3167d56d374SYoshinobu Inoue if (strncmp(&sdl->sdl_data[0], 3177d56d374SYoshinobu Inoue name, 3187d56d374SYoshinobu Inoue sdl->sdl_nlen) == 0) { 3197d56d374SYoshinobu Inoue break; 3207d56d374SYoshinobu Inoue } 3217d56d374SYoshinobu Inoue } 3227d56d374SYoshinobu Inoue } 3237d56d374SYoshinobu Inoue } 3247d56d374SYoshinobu Inoue } 3257d56d374SYoshinobu Inoue if (next == lim) { 3267d56d374SYoshinobu Inoue /* search failed */ 3277d56d374SYoshinobu Inoue free(buf); 3287d56d374SYoshinobu Inoue return (NULL); 3297d56d374SYoshinobu Inoue } 3307d56d374SYoshinobu Inoue 3314b8b545eSSUZUKI Shinsuke if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) { 3324b8b545eSSUZUKI Shinsuke free(buf); 3337d56d374SYoshinobu Inoue return (NULL); 3344b8b545eSSUZUKI Shinsuke } 3357d56d374SYoshinobu Inoue memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); 3367d56d374SYoshinobu Inoue 33733841545SHajimu UMEMOTO free(buf); 3387d56d374SYoshinobu Inoue return (ret_sdl); 3397d56d374SYoshinobu Inoue } 3407d56d374SYoshinobu Inoue 3417d56d374SYoshinobu Inoue int 3427d56d374SYoshinobu Inoue getinet6sysctl(int code) 3437d56d374SYoshinobu Inoue { 3447d56d374SYoshinobu Inoue int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 3457d56d374SYoshinobu Inoue int value; 3467d56d374SYoshinobu Inoue size_t size; 3477d56d374SYoshinobu Inoue 3487d56d374SYoshinobu Inoue mib[3] = code; 3497d56d374SYoshinobu Inoue size = sizeof(value); 3507d56d374SYoshinobu Inoue if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0) < 0) 351*db82af41SHiroki Sato return (-1); 3527d56d374SYoshinobu Inoue else 353*db82af41SHiroki Sato return (value); 3547d56d374SYoshinobu Inoue } 3557d56d374SYoshinobu Inoue 356fcdaee31SHajimu UMEMOTO int 357fcdaee31SHajimu UMEMOTO setinet6sysctl(int code, int newval) 358fcdaee31SHajimu UMEMOTO { 359fcdaee31SHajimu UMEMOTO int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 360fcdaee31SHajimu UMEMOTO int value; 361fcdaee31SHajimu UMEMOTO size_t size; 362fcdaee31SHajimu UMEMOTO 363fcdaee31SHajimu UMEMOTO mib[3] = code; 364fcdaee31SHajimu UMEMOTO size = sizeof(value); 365fcdaee31SHajimu UMEMOTO if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, 366fcdaee31SHajimu UMEMOTO &newval, sizeof(newval)) < 0) 367*db82af41SHiroki Sato return (-1); 368fcdaee31SHajimu UMEMOTO else 369*db82af41SHiroki Sato return (value); 370fcdaee31SHajimu UMEMOTO } 371fcdaee31SHajimu UMEMOTO 3727d56d374SYoshinobu Inoue /*------------------------------------------------------------*/ 3737d56d374SYoshinobu Inoue 374259df286SKris Kennaway /* get ia6_flags for link-local addr on if. returns -1 on error. */ 3757d56d374SYoshinobu Inoue static int 376259df286SKris Kennaway get_llflag(const char *name) 3777d56d374SYoshinobu Inoue { 378259df286SKris Kennaway struct ifaddrs *ifap, *ifa; 379259df286SKris Kennaway struct in6_ifreq ifr6; 380259df286SKris Kennaway struct sockaddr_in6 *sin6; 381259df286SKris Kennaway int s; 3827d56d374SYoshinobu Inoue 383259df286SKris Kennaway if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) { 3841533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s", 385259df286SKris Kennaway strerror(errno)); 3867d56d374SYoshinobu Inoue exit(1); 3877d56d374SYoshinobu Inoue } 388259df286SKris Kennaway if (getifaddrs(&ifap) != 0) { 389fa19f9beSHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "getifaddrs: %s", 390259df286SKris Kennaway strerror(errno)); 391259df286SKris Kennaway exit(1); 3927d56d374SYoshinobu Inoue } 3937d56d374SYoshinobu Inoue 394259df286SKris Kennaway for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 395fa19f9beSHajimu UMEMOTO if (strlen(ifa->ifa_name) != strlen(name) || 396fa19f9beSHajimu UMEMOTO strncmp(ifa->ifa_name, name, strlen(name)) != 0) 397259df286SKris Kennaway continue; 398259df286SKris Kennaway if (ifa->ifa_addr->sa_family != AF_INET6) 399259df286SKris Kennaway continue; 400259df286SKris Kennaway sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 401259df286SKris Kennaway if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 402259df286SKris Kennaway continue; 403259df286SKris Kennaway 404259df286SKris Kennaway memset(&ifr6, 0, sizeof(ifr6)); 40596316581SHajimu UMEMOTO strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 406259df286SKris Kennaway memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len); 407259df286SKris Kennaway if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 4081533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 409259df286SKris Kennaway "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno)); 410259df286SKris Kennaway exit(1); 4117d56d374SYoshinobu Inoue } 4127d56d374SYoshinobu Inoue 413259df286SKris Kennaway freeifaddrs(ifap); 414259df286SKris Kennaway close(s); 415*db82af41SHiroki Sato return (ifr6.ifr_ifru.ifru_flags6); 4167d56d374SYoshinobu Inoue } 4177d56d374SYoshinobu Inoue 418259df286SKris Kennaway freeifaddrs(ifap); 419259df286SKris Kennaway close(s); 420*db82af41SHiroki Sato return (-1); 4217d56d374SYoshinobu Inoue } 4227d56d374SYoshinobu Inoue 423fa19f9beSHajimu UMEMOTO 4247d56d374SYoshinobu Inoue static void 4257d56d374SYoshinobu Inoue get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 4267d56d374SYoshinobu Inoue { 4277d56d374SYoshinobu Inoue int i; 4287d56d374SYoshinobu Inoue 4297d56d374SYoshinobu Inoue for (i = 0; i < RTAX_MAX; i++) { 4307d56d374SYoshinobu Inoue if (addrs & (1 << i)) { 4317d56d374SYoshinobu Inoue rti_info[i] = sa; 4327d56d374SYoshinobu Inoue NEXT_SA(sa); 433fa19f9beSHajimu UMEMOTO } else 4347d56d374SYoshinobu Inoue rti_info[i] = NULL; 4357d56d374SYoshinobu Inoue } 4367d56d374SYoshinobu Inoue } 437