18e7409edSHajimu UMEMOTO /* $KAME: if.c,v 1.27 2003/10/05 00:09:36 itojun Exp $ */ 2804c83d4SKris Kennaway 3*8a16b7a1SPedro F. Giffuni /*- 4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 5*8a16b7a1SPedro F. Giffuni * 67d56d374SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 77d56d374SYoshinobu Inoue * All rights reserved. 87d56d374SYoshinobu Inoue * 97d56d374SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 107d56d374SYoshinobu Inoue * modification, are permitted provided that the following conditions 117d56d374SYoshinobu Inoue * are met: 127d56d374SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 137d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 147d56d374SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 157d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 167d56d374SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 177d56d374SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 187d56d374SYoshinobu Inoue * may be used to endorse or promote products derived from this software 197d56d374SYoshinobu Inoue * without specific prior written permission. 207d56d374SYoshinobu Inoue * 217d56d374SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 227d56d374SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237d56d374SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247d56d374SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 257d56d374SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267d56d374SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277d56d374SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287d56d374SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297d56d374SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307d56d374SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317d56d374SYoshinobu Inoue * SUCH DAMAGE. 327d56d374SYoshinobu Inoue * 337d56d374SYoshinobu Inoue * $FreeBSD$ 347d56d374SYoshinobu Inoue */ 357d56d374SYoshinobu Inoue 367d56d374SYoshinobu Inoue #include <sys/param.h> 377d56d374SYoshinobu Inoue #include <sys/socket.h> 387d56d374SYoshinobu Inoue #include <sys/sysctl.h> 397d56d374SYoshinobu Inoue #include <sys/ioctl.h> 40804c83d4SKris Kennaway #include <sys/queue.h> 417d56d374SYoshinobu Inoue 427d56d374SYoshinobu Inoue #include <net/if.h> 437d56d374SYoshinobu Inoue #include <net/if_types.h> 447d56d374SYoshinobu Inoue #include <net/route.h> 457d56d374SYoshinobu Inoue #include <net/if_dl.h> 467d56d374SYoshinobu Inoue #include <net/if_media.h> 477d56d374SYoshinobu Inoue #include <net/ethernet.h> 487d56d374SYoshinobu Inoue #include <netinet/in.h> 497d56d374SYoshinobu Inoue #include <netinet/icmp6.h> 507d56d374SYoshinobu Inoue 517d56d374SYoshinobu Inoue #include <netinet6/in6_var.h> 52eb87e699SHiroki Sato #include <netinet6/nd6.h> 537d56d374SYoshinobu Inoue 547d56d374SYoshinobu Inoue #include <stdio.h> 557d56d374SYoshinobu Inoue #include <unistd.h> 567d56d374SYoshinobu Inoue #include <stdlib.h> 577d56d374SYoshinobu Inoue #include <syslog.h> 587d56d374SYoshinobu Inoue #include <string.h> 597d56d374SYoshinobu Inoue #include <fcntl.h> 607d56d374SYoshinobu Inoue #include <errno.h> 617d56d374SYoshinobu Inoue #include <limits.h> 62259df286SKris Kennaway #include <ifaddrs.h> 637d56d374SYoshinobu Inoue #include "rtsold.h" 647d56d374SYoshinobu Inoue 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)); 87dc47112fSDon Lewis strlcpy(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"); 157db82af41SHiroki 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); 167db82af41SHiroki 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); 172db82af41SHiroki 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)); 185dc47112fSDon Lewis strlcpy(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 */ 195db82af41SHiroki 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)); 201dc47112fSDon Lewis strlcpy(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: 2527d56d374SYoshinobu Inoue return (ROUNDUP8(ETHER_ADDR_LEN + 2)); 2537d56d374SYoshinobu Inoue default: 2547d56d374SYoshinobu Inoue return (0); 2557d56d374SYoshinobu Inoue } 2567d56d374SYoshinobu Inoue } 2577d56d374SYoshinobu Inoue 2587d56d374SYoshinobu Inoue void 2597d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2607d56d374SYoshinobu Inoue { 2617d56d374SYoshinobu Inoue char *addr; 2627d56d374SYoshinobu Inoue 2637d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2647d56d374SYoshinobu Inoue 2657d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2667d56d374SYoshinobu Inoue case IFT_ETHER: 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)); 399dc47112fSDon 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