18e7409edSHajimu UMEMOTO /* $KAME: if.c,v 1.27 2003/10/05 00:09:36 itojun Exp $ */ 2804c83d4SKris Kennaway 38a16b7a1SPedro F. Giffuni /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro 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> 3704e9edb5SMark Johnston #include <sys/capsicum.h> 387d56d374SYoshinobu Inoue #include <sys/ioctl.h> 39804c83d4SKris Kennaway #include <sys/queue.h> 4004e9edb5SMark Johnston #include <sys/socket.h> 4104e9edb5SMark Johnston #include <sys/sysctl.h> 427d56d374SYoshinobu Inoue 437d56d374SYoshinobu Inoue #include <net/if.h> 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> 487d56d374SYoshinobu Inoue #include <net/ethernet.h> 497d56d374SYoshinobu Inoue #include <netinet/in.h> 507d56d374SYoshinobu Inoue #include <netinet/icmp6.h> 517d56d374SYoshinobu Inoue 527d56d374SYoshinobu Inoue #include <netinet6/in6_var.h> 53eb87e699SHiroki Sato #include <netinet6/nd6.h> 547d56d374SYoshinobu Inoue 5504e9edb5SMark Johnston #include <capsicum_helpers.h> 567d56d374SYoshinobu Inoue #include <stdio.h> 577d56d374SYoshinobu Inoue #include <unistd.h> 587d56d374SYoshinobu Inoue #include <stdlib.h> 597d56d374SYoshinobu Inoue #include <syslog.h> 607d56d374SYoshinobu Inoue #include <string.h> 617d56d374SYoshinobu Inoue #include <fcntl.h> 627d56d374SYoshinobu Inoue #include <errno.h> 637d56d374SYoshinobu Inoue #include <limits.h> 64259df286SKris Kennaway #include <ifaddrs.h> 657d56d374SYoshinobu Inoue #include "rtsold.h" 667d56d374SYoshinobu Inoue 677d56d374SYoshinobu Inoue static int ifsock; 68784bddbcSKevin Lo static void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 697d56d374SYoshinobu Inoue 707d56d374SYoshinobu Inoue int 718e7409edSHajimu UMEMOTO ifinit(void) 727d56d374SYoshinobu Inoue { 7304e9edb5SMark Johnston cap_rights_t rights; 7404e9edb5SMark Johnston int sock; 757d56d374SYoshinobu Inoue 7604e9edb5SMark Johnston sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 7704e9edb5SMark Johnston if (sock < 0) { 7804e9edb5SMark Johnston warnmsg(LOG_ERR, __func__, "socket(): %s", 7904e9edb5SMark Johnston strerror(errno)); 8004e9edb5SMark Johnston return (-1); 8104e9edb5SMark Johnston } 8204e9edb5SMark Johnston if (caph_rights_limit(sock, cap_rights_init(&rights, CAP_IOCTL)) < 0) { 8304e9edb5SMark Johnston warnmsg(LOG_ERR, __func__, "caph_rights_limit(): %s", 8404e9edb5SMark Johnston strerror(errno)); 8504e9edb5SMark Johnston (void)close(sock); 8604e9edb5SMark Johnston return (-1); 8704e9edb5SMark Johnston } 8804e9edb5SMark Johnston ifsock = sock; 897d56d374SYoshinobu Inoue return (0); 907d56d374SYoshinobu Inoue } 917d56d374SYoshinobu Inoue 927d56d374SYoshinobu Inoue int 937d56d374SYoshinobu Inoue interface_up(char *name) 947d56d374SYoshinobu Inoue { 957d56d374SYoshinobu Inoue struct ifreq ifr; 96eb87e699SHiroki Sato struct in6_ndireq nd; 97259df286SKris Kennaway int llflag; 98eb87e699SHiroki Sato int s; 997d56d374SYoshinobu Inoue 100eb87e699SHiroki Sato memset(&ifr, 0, sizeof(ifr)); 101dc47112fSDon Lewis strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 102eb87e699SHiroki Sato memset(&nd, 0, sizeof(nd)); 103eb87e699SHiroki Sato strlcpy(nd.ifname, name, sizeof(nd.ifname)); 1047d56d374SYoshinobu Inoue 1057d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { 1061533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s", 1077d56d374SYoshinobu Inoue strerror(errno)); 1087d56d374SYoshinobu Inoue return (-1); 1097d56d374SYoshinobu Inoue } 1107d56d374SYoshinobu Inoue if (!(ifr.ifr_flags & IFF_UP)) { 1117d56d374SYoshinobu Inoue ifr.ifr_flags |= IFF_UP; 112fa19f9beSHajimu UMEMOTO if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 1131533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 1147d56d374SYoshinobu Inoue "ioctl(SIOCSIFFLAGS): %s", strerror(errno)); 1157d56d374SYoshinobu Inoue return (-1); 1167d56d374SYoshinobu Inoue } 117eb87e699SHiroki Sato if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 118eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s", 119eb87e699SHiroki Sato strerror(errno)); 120eb87e699SHiroki Sato return (-1); 121eb87e699SHiroki Sato } 122eb87e699SHiroki Sato if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 123eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s", 124eb87e699SHiroki Sato strerror(errno)); 125eb87e699SHiroki Sato close(s); 126eb87e699SHiroki Sato return (-1); 127eb87e699SHiroki Sato } 1287d56d374SYoshinobu Inoue 1291533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name); 1307d56d374SYoshinobu Inoue 131eb87e699SHiroki Sato if (nd.ndi.flags & ND6_IFF_IFDISABLED) { 132eb87e699SHiroki Sato if (Fflag) { 133eb87e699SHiroki Sato nd.ndi.flags &= ~ND6_IFF_IFDISABLED; 134eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 135eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 136eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 137eb87e699SHiroki Sato strerror(errno)); 138eb87e699SHiroki Sato close(s); 139eb87e699SHiroki Sato return (-1); 140eb87e699SHiroki Sato } 141eb87e699SHiroki Sato } else { 142eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 143eb87e699SHiroki Sato "%s is disabled.", name); 144eb87e699SHiroki Sato close(s); 145eb87e699SHiroki Sato return (-1); 146eb87e699SHiroki Sato } 147eb87e699SHiroki Sato } 148eb87e699SHiroki Sato if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) { 149eb87e699SHiroki Sato if (Fflag) { 150eb87e699SHiroki Sato nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV; 151eb87e699SHiroki Sato if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) { 152eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 153eb87e699SHiroki Sato "ioctl(SIOCSIFINFO_IN6): %s", 154eb87e699SHiroki Sato strerror(errno)); 155eb87e699SHiroki Sato close(s); 156eb87e699SHiroki Sato return (-1); 157eb87e699SHiroki Sato } 158eb87e699SHiroki Sato } else { 159eb87e699SHiroki Sato warnmsg(LOG_WARNING, __func__, 160eb87e699SHiroki Sato "%s does not accept Router Advertisement.", name); 161eb87e699SHiroki Sato close(s); 162eb87e699SHiroki Sato return (-1); 163eb87e699SHiroki Sato } 164eb87e699SHiroki Sato } 165eb87e699SHiroki Sato close(s); 166eb87e699SHiroki Sato 16704e9edb5SMark Johnston if (cap_llflags_get(capllflags, name, &llflag) != 0) { 1681533bed0SHajimu UMEMOTO warnmsg(LOG_WARNING, __func__, 16904e9edb5SMark Johnston "cap_llflags_get() failed, anyway I'll try"); 170db82af41SHiroki Sato return (0); 1717d56d374SYoshinobu Inoue } 1727d56d374SYoshinobu Inoue 173259df286SKris Kennaway if (!(llflag & IN6_IFF_NOTREADY)) { 174fa19f9beSHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is ready", name); 1757d56d374SYoshinobu Inoue return (0); 176259df286SKris Kennaway } else { 177259df286SKris Kennaway if (llflag & IN6_IFF_TENTATIVE) { 1781533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is tentative", 1797d56d374SYoshinobu Inoue name); 180db82af41SHiroki Sato return (IFS_TENTATIVE); 1817d56d374SYoshinobu Inoue } 182259df286SKris Kennaway if (llflag & IN6_IFF_DUPLICATED) 1831533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, "%s is duplicated", 1847d56d374SYoshinobu Inoue name); 185db82af41SHiroki Sato return (-1); 1867d56d374SYoshinobu Inoue } 1877d56d374SYoshinobu Inoue } 1887d56d374SYoshinobu Inoue 1897d56d374SYoshinobu Inoue int 1907d56d374SYoshinobu Inoue interface_status(struct ifinfo *ifinfo) 1917d56d374SYoshinobu Inoue { 1927d56d374SYoshinobu Inoue char *ifname = ifinfo->ifname; 1937d56d374SYoshinobu Inoue struct ifreq ifr; 1947d56d374SYoshinobu Inoue struct ifmediareq ifmr; 1957d56d374SYoshinobu Inoue 1967d56d374SYoshinobu Inoue /* get interface flags */ 1977d56d374SYoshinobu Inoue memset(&ifr, 0, sizeof(ifr)); 198dc47112fSDon Lewis strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1997d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 2001533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s", 2017d56d374SYoshinobu Inoue ifname, strerror(errno)); 2027d56d374SYoshinobu Inoue return (-1); 2037d56d374SYoshinobu Inoue } 2047d56d374SYoshinobu Inoue /* 2057d56d374SYoshinobu Inoue * if one of UP and RUNNING flags is dropped, 2067d56d374SYoshinobu Inoue * the interface is not active. 2077d56d374SYoshinobu Inoue */ 208db82af41SHiroki Sato if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 2097d56d374SYoshinobu Inoue goto inactive; 2107d56d374SYoshinobu Inoue /* Next, check carrier on the interface, if possible */ 2117d56d374SYoshinobu Inoue if (!ifinfo->mediareqok) 2127d56d374SYoshinobu Inoue goto active; 2137d56d374SYoshinobu Inoue memset(&ifmr, 0, sizeof(ifmr)); 214dc47112fSDon Lewis strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 2157d56d374SYoshinobu Inoue 2167d56d374SYoshinobu Inoue if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 2177d56d374SYoshinobu Inoue if (errno != EINVAL) { 2181533bed0SHajimu UMEMOTO warnmsg(LOG_DEBUG, __func__, 2197d56d374SYoshinobu Inoue "ioctl(SIOCGIFMEDIA) on %s: %s", 2207d56d374SYoshinobu Inoue ifname, strerror(errno)); 2217d56d374SYoshinobu Inoue return(-1); 2227d56d374SYoshinobu Inoue } 2237d56d374SYoshinobu Inoue /* 2247d56d374SYoshinobu Inoue * EINVAL simply means that the interface does not support 2257d56d374SYoshinobu Inoue * the SIOCGIFMEDIA ioctl. We regard it alive. 2267d56d374SYoshinobu Inoue */ 2277d56d374SYoshinobu Inoue ifinfo->mediareqok = 0; 2287d56d374SYoshinobu Inoue goto active; 2297d56d374SYoshinobu Inoue } 2307d56d374SYoshinobu Inoue 2317d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_AVALID) { 2327d56d374SYoshinobu Inoue switch (ifmr.ifm_active & IFM_NMASK) { 2337d56d374SYoshinobu Inoue case IFM_ETHER: 234131033d5SHajimu UMEMOTO case IFM_IEEE80211: 2357d56d374SYoshinobu Inoue if (ifmr.ifm_status & IFM_ACTIVE) 2367d56d374SYoshinobu Inoue goto active; 2377d56d374SYoshinobu Inoue else 2387d56d374SYoshinobu Inoue goto inactive; 2397d56d374SYoshinobu Inoue break; 2407d56d374SYoshinobu Inoue default: 2417d56d374SYoshinobu Inoue goto inactive; 2427d56d374SYoshinobu Inoue } 2437d56d374SYoshinobu Inoue } 2447d56d374SYoshinobu Inoue 2457d56d374SYoshinobu Inoue inactive: 2467d56d374SYoshinobu Inoue return (0); 2477d56d374SYoshinobu Inoue 2487d56d374SYoshinobu Inoue active: 2497d56d374SYoshinobu Inoue return (1); 2507d56d374SYoshinobu Inoue } 2517d56d374SYoshinobu Inoue 2527d56d374SYoshinobu Inoue #define ROUNDUP(a, size) \ 2537d56d374SYoshinobu Inoue (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 2547d56d374SYoshinobu Inoue 2557d56d374SYoshinobu Inoue #define NEXT_SA(ap) (ap) = (struct sockaddr *) \ 2567d56d374SYoshinobu Inoue ((caddr_t)(ap) + ((ap)->sa_len ? ROUNDUP((ap)->sa_len,\ 257fa19f9beSHajimu UMEMOTO sizeof(u_long)) : sizeof(u_long))) 2587d56d374SYoshinobu Inoue #define ROUNDUP8(a) (1 + (((a) - 1) | 7)) 2597d56d374SYoshinobu Inoue 2607d56d374SYoshinobu Inoue int 2617d56d374SYoshinobu Inoue lladdropt_length(struct sockaddr_dl *sdl) 2627d56d374SYoshinobu Inoue { 2637d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2647d56d374SYoshinobu Inoue case IFT_ETHER: 265*1a4d7030SLuiz Otavio O Souza case IFT_L2VLAN: 2667d56d374SYoshinobu Inoue return (ROUNDUP8(ETHER_ADDR_LEN + 2)); 2677d56d374SYoshinobu Inoue default: 2687d56d374SYoshinobu Inoue return (0); 2697d56d374SYoshinobu Inoue } 2707d56d374SYoshinobu Inoue } 2717d56d374SYoshinobu Inoue 2727d56d374SYoshinobu Inoue void 2737d56d374SYoshinobu Inoue lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) 2747d56d374SYoshinobu Inoue { 2757d56d374SYoshinobu Inoue char *addr; 2767d56d374SYoshinobu Inoue 2777d56d374SYoshinobu Inoue ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ 2787d56d374SYoshinobu Inoue 2797d56d374SYoshinobu Inoue switch (sdl->sdl_type) { 2807d56d374SYoshinobu Inoue case IFT_ETHER: 281*1a4d7030SLuiz Otavio O Souza case IFT_L2VLAN: 2827d56d374SYoshinobu Inoue ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; 2837d56d374SYoshinobu Inoue addr = (char *)(ndopt + 1); 2847d56d374SYoshinobu Inoue memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); 2857d56d374SYoshinobu Inoue break; 2867d56d374SYoshinobu Inoue default: 2871533bed0SHajimu UMEMOTO warnmsg(LOG_ERR, __func__, 2887d56d374SYoshinobu Inoue "unsupported link type(%d)", sdl->sdl_type); 2897d56d374SYoshinobu Inoue exit(1); 2907d56d374SYoshinobu Inoue } 2917d56d374SYoshinobu Inoue } 2927d56d374SYoshinobu Inoue 2937d56d374SYoshinobu Inoue struct sockaddr_dl * 2947d56d374SYoshinobu Inoue if_nametosdl(char *name) 2957d56d374SYoshinobu Inoue { 296f74237f5SHiroki Sato int mib[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 2977d56d374SYoshinobu Inoue char *buf, *next, *lim; 2987d56d374SYoshinobu Inoue size_t len; 2997d56d374SYoshinobu Inoue struct if_msghdr *ifm; 3007d56d374SYoshinobu Inoue struct sockaddr *sa, *rti_info[RTAX_MAX]; 3017d56d374SYoshinobu Inoue struct sockaddr_dl *sdl = NULL, *ret_sdl; 3027d56d374SYoshinobu Inoue 303f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) < 0) 3047d56d374SYoshinobu Inoue return(NULL); 3057d56d374SYoshinobu Inoue if ((buf = malloc(len)) == NULL) 3067d56d374SYoshinobu Inoue return(NULL); 307f74237f5SHiroki Sato if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) < 0) { 3087d56d374SYoshinobu Inoue free(buf); 3097d56d374SYoshinobu Inoue return (NULL); 3107d56d374SYoshinobu Inoue } 3117d56d374SYoshinobu Inoue 3127d56d374SYoshinobu Inoue lim = buf + len; 3137d56d374SYoshinobu Inoue for (next = buf; next < lim; next += ifm->ifm_msglen) { 314a678ca23SHiroki Sato ifm = (struct if_msghdr *)(void *)next; 3157d56d374SYoshinobu Inoue if (ifm->ifm_type == RTM_IFINFO) { 3167d56d374SYoshinobu Inoue sa = (struct sockaddr *)(ifm + 1); 3177d56d374SYoshinobu Inoue get_rtaddrs(ifm->ifm_addrs, sa, rti_info); 3187d56d374SYoshinobu Inoue if ((sa = rti_info[RTAX_IFP]) != NULL) { 3197d56d374SYoshinobu Inoue if (sa->sa_family == AF_LINK) { 320a678ca23SHiroki Sato sdl = (struct sockaddr_dl *)(void *)sa; 321259df286SKris Kennaway if (strlen(name) != sdl->sdl_nlen) 322259df286SKris Kennaway continue; /* not same len */ 3237d56d374SYoshinobu Inoue if (strncmp(&sdl->sdl_data[0], 3247d56d374SYoshinobu Inoue name, 3257d56d374SYoshinobu Inoue sdl->sdl_nlen) == 0) { 3267d56d374SYoshinobu Inoue break; 3277d56d374SYoshinobu Inoue } 3287d56d374SYoshinobu Inoue } 3297d56d374SYoshinobu Inoue } 3307d56d374SYoshinobu Inoue } 3317d56d374SYoshinobu Inoue } 332ecce515dSMark Johnston if (next >= lim) { 3337d56d374SYoshinobu Inoue /* search failed */ 3347d56d374SYoshinobu Inoue free(buf); 3357d56d374SYoshinobu Inoue return (NULL); 3367d56d374SYoshinobu Inoue } 3377d56d374SYoshinobu Inoue 3384b8b545eSSUZUKI Shinsuke if ((ret_sdl = malloc(sdl->sdl_len)) == NULL) { 3394b8b545eSSUZUKI Shinsuke free(buf); 3407d56d374SYoshinobu Inoue return (NULL); 3414b8b545eSSUZUKI Shinsuke } 3427d56d374SYoshinobu Inoue memcpy((caddr_t)ret_sdl, (caddr_t)sdl, sdl->sdl_len); 3437d56d374SYoshinobu Inoue 34433841545SHajimu UMEMOTO free(buf); 3457d56d374SYoshinobu Inoue return (ret_sdl); 3467d56d374SYoshinobu Inoue } 3477d56d374SYoshinobu Inoue 3487d56d374SYoshinobu Inoue static void 3497d56d374SYoshinobu Inoue get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 3507d56d374SYoshinobu Inoue { 3517d56d374SYoshinobu Inoue int i; 3527d56d374SYoshinobu Inoue 3537d56d374SYoshinobu Inoue for (i = 0; i < RTAX_MAX; i++) { 3547d56d374SYoshinobu Inoue if (addrs & (1 << i)) { 3557d56d374SYoshinobu Inoue rti_info[i] = sa; 3567d56d374SYoshinobu Inoue NEXT_SA(sa); 357fa19f9beSHajimu UMEMOTO } else 3587d56d374SYoshinobu Inoue rti_info[i] = NULL; 3597d56d374SYoshinobu Inoue } 3607d56d374SYoshinobu Inoue } 361