The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/in6.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: in6.c,v 1.141 2008/07/31 18:24:07 matt Exp $   */
    2 /*      $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $   */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Copyright (c) 1982, 1986, 1991, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)in.c        8.2 (Berkeley) 11/15/93
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 __KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.141 2008/07/31 18:24:07 matt Exp $");
   66 
   67 #include "opt_inet.h"
   68 #include "opt_pfil_hooks.h"
   69 
   70 #include <sys/param.h>
   71 #include <sys/ioctl.h>
   72 #include <sys/errno.h>
   73 #include <sys/malloc.h>
   74 #include <sys/socket.h>
   75 #include <sys/socketvar.h>
   76 #include <sys/sockio.h>
   77 #include <sys/systm.h>
   78 #include <sys/proc.h>
   79 #include <sys/time.h>
   80 #include <sys/kernel.h>
   81 #include <sys/syslog.h>
   82 #include <sys/kauth.h>
   83 
   84 #include <net/if.h>
   85 #include <net/if_types.h>
   86 #include <net/route.h>
   87 #include <net/if_dl.h>
   88 
   89 #include <netinet/in.h>
   90 #include <netinet/in_var.h>
   91 #include <net/if_ether.h>
   92 
   93 #include <netinet/ip6.h>
   94 #include <netinet6/ip6_var.h>
   95 #include <netinet6/nd6.h>
   96 #include <netinet6/mld6_var.h>
   97 #include <netinet6/ip6_mroute.h>
   98 #include <netinet6/in6_ifattach.h>
   99 #include <netinet6/scope6_var.h>
  100 
  101 #include <net/net_osdep.h>
  102 
  103 #ifdef PFIL_HOOKS
  104 #include <net/pfil.h>
  105 #endif
  106 
  107 MALLOC_DEFINE(M_IP6OPT, "ip6_options", "IPv6 options");
  108 
  109 /* enable backward compatibility code for obsoleted ioctls */
  110 #define COMPAT_IN6IFIOCTL
  111 
  112 #ifdef  IN6_DEBUG
  113 #define IN6_DPRINTF(__fmt, ...) printf(__fmt, __VA_ARGS__)
  114 #else
  115 #define IN6_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0) 
  116 #endif /* IN6_DEBUG */
  117 
  118 /*
  119  * Definitions of some constant IP6 addresses.
  120  */
  121 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
  122 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
  123 const struct in6_addr in6addr_nodelocal_allnodes =
  124         IN6ADDR_NODELOCAL_ALLNODES_INIT;
  125 const struct in6_addr in6addr_linklocal_allnodes =
  126         IN6ADDR_LINKLOCAL_ALLNODES_INIT;
  127 const struct in6_addr in6addr_linklocal_allrouters =
  128         IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
  129 
  130 const struct in6_addr in6mask0 = IN6MASK0;
  131 const struct in6_addr in6mask32 = IN6MASK32;
  132 const struct in6_addr in6mask64 = IN6MASK64;
  133 const struct in6_addr in6mask96 = IN6MASK96;
  134 const struct in6_addr in6mask128 = IN6MASK128;
  135 
  136 const struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
  137                                      0, 0, IN6ADDR_ANY_INIT, 0};
  138 
  139 static int in6_lifaddr_ioctl(struct socket *, u_long, void *,
  140         struct ifnet *, struct lwp *);
  141 static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
  142         struct sockaddr_in6 *, int);
  143 static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
  144 
  145 /*
  146  * Subroutine for in6_ifaddloop() and in6_ifremloop().
  147  * This routine does actual work.
  148  */
  149 static void
  150 in6_ifloop_request(int cmd, struct ifaddr *ifa)
  151 {
  152         struct sockaddr_in6 lo_sa;
  153         struct sockaddr_in6 all1_sa;
  154         struct rtentry *nrt = NULL;
  155         int e;
  156 
  157         sockaddr_in6_init(&all1_sa, &in6mask128, 0, 0, 0);
  158         sockaddr_in6_init(&lo_sa, &in6addr_loopback, 0, 0, 0);
  159 
  160         /*
  161          * We specify the address itself as the gateway, and set the
  162          * RTF_LLINFO flag, so that the corresponding host route would have
  163          * the flag, and thus applications that assume traditional behavior
  164          * would be happy.  Note that we assume the caller of the function
  165          * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
  166          * which changes the outgoing interface to the loopback interface.
  167          */
  168         e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
  169             (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
  170         if (e != 0) {
  171                 log(LOG_ERR, "in6_ifloop_request: "
  172                     "%s operation failed for %s (errno=%d)\n",
  173                     cmd == RTM_ADD ? "ADD" : "DELETE",
  174                     ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
  175                     e);
  176         }
  177 
  178         /*
  179          * Make sure rt_ifa be equal to IFA, the second argument of the
  180          * function.
  181          * We need this because when we refer to rt_ifa->ia6_flags in
  182          * ip6_input, we assume that the rt_ifa points to the address instead
  183          * of the loopback address.
  184          */
  185         if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
  186                 rt_replace_ifa(nrt, ifa);
  187 
  188         /*
  189          * Report the addition/removal of the address to the routing socket.
  190          * XXX: since we called rtinit for a p2p interface with a destination,
  191          *      we end up reporting twice in such a case.  Should we rather
  192          *      omit the second report?
  193          */
  194         if (nrt) {
  195                 rt_newaddrmsg(cmd, ifa, e, nrt);
  196                 if (cmd == RTM_DELETE) {
  197                         if (nrt->rt_refcnt <= 0) {
  198                                 /* XXX: we should free the entry ourselves. */
  199                                 nrt->rt_refcnt++;
  200                                 rtfree(nrt);
  201                         }
  202                 } else {
  203                         /* the cmd must be RTM_ADD here */
  204                         nrt->rt_refcnt--;
  205                 }
  206         }
  207 }
  208 
  209 /*
  210  * Add ownaddr as loopback rtentry.  We previously add the route only if
  211  * necessary (ex. on a p2p link).  However, since we now manage addresses
  212  * separately from prefixes, we should always add the route.  We can't
  213  * rely on the cloning mechanism from the corresponding interface route
  214  * any more.
  215  */
  216 void
  217 in6_ifaddloop(struct ifaddr *ifa)
  218 {
  219         struct rtentry *rt;
  220 
  221         /* If there is no loopback entry, allocate one. */
  222         rt = rtalloc1(ifa->ifa_addr, 0);
  223         if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
  224             (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
  225                 in6_ifloop_request(RTM_ADD, ifa);
  226         if (rt != NULL)
  227                 rt->rt_refcnt--;
  228 }
  229 
  230 /*
  231  * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
  232  * if it exists.
  233  */
  234 void
  235 in6_ifremloop(struct ifaddr *ifa)
  236 {
  237         struct in6_ifaddr *alt_ia = NULL, *ia;
  238         struct rtentry *rt;
  239         int ia_count = 0;
  240 
  241         /*
  242          * Some of BSD variants do not remove cloned routes
  243          * from an interface direct route, when removing the direct route
  244          * (see comments in net/net_osdep.h).  Even for variants that do remove
  245          * cloned routes, they could fail to remove the cloned routes when
  246          * we handle multple addresses that share a common prefix.
  247          * So, we should remove the route corresponding to the deleted address.
  248          */
  249 
  250         /*
  251          * Delete the entry only if exactly one ifaddr matches the
  252          * address, ifa->ifa_addr.
  253          *
  254          * If more than one ifaddr matches, replace the ifaddr in
  255          * the routing table, rt_ifa, with a different ifaddr than
  256          * the one we are purging, ifa.  It is important to do
  257          * this, or else the routing table can accumulate dangling
  258          * pointers rt->rt_ifa->ifa_ifp to destroyed interfaces,
  259          * which will lead to crashes, later.  (More than one ifaddr
  260          * can match if we assign the same address to multiple---probably
  261          * p2p---interfaces.)
  262          *
  263          * XXX An old comment at this place said, "we should avoid
  264          * XXX such a configuration [i.e., interfaces with the same
  265          * XXX addressed assigned --ed.] in IPv6...".  I do not
  266          * XXX agree, especially now that I have fixed the dangling
  267          * XXX ifp-pointers bug.
  268          */
  269         for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
  270                 if (!IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr))
  271                         continue;
  272                 if (ia->ia_ifp != ifa->ifa_ifp)
  273                         alt_ia = ia;
  274                 if (++ia_count > 1 && alt_ia != NULL)
  275                         break;
  276         }
  277 
  278         if (ia_count == 0)
  279                 return;
  280 
  281         if ((rt = rtalloc1(ifa->ifa_addr, 0)) == NULL)
  282                 return;
  283         rt->rt_refcnt--;
  284 
  285         /*
  286          * Before deleting, check if a corresponding loopbacked
  287          * host route surely exists.  With this check, we can avoid
  288          * deleting an interface direct route whose destination is
  289          * the same as the address being removed.  This can happen
  290          * when removing a subnet-router anycast address on an
  291          * interface attached to a shared medium.
  292          */
  293         if ((rt->rt_flags & RTF_HOST) == 0 ||
  294             (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
  295                 return;
  296 
  297         /* If we cannot replace the route's ifaddr with the equivalent
  298          * ifaddr of another interface, I believe it is safest to
  299          * delete the route.
  300          */
  301         if (ia_count == 1 || alt_ia == NULL)
  302                 in6_ifloop_request(RTM_DELETE, ifa);
  303         else
  304                 rt_replace_ifa(rt, &alt_ia->ia_ifa);
  305 }
  306 
  307 int
  308 in6_mask2len(struct in6_addr *mask, u_char *lim0)
  309 {
  310         int x = 0, y;
  311         u_char *lim = lim0, *p;
  312 
  313         /* ignore the scope_id part */
  314         if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
  315                 lim = (u_char *)mask + sizeof(*mask);
  316         for (p = (u_char *)mask; p < lim; x++, p++) {
  317                 if (*p != 0xff)
  318                         break;
  319         }
  320         y = 0;
  321         if (p < lim) {
  322                 for (y = 0; y < NBBY; y++) {
  323                         if ((*p & (0x80 >> y)) == 0)
  324                                 break;
  325                 }
  326         }
  327 
  328         /*
  329          * when the limit pointer is given, do a stricter check on the
  330          * remaining bits.
  331          */
  332         if (p < lim) {
  333                 if (y != 0 && (*p & (0x00ff >> y)) != 0)
  334                         return -1;
  335                 for (p = p + 1; p < lim; p++)
  336                         if (*p != 0)
  337                                 return -1;
  338         }
  339 
  340         return x * NBBY + y;
  341 }
  342 
  343 #define ifa2ia6(ifa)    ((struct in6_ifaddr *)(ifa))
  344 #define ia62ifa(ia6)    (&((ia6)->ia_ifa))
  345 
  346 static int
  347 in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
  348     struct lwp *l, int privileged)
  349 {
  350         struct  in6_ifreq *ifr = (struct in6_ifreq *)data;
  351         struct  in6_ifaddr *ia = NULL;
  352         struct  in6_aliasreq *ifra = (struct in6_aliasreq *)data;
  353         struct sockaddr_in6 *sa6;
  354         int error;
  355         switch (cmd) {
  356         /*
  357          * XXX: Fix me, once we fix SIOCSIFADDR, SIOCIFDSTADDR, etc.
  358          */
  359         case SIOCSIFADDR:
  360         case SIOCSIFDSTADDR:
  361 #ifdef SIOCSIFCONF_X25
  362         case SIOCSIFCONF_X25:
  363 #endif
  364                 return EOPNOTSUPP;
  365         case SIOCGETSGCNT_IN6:
  366         case SIOCGETMIFCNT_IN6:
  367                 return mrt6_ioctl(cmd, data);
  368         }
  369 
  370         if (ifp == NULL)
  371                 return EOPNOTSUPP;
  372 
  373         switch (cmd) {
  374         case SIOCSNDFLUSH_IN6:
  375         case SIOCSPFXFLUSH_IN6:
  376         case SIOCSRTRFLUSH_IN6:
  377         case SIOCSDEFIFACE_IN6:
  378         case SIOCSIFINFO_FLAGS:
  379         case SIOCSIFINFO_IN6:
  380                 if (!privileged)
  381                         return EPERM;
  382                 /* FALLTHROUGH */
  383         case OSIOCGIFINFO_IN6:
  384         case SIOCGIFINFO_IN6:
  385         case SIOCGDRLST_IN6:
  386         case SIOCGPRLST_IN6:
  387         case SIOCGNBRINFO_IN6:
  388         case SIOCGDEFIFACE_IN6:
  389                 return nd6_ioctl(cmd, data, ifp);
  390         }
  391 
  392         switch (cmd) {
  393         case SIOCSIFPREFIX_IN6:
  394         case SIOCDIFPREFIX_IN6:
  395         case SIOCAIFPREFIX_IN6:
  396         case SIOCCIFPREFIX_IN6:
  397         case SIOCSGIFPREFIX_IN6:
  398         case SIOCGIFPREFIX_IN6:
  399                 log(LOG_NOTICE,
  400                     "prefix ioctls are now invalidated. "
  401                     "please use ifconfig.\n");
  402                 return EOPNOTSUPP;
  403         }
  404 
  405         switch (cmd) {
  406         case SIOCALIFADDR:
  407         case SIOCDLIFADDR:
  408                 if (!privileged)
  409                         return EPERM;
  410                 /* FALLTHROUGH */
  411         case SIOCGLIFADDR:
  412                 return in6_lifaddr_ioctl(so, cmd, data, ifp, l);
  413         }
  414 
  415         /*
  416          * Find address for this interface, if it exists.
  417          *
  418          * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation
  419          * only, and used the first interface address as the target of other
  420          * operations (without checking ifra_addr).  This was because netinet
  421          * code/API assumed at most 1 interface address per interface.
  422          * Since IPv6 allows a node to assign multiple addresses
  423          * on a single interface, we almost always look and check the
  424          * presence of ifra_addr, and reject invalid ones here.
  425          * It also decreases duplicated code among SIOC*_IN6 operations.
  426          */
  427         switch (cmd) {
  428         case SIOCAIFADDR_IN6:
  429         case SIOCSIFPHYADDR_IN6:
  430                 sa6 = &ifra->ifra_addr;
  431                 break;
  432         case SIOCSIFADDR_IN6:
  433         case SIOCGIFADDR_IN6:
  434         case SIOCSIFDSTADDR_IN6:
  435         case SIOCSIFNETMASK_IN6:
  436         case SIOCGIFDSTADDR_IN6:
  437         case SIOCGIFNETMASK_IN6:
  438         case SIOCDIFADDR_IN6:
  439         case SIOCGIFPSRCADDR_IN6:
  440         case SIOCGIFPDSTADDR_IN6:
  441         case SIOCGIFAFLAG_IN6:
  442         case SIOCSNDFLUSH_IN6:
  443         case SIOCSPFXFLUSH_IN6:
  444         case SIOCSRTRFLUSH_IN6:
  445         case SIOCGIFALIFETIME_IN6:
  446         case SIOCGIFSTAT_IN6:
  447         case SIOCGIFSTAT_ICMP6:
  448                 sa6 = &ifr->ifr_addr;
  449                 break;
  450         default:
  451                 sa6 = NULL;
  452                 break;
  453         }
  454         if (sa6 && sa6->sin6_family == AF_INET6) {
  455                 if (sa6->sin6_scope_id != 0)
  456                         error = sa6_embedscope(sa6, 0);
  457                 else
  458                         error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
  459                 if (error != 0)
  460                         return error;
  461                 ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
  462         } else
  463                 ia = NULL;
  464 
  465         switch (cmd) {
  466         case SIOCSIFADDR_IN6:
  467         case SIOCSIFDSTADDR_IN6:
  468         case SIOCSIFNETMASK_IN6:
  469                 /*
  470                  * Since IPv6 allows a node to assign multiple addresses
  471                  * on a single interface, SIOCSIFxxx ioctls are deprecated.
  472                  */
  473                 return EINVAL;
  474 
  475         case SIOCDIFADDR_IN6:
  476                 /*
  477                  * for IPv4, we look for existing in_ifaddr here to allow
  478                  * "ifconfig if0 delete" to remove the first IPv4 address on
  479                  * the interface.  For IPv6, as the spec allows multiple
  480                  * interface address from the day one, we consider "remove the
  481                  * first one" semantics to be not preferable.
  482                  */
  483                 if (ia == NULL)
  484                         return EADDRNOTAVAIL;
  485                 /* FALLTHROUGH */
  486         case SIOCAIFADDR_IN6:
  487                 /*
  488                  * We always require users to specify a valid IPv6 address for
  489                  * the corresponding operation.
  490                  */
  491                 if (ifra->ifra_addr.sin6_family != AF_INET6 ||
  492                     ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
  493                         return EAFNOSUPPORT;
  494                 if (!privileged)
  495                         return EPERM;
  496 
  497                 break;
  498 
  499         case SIOCGIFADDR_IN6:
  500                 /* This interface is basically deprecated. use SIOCGIFCONF. */
  501                 /* FALLTHROUGH */
  502         case SIOCGIFAFLAG_IN6:
  503         case SIOCGIFNETMASK_IN6:
  504         case SIOCGIFDSTADDR_IN6:
  505         case SIOCGIFALIFETIME_IN6:
  506                 /* must think again about its semantics */
  507                 if (ia == NULL)
  508                         return EADDRNOTAVAIL;
  509                 break;
  510         }
  511 
  512         switch (cmd) {
  513 
  514         case SIOCGIFADDR_IN6:
  515                 ifr->ifr_addr = ia->ia_addr;
  516                 if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
  517                         return error;
  518                 break;
  519 
  520         case SIOCGIFDSTADDR_IN6:
  521                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  522                         return EINVAL;
  523                 /*
  524                  * XXX: should we check if ifa_dstaddr is NULL and return
  525                  * an error?
  526                  */
  527                 ifr->ifr_dstaddr = ia->ia_dstaddr;
  528                 if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
  529                         return error;
  530                 break;
  531 
  532         case SIOCGIFNETMASK_IN6:
  533                 ifr->ifr_addr = ia->ia_prefixmask;
  534                 break;
  535 
  536         case SIOCGIFAFLAG_IN6:
  537                 ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
  538                 break;
  539 
  540         case SIOCGIFSTAT_IN6:
  541                 if (ifp == NULL)
  542                         return EINVAL;
  543                 bzero(&ifr->ifr_ifru.ifru_stat,
  544                     sizeof(ifr->ifr_ifru.ifru_stat));
  545                 ifr->ifr_ifru.ifru_stat =
  546                     *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
  547                 break;
  548 
  549         case SIOCGIFSTAT_ICMP6:
  550                 if (ifp == NULL)
  551                         return EINVAL;
  552                 bzero(&ifr->ifr_ifru.ifru_icmp6stat,
  553                     sizeof(ifr->ifr_ifru.ifru_icmp6stat));
  554                 ifr->ifr_ifru.ifru_icmp6stat =
  555                     *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
  556                 break;
  557 
  558         case SIOCGIFALIFETIME_IN6:
  559                 ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
  560                 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
  561                         time_t maxexpire;
  562                         struct in6_addrlifetime *retlt =
  563                             &ifr->ifr_ifru.ifru_lifetime;
  564 
  565                         /*
  566                          * XXX: adjust expiration time assuming time_t is
  567                          * signed.
  568                          */
  569                         maxexpire = ((time_t)~0) &
  570                             ~((time_t)1 << ((sizeof(maxexpire) * NBBY) - 1));
  571                         if (ia->ia6_lifetime.ia6t_vltime <
  572                             maxexpire - ia->ia6_updatetime) {
  573                                 retlt->ia6t_expire = ia->ia6_updatetime +
  574                                     ia->ia6_lifetime.ia6t_vltime;
  575                         } else
  576                                 retlt->ia6t_expire = maxexpire;
  577                 }
  578                 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
  579                         time_t maxexpire;
  580                         struct in6_addrlifetime *retlt =
  581                             &ifr->ifr_ifru.ifru_lifetime;
  582 
  583                         /*
  584                          * XXX: adjust expiration time assuming time_t is
  585                          * signed.
  586                          */
  587                         maxexpire = ((time_t)~0) &
  588                             ~((time_t)1 << ((sizeof(maxexpire) * NBBY) - 1));
  589                         if (ia->ia6_lifetime.ia6t_pltime <
  590                             maxexpire - ia->ia6_updatetime) {
  591                                 retlt->ia6t_preferred = ia->ia6_updatetime +
  592                                     ia->ia6_lifetime.ia6t_pltime;
  593                         } else
  594                                 retlt->ia6t_preferred = maxexpire;
  595                 }
  596                 break;
  597 
  598         case SIOCAIFADDR_IN6:
  599         {
  600                 int i;
  601                 struct nd_prefixctl pr0;
  602                 struct nd_prefix *pr;
  603 
  604                 /* reject read-only flags */
  605                 if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
  606                     (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
  607                     (ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
  608                     (ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
  609                         return EINVAL;
  610                 }
  611                 /*
  612                  * first, make or update the interface address structure,
  613                  * and link it to the list.
  614                  */
  615                 if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
  616                         return error;
  617                 if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
  618                     == NULL) {
  619                         /*
  620                          * this can happen when the user specify the 0 valid
  621                          * lifetime.
  622                          */
  623                         break;
  624                 }
  625 
  626                 /*
  627                  * then, make the prefix on-link on the interface.
  628                  * XXX: we'd rather create the prefix before the address, but
  629                  * we need at least one address to install the corresponding
  630                  * interface route, so we configure the address first.
  631                  */
  632 
  633                 /*
  634                  * convert mask to prefix length (prefixmask has already
  635                  * been validated in in6_update_ifa().
  636                  */
  637                 bzero(&pr0, sizeof(pr0));
  638                 pr0.ndpr_ifp = ifp;
  639                 pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
  640                     NULL);
  641                 if (pr0.ndpr_plen == 128) {
  642                         break;  /* we don't need to install a host route. */
  643                 }
  644                 pr0.ndpr_prefix = ifra->ifra_addr;
  645                 /* apply the mask for safety. */
  646                 for (i = 0; i < 4; i++) {
  647                         pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
  648                             ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
  649                 }
  650                 /*
  651                  * XXX: since we don't have an API to set prefix (not address)
  652                  * lifetimes, we just use the same lifetimes as addresses.
  653                  * The (temporarily) installed lifetimes can be overridden by
  654                  * later advertised RAs (when accept_rtadv is non 0), which is
  655                  * an intended behavior.
  656                  */
  657                 pr0.ndpr_raf_onlink = 1; /* should be configurable? */
  658                 pr0.ndpr_raf_auto =
  659                     ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
  660                 pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
  661                 pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
  662 
  663                 /* add the prefix if not yet. */
  664                 if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
  665                         /*
  666                          * nd6_prelist_add will install the corresponding
  667                          * interface route.
  668                          */
  669                         if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
  670                                 return error;
  671                         if (pr == NULL) {
  672                                 log(LOG_ERR, "nd6_prelist_add succeeded but "
  673                                     "no prefix\n");
  674                                 return EINVAL; /* XXX panic here? */
  675                         }
  676                 }
  677 
  678                 /* relate the address to the prefix */
  679                 if (ia->ia6_ndpr == NULL) {
  680                         ia->ia6_ndpr = pr;
  681                         pr->ndpr_refcnt++;
  682 
  683                         /*
  684                          * If this is the first autoconf address from the
  685                          * prefix, create a temporary address as well
  686                          * (when required).
  687                          */
  688                         if ((ia->ia6_flags & IN6_IFF_AUTOCONF) &&
  689                             ip6_use_tempaddr && pr->ndpr_refcnt == 1) {
  690                                 int e;
  691                                 if ((e = in6_tmpifadd(ia, 1, 0)) != 0) {
  692                                         log(LOG_NOTICE, "in6_control: failed "
  693                                             "to create a temporary address, "
  694                                             "errno=%d\n", e);
  695                                 }
  696                         }
  697                 }
  698 
  699                 /*
  700                  * this might affect the status of autoconfigured addresses,
  701                  * that is, this address might make other addresses detached.
  702                  */
  703                 pfxlist_onlink_check();
  704 
  705 #ifdef PFIL_HOOKS
  706                 (void)pfil_run_hooks(&if_pfil, (struct mbuf **)SIOCAIFADDR_IN6,
  707                     ifp, PFIL_IFADDR);
  708 #endif
  709 
  710                 break;
  711         }
  712 
  713         case SIOCDIFADDR_IN6:
  714         {
  715                 struct nd_prefix *pr;
  716 
  717                 /*
  718                  * If the address being deleted is the only one that owns
  719                  * the corresponding prefix, expire the prefix as well.
  720                  * XXX: theoretically, we don't have to worry about such
  721                  * relationship, since we separate the address management
  722                  * and the prefix management.  We do this, however, to provide
  723                  * as much backward compatibility as possible in terms of
  724                  * the ioctl operation.
  725                  * Note that in6_purgeaddr() will decrement ndpr_refcnt.
  726                  */
  727                 pr = ia->ia6_ndpr;
  728                 in6_purgeaddr(&ia->ia_ifa);
  729                 if (pr && pr->ndpr_refcnt == 0)
  730                         prelist_remove(pr);
  731 #ifdef PFIL_HOOKS
  732                 (void)pfil_run_hooks(&if_pfil, (struct mbuf **)SIOCDIFADDR_IN6,
  733                     ifp, PFIL_IFADDR);
  734 #endif
  735                 break;
  736         }
  737 
  738         default:
  739                 if (ifp == NULL || ifp->if_ioctl == 0)
  740                         return EOPNOTSUPP;
  741                 error = ((*ifp->if_ioctl)(ifp, cmd, data));
  742                 return error;
  743         }
  744 
  745         return 0;
  746 }
  747 
  748 int
  749 in6_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
  750     struct lwp *l)
  751 {
  752         int error, privileged, s;
  753 
  754         privileged = 0;
  755         if (l && !kauth_authorize_generic(l->l_cred,
  756             KAUTH_GENERIC_ISSUSER, NULL))
  757                 privileged++;
  758 
  759         s = splnet();
  760         error = in6_control1(so , cmd, data, ifp, l, privileged);
  761         splx(s);
  762         return error;
  763 }
  764 
  765 /*
  766  * Update parameters of an IPv6 interface address.
  767  * If necessary, a new entry is created and linked into address chains.
  768  * This function is separated from in6_control().
  769  * XXX: should this be performed under splnet()?
  770  */
  771 static int
  772 in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra,
  773     struct in6_ifaddr *ia, int flags)
  774 {
  775         int error = 0, hostIsNew = 0, plen = -1;
  776         struct in6_ifaddr *oia;
  777         struct sockaddr_in6 dst6;
  778         struct in6_addrlifetime *lt;
  779         struct in6_multi_mship *imm;
  780         struct in6_multi *in6m_sol;
  781         struct rtentry *rt;
  782         int dad_delay;
  783 
  784         in6m_sol = NULL;
  785 
  786         /* Validate parameters */
  787         if (ifp == NULL || ifra == NULL) /* this maybe redundant */
  788                 return EINVAL;
  789 
  790         /*
  791          * The destination address for a p2p link must have a family
  792          * of AF_UNSPEC or AF_INET6.
  793          */
  794         if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
  795             ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
  796             ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
  797                 return EAFNOSUPPORT;
  798         /*
  799          * validate ifra_prefixmask.  don't check sin6_family, netmask
  800          * does not carry fields other than sin6_len.
  801          */
  802         if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
  803                 return EINVAL;
  804         /*
  805          * Because the IPv6 address architecture is classless, we require
  806          * users to specify a (non 0) prefix length (mask) for a new address.
  807          * We also require the prefix (when specified) mask is valid, and thus
  808          * reject a non-consecutive mask.
  809          */
  810         if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
  811                 return EINVAL;
  812         if (ifra->ifra_prefixmask.sin6_len != 0) {
  813                 plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
  814                     (u_char *)&ifra->ifra_prefixmask +
  815                     ifra->ifra_prefixmask.sin6_len);
  816                 if (plen <= 0)
  817                         return EINVAL;
  818         } else {
  819                 /*
  820                  * In this case, ia must not be NULL.  We just use its prefix
  821                  * length.
  822                  */
  823                 plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
  824         }
  825         /*
  826          * If the destination address on a p2p interface is specified,
  827          * and the address is a scoped one, validate/set the scope
  828          * zone identifier.
  829          */
  830         dst6 = ifra->ifra_dstaddr;
  831         if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
  832             (dst6.sin6_family == AF_INET6)) {
  833                 struct in6_addr in6_tmp;
  834                 u_int32_t zoneid;
  835 
  836                 in6_tmp = dst6.sin6_addr;
  837                 if (in6_setscope(&in6_tmp, ifp, &zoneid))
  838                         return EINVAL; /* XXX: should be impossible */
  839 
  840                 if (dst6.sin6_scope_id != 0) {
  841                         if (dst6.sin6_scope_id != zoneid)
  842                                 return EINVAL;
  843                 } else          /* user omit to specify the ID. */
  844                         dst6.sin6_scope_id = zoneid;
  845 
  846                 /* convert into the internal form */
  847                 if (sa6_embedscope(&dst6, 0))
  848                         return EINVAL; /* XXX: should be impossible */
  849         }
  850         /*
  851          * The destination address can be specified only for a p2p or a
  852          * loopback interface.  If specified, the corresponding prefix length
  853          * must be 128.
  854          */
  855         if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
  856 #ifdef FORCE_P2PPLEN
  857                 int i;
  858 #endif
  859 
  860                 if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
  861                         /* XXX: noisy message */
  862                         nd6log((LOG_INFO, "in6_update_ifa: a destination can "
  863                             "be specified for a p2p or a loopback IF only\n"));
  864                         return EINVAL;
  865                 }
  866                 if (plen != 128) {
  867                         nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
  868                             "be 128 when dstaddr is specified\n"));
  869 #ifdef FORCE_P2PPLEN
  870                         /*
  871                          * To be compatible with old configurations,
  872                          * such as ifconfig gif0 inet6 2001::1 2001::2
  873                          * prefixlen 126, we override the specified
  874                          * prefixmask as if the prefix length was 128.
  875                          */
  876                         ifra->ifra_prefixmask.sin6_len =
  877                             sizeof(struct sockaddr_in6);
  878                         for (i = 0; i < 4; i++)
  879                                 ifra->ifra_prefixmask.sin6_addr.s6_addr32[i] =
  880                                     0xffffffff;
  881                         plen = 128;
  882 #else
  883                         return EINVAL;
  884 #endif
  885                 }
  886         }
  887         /* lifetime consistency check */
  888         lt = &ifra->ifra_lifetime;
  889         if (lt->ia6t_pltime > lt->ia6t_vltime)
  890                 return EINVAL;
  891         if (lt->ia6t_vltime == 0) {
  892                 /*
  893                  * the following log might be noisy, but this is a typical
  894                  * configuration mistake or a tool's bug.
  895                  */
  896                 nd6log((LOG_INFO,
  897                     "in6_update_ifa: valid lifetime is 0 for %s\n",
  898                     ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
  899 
  900                 if (ia == NULL)
  901                         return 0; /* there's nothing to do */
  902         }
  903 
  904         /*
  905          * If this is a new address, allocate a new ifaddr and link it
  906          * into chains.
  907          */
  908         if (ia == NULL) {
  909                 hostIsNew = 1;
  910                 /*
  911                  * When in6_update_ifa() is called in a process of a received
  912                  * RA, it is called under an interrupt context.  So, we should
  913                  * call malloc with M_NOWAIT.
  914                  */
  915                 ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
  916                     M_NOWAIT);
  917                 if (ia == NULL)
  918                         return ENOBUFS;
  919                 bzero((void *)ia, sizeof(*ia));
  920                 LIST_INIT(&ia->ia6_memberships);
  921                 /* Initialize the address and masks, and put time stamp */
  922                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  923                 ia->ia_addr.sin6_family = AF_INET6;
  924                 ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
  925                 ia->ia6_createtime = time_second;
  926                 if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
  927                         /*
  928                          * XXX: some functions expect that ifa_dstaddr is not
  929                          * NULL for p2p interfaces.
  930                          */
  931                         ia->ia_ifa.ifa_dstaddr =
  932                             (struct sockaddr *)&ia->ia_dstaddr;
  933                 } else {
  934                         ia->ia_ifa.ifa_dstaddr = NULL;
  935                 }
  936                 ia->ia_ifa.ifa_netmask =
  937                     (struct sockaddr *)&ia->ia_prefixmask;
  938 
  939                 ia->ia_ifp = ifp;
  940                 if ((oia = in6_ifaddr) != NULL) {
  941                         for ( ; oia->ia_next; oia = oia->ia_next)
  942                                 continue;
  943                         oia->ia_next = ia;
  944                 } else
  945                         in6_ifaddr = ia;
  946                 /* gain a refcnt for the link from in6_ifaddr */
  947                 IFAREF(&ia->ia_ifa);
  948 
  949                 ifa_insert(ifp, &ia->ia_ifa);
  950         }
  951 
  952         /* update timestamp */
  953         ia->ia6_updatetime = time_second;
  954 
  955         /* set prefix mask */
  956         if (ifra->ifra_prefixmask.sin6_len) {
  957                 /*
  958                  * We prohibit changing the prefix length of an existing
  959                  * address, because
  960                  * + such an operation should be rare in IPv6, and
  961                  * + the operation would confuse prefix management.
  962                  */
  963                 if (ia->ia_prefixmask.sin6_len &&
  964                     in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
  965                         nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
  966                             " existing (%s) address should not be changed\n",
  967                             ip6_sprintf(&ia->ia_addr.sin6_addr)));
  968                         error = EINVAL;
  969                         goto unlink;
  970                 }
  971                 ia->ia_prefixmask = ifra->ifra_prefixmask;
  972         }
  973 
  974         /*
  975          * If a new destination address is specified, scrub the old one and
  976          * install the new destination.  Note that the interface must be
  977          * p2p or loopback (see the check above.)
  978          */
  979         if (dst6.sin6_family == AF_INET6 &&
  980             !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
  981                 if ((ia->ia_flags & IFA_ROUTE) != 0 &&
  982                     rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST) != 0) {
  983                         nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
  984                             "a route to the old destination: %s\n",
  985                             ip6_sprintf(&ia->ia_addr.sin6_addr)));
  986                         /* proceed anyway... */
  987                 } else
  988                         ia->ia_flags &= ~IFA_ROUTE;
  989                 ia->ia_dstaddr = dst6;
  990         }
  991 
  992         /*
  993          * Set lifetimes.  We do not refer to ia6t_expire and ia6t_preferred
  994          * to see if the address is deprecated or invalidated, but initialize
  995          * these members for applications.
  996          */
  997         ia->ia6_lifetime = ifra->ifra_lifetime;
  998         if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
  999                 ia->ia6_lifetime.ia6t_expire =
 1000                     time_second + ia->ia6_lifetime.ia6t_vltime;
 1001         } else
 1002                 ia->ia6_lifetime.ia6t_expire = 0;
 1003         if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
 1004                 ia->ia6_lifetime.ia6t_preferred =
 1005                     time_second + ia->ia6_lifetime.ia6t_pltime;
 1006         } else
 1007                 ia->ia6_lifetime.ia6t_preferred = 0;
 1008 
 1009         /* reset the interface and routing table appropriately. */
 1010         if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
 1011                 goto unlink;
 1012 
 1013         /*
 1014          * configure address flags.
 1015          */
 1016         ia->ia6_flags = ifra->ifra_flags;
 1017         /*
 1018          * backward compatibility - if IN6_IFF_DEPRECATED is set from the
 1019          * userland, make it deprecated.
 1020          */
 1021         if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
 1022                 ia->ia6_lifetime.ia6t_pltime = 0;
 1023                 ia->ia6_lifetime.ia6t_preferred = time_second;
 1024         }
 1025 
 1026         /*
 1027          * Make the address tentative before joining multicast addresses,
 1028          * so that corresponding MLD responses would not have a tentative
 1029          * source address.
 1030          */
 1031         ia->ia6_flags &= ~IN6_IFF_DUPLICATED;   /* safety */
 1032         if (hostIsNew && in6if_do_dad(ifp)) 
 1033                 ia->ia6_flags |= IN6_IFF_TENTATIVE;
 1034 
 1035         /*
 1036          * We are done if we have simply modified an existing address.
 1037          */
 1038         if (!hostIsNew)
 1039                 return error;
 1040 
 1041         /*
 1042          * Beyond this point, we should call in6_purgeaddr upon an error,
 1043          * not just go to unlink.
 1044          */
 1045 
 1046         /* join necessary multicast groups */
 1047         if ((ifp->if_flags & IFF_MULTICAST) != 0) {
 1048                 struct sockaddr_in6 mltaddr, mltmask;
 1049                 struct in6_addr llsol;
 1050 
 1051                 /* join solicited multicast addr for new host id */
 1052                 bzero(&llsol, sizeof(struct in6_addr));
 1053                 llsol.s6_addr16[0] = htons(0xff02);
 1054                 llsol.s6_addr32[1] = 0;
 1055                 llsol.s6_addr32[2] = htonl(1);
 1056                 llsol.s6_addr32[3] = ifra->ifra_addr.sin6_addr.s6_addr32[3];
 1057                 llsol.s6_addr8[12] = 0xff;
 1058                 if ((error = in6_setscope(&llsol, ifp, NULL)) != 0) {
 1059                         /* XXX: should not happen */
 1060                         log(LOG_ERR, "in6_update_ifa: "
 1061                             "in6_setscope failed\n");
 1062                         goto cleanup;
 1063                 }
 1064                 dad_delay = 0;
 1065                 if ((flags & IN6_IFAUPDATE_DADDELAY)) {
 1066                         /*
 1067                          * We need a random delay for DAD on the address
 1068                          * being configured.  It also means delaying
 1069                          * transmission of the corresponding MLD report to
 1070                          * avoid report collision.
 1071                          * [draft-ietf-ipv6-rfc2462bis-02.txt]
 1072                          */
 1073                         dad_delay = arc4random() %
 1074                             (MAX_RTR_SOLICITATION_DELAY * hz);
 1075                 }
 1076 
 1077 #define MLTMASK_LEN  4  /* mltmask's masklen (=32bit=4octet) */
 1078                 /* join solicited multicast addr for new host id */
 1079                 imm = in6_joingroup(ifp, &llsol, &error, dad_delay);
 1080                 if (!imm) {
 1081                         nd6log((LOG_ERR,
 1082                             "in6_update_ifa: addmulti "
 1083                             "failed for %s on %s (errno=%d)\n",
 1084                             ip6_sprintf(&llsol), if_name(ifp), error));
 1085                         goto cleanup;
 1086                 }
 1087                 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
 1088                 in6m_sol = imm->i6mm_maddr;
 1089 
 1090                 sockaddr_in6_init(&mltmask, &in6mask32, 0, 0, 0);
 1091 
 1092                 /*
 1093                  * join link-local all-nodes address
 1094                  */
 1095                 sockaddr_in6_init(&mltaddr, &in6addr_linklocal_allnodes,
 1096                     0, 0, 0);
 1097                 if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0)
 1098                         goto cleanup; /* XXX: should not fail */
 1099 
 1100                 /*
 1101                  * XXX: do we really need this automatic routes?
 1102                  * We should probably reconsider this stuff.  Most applications
 1103                  * actually do not need the routes, since they usually specify
 1104                  * the outgoing interface.
 1105                  */
 1106                 rt = rtalloc1((struct sockaddr *)&mltaddr, 0);
 1107                 if (rt) {
 1108                         if (memcmp(&mltaddr.sin6_addr,
 1109                             &satocsin6(rt_getkey(rt))->sin6_addr,
 1110                             MLTMASK_LEN)) {
 1111                                 RTFREE(rt);
 1112                                 rt = NULL;
 1113                         } else if (rt->rt_ifp != ifp) {
 1114                                 IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
 1115                                     "network %04x:%04x::/32 = %04x:%04x::/32\n",
 1116                                     __func__, rt->rt_ifp, ifp, ifp->if_xname,
 1117                                     ntohs(mltaddr.sin6_addr.s6_addr16[0]),
 1118                                     ntohs(mltaddr.sin6_addr.s6_addr16[1]),
 1119                                     satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
 1120                                     satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
 1121                                 rt_replace_ifa(rt, &ia->ia_ifa);
 1122                                 rt->rt_ifp = ifp;
 1123                         }
 1124                 }
 1125                 if (!rt) {
 1126                         struct rt_addrinfo info;
 1127 
 1128                         bzero(&info, sizeof(info));
 1129                         info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
 1130                         info.rti_info[RTAX_GATEWAY] =
 1131                             (struct sockaddr *)&ia->ia_addr;
 1132                         info.rti_info[RTAX_NETMASK] =
 1133                             (struct sockaddr *)&mltmask;
 1134                         info.rti_info[RTAX_IFA] =
 1135                             (struct sockaddr *)&ia->ia_addr;
 1136                         /* XXX: we need RTF_CLONING to fake nd6_rtrequest */
 1137                         info.rti_flags = RTF_UP | RTF_CLONING;
 1138                         error = rtrequest1(RTM_ADD, &info, NULL);
 1139                         if (error)
 1140                                 goto cleanup;
 1141                 } else {
 1142                         RTFREE(rt);
 1143                 }
 1144                 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
 1145                 if (!imm) {
 1146                         nd6log((LOG_WARNING,
 1147                             "in6_update_ifa: addmulti failed for "
 1148                             "%s on %s (errno=%d)\n",
 1149                             ip6_sprintf(&mltaddr.sin6_addr),
 1150                             if_name(ifp), error));
 1151                         goto cleanup;
 1152                 }
 1153                 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
 1154 
 1155                 /*
 1156                  * join node information group address
 1157                  */
 1158                 dad_delay = 0;
 1159                 if ((flags & IN6_IFAUPDATE_DADDELAY)) {
 1160                         /*
 1161                          * The spec doesn't say anything about delay for this
 1162                          * group, but the same logic should apply.
 1163                          */
 1164                         dad_delay = arc4random() %
 1165                             (MAX_RTR_SOLICITATION_DELAY * hz);
 1166                 }
 1167                 if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) != 0)
 1168                         ;
 1169                 else if ((imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error,
 1170                           dad_delay)) == NULL) { /* XXX jinmei */
 1171                         nd6log((LOG_WARNING, "in6_update_ifa: "
 1172                             "addmulti failed for %s on %s (errno=%d)\n",
 1173                             ip6_sprintf(&mltaddr.sin6_addr),
 1174                             if_name(ifp), error));
 1175                         /* XXX not very fatal, go on... */
 1176                 } else {
 1177                         LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
 1178                 }
 1179 
 1180 
 1181                 /*
 1182                  * join interface-local all-nodes address.
 1183                  * (ff01::1%ifN, and ff01::%ifN/32)
 1184                  */
 1185                 mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
 1186                 if ((error = in6_setscope(&mltaddr.sin6_addr, ifp, NULL)) != 0) 
 1187                         goto cleanup; /* XXX: should not fail */
 1188 
 1189                 /* XXX: again, do we really need the route? */
 1190                 rt = rtalloc1((struct sockaddr *)&mltaddr, 0);
 1191                 if (rt) {
 1192                         /* 32bit came from "mltmask" */
 1193                         if (memcmp(&mltaddr.sin6_addr,
 1194                             &satocsin6(rt_getkey(rt))->sin6_addr,
 1195                             32 / NBBY)) {
 1196                                 RTFREE(rt);
 1197                                 rt = NULL;
 1198                         } else if (rt->rt_ifp != ifp) {
 1199                                 IN6_DPRINTF("%s: rt_ifp %p -> %p (%s) "
 1200                                     "network %04x:%04x::/32 = %04x:%04x::/32\n",
 1201                                     __func__, rt->rt_ifp, ifp, ifp->if_xname,
 1202                                     ntohs(mltaddr.sin6_addr.s6_addr16[0]),
 1203                                     ntohs(mltaddr.sin6_addr.s6_addr16[1]),
 1204                                     satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[0],
 1205                                     satocsin6(rt_getkey(rt))->sin6_addr.s6_addr16[1]);
 1206                                 rt_replace_ifa(rt, &ia->ia_ifa);
 1207                                 rt->rt_ifp = ifp;
 1208                         }
 1209                 }
 1210                 if (!rt) {
 1211                         struct rt_addrinfo info;
 1212 
 1213                         bzero(&info, sizeof(info));
 1214                         info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
 1215                         info.rti_info[RTAX_GATEWAY] =
 1216                             (struct sockaddr *)&ia->ia_addr;
 1217                         info.rti_info[RTAX_NETMASK] =
 1218                             (struct sockaddr *)&mltmask;
 1219                         info.rti_info[RTAX_IFA] =
 1220                             (struct sockaddr *)&ia->ia_addr;
 1221                         info.rti_flags = RTF_UP | RTF_CLONING;
 1222                         error = rtrequest1(RTM_ADD, &info, NULL);
 1223                         if (error)
 1224                                 goto cleanup;
 1225 #undef  MLTMASK_LEN
 1226                 } else {
 1227                         RTFREE(rt);
 1228                 }
 1229                 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0);
 1230                 if (!imm) {
 1231                         nd6log((LOG_WARNING, "in6_update_ifa: "
 1232                             "addmulti failed for %s on %s (errno=%d)\n",
 1233                             ip6_sprintf(&mltaddr.sin6_addr),
 1234                             if_name(ifp), error));
 1235                         goto cleanup;
 1236                 } else {
 1237                         LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
 1238                 }
 1239         }
 1240 
 1241         /*
 1242          * Perform DAD, if needed.
 1243          * XXX It may be of use, if we can administratively
 1244          * disable DAD.
 1245          */
 1246         if (hostIsNew && in6if_do_dad(ifp) &&
 1247             ((ifra->ifra_flags & IN6_IFF_NODAD) == 0) &&
 1248             (ia->ia6_flags & IN6_IFF_TENTATIVE))
 1249         {
 1250                 int mindelay, maxdelay;
 1251 
 1252                 dad_delay = 0;
 1253                 if ((flags & IN6_IFAUPDATE_DADDELAY)) {
 1254                         /*
 1255                          * We need to impose a delay before sending an NS
 1256                          * for DAD.  Check if we also needed a delay for the
 1257                          * corresponding MLD message.  If we did, the delay
 1258                          * should be larger than the MLD delay (this could be
 1259                          * relaxed a bit, but this simple logic is at least
 1260                          * safe).
 1261                          */
 1262                         mindelay = 0;
 1263                         if (in6m_sol != NULL &&
 1264                             in6m_sol->in6m_state == MLD_REPORTPENDING) {
 1265                                 mindelay = in6m_sol->in6m_timer;
 1266                         }
 1267                         maxdelay = MAX_RTR_SOLICITATION_DELAY * hz;
 1268                         if (maxdelay - mindelay == 0)
 1269                                 dad_delay = 0;
 1270                         else {
 1271                                 dad_delay =
 1272                                     (arc4random() % (maxdelay - mindelay)) +
 1273                                     mindelay;
 1274                         }
 1275                 }
 1276                 nd6_dad_start((struct ifaddr *)ia, dad_delay);
 1277         }
 1278 
 1279         return error;
 1280 
 1281   unlink:
 1282         /*
 1283          * XXX: if a change of an existing address failed, keep the entry
 1284          * anyway.
 1285          */
 1286         if (hostIsNew)
 1287                 in6_unlink_ifa(ia, ifp);
 1288         return error;
 1289 
 1290   cleanup:
 1291         in6_purgeaddr(&ia->ia_ifa);
 1292         return error;
 1293 }
 1294 
 1295 int
 1296 in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
 1297     struct in6_ifaddr *ia, int flags)
 1298 {
 1299         int rc, s;
 1300 
 1301         s = splnet();
 1302         rc = in6_update_ifa1(ifp, ifra, ia, flags);
 1303         splx(s);
 1304         return rc;
 1305 }
 1306 
 1307 void
 1308 in6_purgeaddr(struct ifaddr *ifa)
 1309 {
 1310         struct ifnet *ifp = ifa->ifa_ifp;
 1311         struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
 1312         struct in6_multi_mship *imm;
 1313 
 1314         /* stop DAD processing */
 1315         nd6_dad_stop(ifa);
 1316 
 1317         /*
 1318          * delete route to the destination of the address being purged.
 1319          * The interface must be p2p or loopback in this case.
 1320          */
 1321         if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
 1322                 int e;
 1323 
 1324                 if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
 1325                     != 0) {
 1326                         log(LOG_ERR, "in6_purgeaddr: failed to remove "
 1327                             "a route to the p2p destination: %s on %s, "
 1328                             "errno=%d\n",
 1329                             ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp),
 1330                             e);
 1331                         /* proceed anyway... */
 1332                 } else
 1333                         ia->ia_flags &= ~IFA_ROUTE;
 1334         }
 1335 
 1336         /* Remove ownaddr's loopback rtentry, if it exists. */
 1337         in6_ifremloop(&(ia->ia_ifa));
 1338 
 1339         /*
 1340          * leave from multicast groups we have joined for the interface
 1341          */
 1342         while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
 1343                 LIST_REMOVE(imm, i6mm_chain);
 1344                 in6_leavegroup(imm);
 1345         }
 1346 
 1347         in6_unlink_ifa(ia, ifp);
 1348 }
 1349 
 1350 static void
 1351 in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
 1352 {
 1353         struct in6_ifaddr *oia;
 1354         int     s = splnet();
 1355 
 1356         ifa_remove(ifp, &ia->ia_ifa);
 1357 
 1358         oia = ia;
 1359         if (oia == (ia = in6_ifaddr))
 1360                 in6_ifaddr = ia->ia_next;
 1361         else {
 1362                 while (ia->ia_next && (ia->ia_next != oia))
 1363                         ia = ia->ia_next;
 1364                 if (ia->ia_next)
 1365                         ia->ia_next = oia->ia_next;
 1366                 else {
 1367                         /* search failed */
 1368                         printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
 1369                 }
 1370         }
 1371 
 1372         /*
 1373          * XXX thorpej@NetBSD.org -- if the interface is going
 1374          * XXX away, don't save the multicast entries, delete them!
 1375          */
 1376         if (LIST_EMPTY(&oia->ia6_multiaddrs))
 1377                 ;
 1378         else if (oia->ia_ifa.ifa_ifp->if_output == if_nulloutput) {
 1379                 struct in6_multi *in6m, *next;
 1380 
 1381                 for (in6m = LIST_FIRST(&oia->ia6_multiaddrs); in6m != NULL;
 1382                      in6m = next) {
 1383                         next = LIST_NEXT(in6m, in6m_entry);
 1384                         in6_delmulti(in6m);
 1385                 }
 1386         } else
 1387                 in6_savemkludge(oia);
 1388 
 1389         /*
 1390          * Release the reference to the base prefix.  There should be a
 1391          * positive reference.
 1392          */
 1393         if (oia->ia6_ndpr == NULL) {
 1394                 nd6log((LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
 1395                     "%p has no prefix\n", oia));
 1396         } else {
 1397                 oia->ia6_ndpr->ndpr_refcnt--;
 1398                 oia->ia6_ndpr = NULL;
 1399         }
 1400 
 1401         /*
 1402          * Also, if the address being removed is autoconf'ed, call
 1403          * pfxlist_onlink_check() since the release might affect the status of
 1404          * other (detached) addresses.
 1405          */
 1406         if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0)
 1407                 pfxlist_onlink_check();
 1408 
 1409         /*
 1410          * release another refcnt for the link from in6_ifaddr.
 1411          * Note that we should decrement the refcnt at least once for all *BSD.
 1412          */
 1413         IFAFREE(&oia->ia_ifa);
 1414 
 1415         splx(s);
 1416 }
 1417 
 1418 void
 1419 in6_purgeif(struct ifnet *ifp)
 1420 {
 1421         if_purgeaddrs(ifp, AF_INET6, in6_purgeaddr);
 1422 
 1423         in6_ifdetach(ifp);
 1424 }
 1425 
 1426 /*
 1427  * SIOC[GAD]LIFADDR.
 1428  *      SIOCGLIFADDR: get first address. (?)
 1429  *      SIOCGLIFADDR with IFLR_PREFIX:
 1430  *              get first address that matches the specified prefix.
 1431  *      SIOCALIFADDR: add the specified address.
 1432  *      SIOCALIFADDR with IFLR_PREFIX:
 1433  *              add the specified prefix, filling hostid part from
 1434  *              the first link-local address.  prefixlen must be <= 64.
 1435  *      SIOCDLIFADDR: delete the specified address.
 1436  *      SIOCDLIFADDR with IFLR_PREFIX:
 1437  *              delete the first address that matches the specified prefix.
 1438  * return values:
 1439  *      EINVAL on invalid parameters
 1440  *      EADDRNOTAVAIL on prefix match failed/specified address not found
 1441  *      other values may be returned from in6_ioctl()
 1442  *
 1443  * NOTE: SIOCALIFADDR(with IFLR_PREFIX set) allows prefixlen less than 64.
 1444  * this is to accommodate address naming scheme other than RFC2374,
 1445  * in the future.
 1446  * RFC2373 defines interface id to be 64bit, but it allows non-RFC2374
 1447  * address encoding scheme. (see figure on page 8)
 1448  */
 1449 static int
 1450 in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data, 
 1451         struct ifnet *ifp, struct lwp *l)
 1452 {
 1453         struct if_laddrreq *iflr = (struct if_laddrreq *)data;
 1454         struct ifaddr *ifa;
 1455         struct sockaddr *sa;
 1456 
 1457         /* sanity checks */
 1458         if (!data || !ifp) {
 1459                 panic("invalid argument to in6_lifaddr_ioctl");
 1460                 /* NOTREACHED */
 1461         }
 1462 
 1463         switch (cmd) {
 1464         case SIOCGLIFADDR:
 1465                 /* address must be specified on GET with IFLR_PREFIX */
 1466                 if ((iflr->flags & IFLR_PREFIX) == 0)
 1467                         break;
 1468                 /* FALLTHROUGH */
 1469         case SIOCALIFADDR:
 1470         case SIOCDLIFADDR:
 1471                 /* address must be specified on ADD and DELETE */
 1472                 sa = (struct sockaddr *)&iflr->addr;
 1473                 if (sa->sa_family != AF_INET6)
 1474                         return EINVAL;
 1475                 if (sa->sa_len != sizeof(struct sockaddr_in6))
 1476                         return EINVAL;
 1477                 /* XXX need improvement */
 1478                 sa = (struct sockaddr *)&iflr->dstaddr;
 1479                 if (sa->sa_family && sa->sa_family != AF_INET6)
 1480                         return EINVAL;
 1481                 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
 1482                         return EINVAL;
 1483                 break;
 1484         default: /* shouldn't happen */
 1485 #if 0
 1486                 panic("invalid cmd to in6_lifaddr_ioctl");
 1487                 /* NOTREACHED */
 1488 #else
 1489                 return EOPNOTSUPP;
 1490 #endif
 1491         }
 1492         if (sizeof(struct in6_addr) * NBBY < iflr->prefixlen)
 1493                 return EINVAL;
 1494 
 1495         switch (cmd) {
 1496         case SIOCALIFADDR:
 1497             {
 1498                 struct in6_aliasreq ifra;
 1499                 struct in6_addr *xhostid = NULL;
 1500                 int prefixlen;
 1501 
 1502                 if ((iflr->flags & IFLR_PREFIX) != 0) {
 1503                         struct sockaddr_in6 *sin6;
 1504 
 1505                         /*
 1506                          * xhostid is to fill in the hostid part of the
 1507                          * address.  xhostid points to the first link-local
 1508                          * address attached to the interface.
 1509                          */
 1510                         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
 1511                         if (!ifa)
 1512                                 return EADDRNOTAVAIL;
 1513                         xhostid = IFA_IN6(ifa);
 1514 
 1515                         /* prefixlen must be <= 64. */
 1516                         if (64 < iflr->prefixlen)
 1517                                 return EINVAL;
 1518                         prefixlen = iflr->prefixlen;
 1519 
 1520                         /* hostid part must be zero. */
 1521                         sin6 = (struct sockaddr_in6 *)&iflr->addr;
 1522                         if (sin6->sin6_addr.s6_addr32[2] != 0
 1523                          || sin6->sin6_addr.s6_addr32[3] != 0) {
 1524                                 return EINVAL;
 1525                         }
 1526                 } else
 1527                         prefixlen = iflr->prefixlen;
 1528 
 1529                 /* copy args to in6_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
 1530                 bzero(&ifra, sizeof(ifra));
 1531                 bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
 1532 
 1533                 bcopy(&iflr->addr, &ifra.ifra_addr,
 1534                     ((struct sockaddr *)&iflr->addr)->sa_len);
 1535                 if (xhostid) {
 1536                         /* fill in hostid part */
 1537                         ifra.ifra_addr.sin6_addr.s6_addr32[2] =
 1538                             xhostid->s6_addr32[2];
 1539                         ifra.ifra_addr.sin6_addr.s6_addr32[3] =
 1540                             xhostid->s6_addr32[3];
 1541                 }
 1542 
 1543                 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /* XXX */
 1544                         bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
 1545                             ((struct sockaddr *)&iflr->dstaddr)->sa_len);
 1546                         if (xhostid) {
 1547                                 ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
 1548                                     xhostid->s6_addr32[2];
 1549                                 ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
 1550                                     xhostid->s6_addr32[3];
 1551                         }
 1552                 }
 1553 
 1554                 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
 1555                 in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
 1556 
 1557                 ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
 1558                 ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
 1559                 ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
 1560                 return in6_control(so, SIOCAIFADDR_IN6, (void *)&ifra, ifp, l);
 1561             }
 1562         case SIOCGLIFADDR:
 1563         case SIOCDLIFADDR:
 1564             {
 1565                 struct in6_ifaddr *ia;
 1566                 struct in6_addr mask, candidate, match;
 1567                 struct sockaddr_in6 *sin6;
 1568                 int cmp;
 1569 
 1570                 bzero(&mask, sizeof(mask));
 1571                 if (iflr->flags & IFLR_PREFIX) {
 1572                         /* lookup a prefix rather than address. */
 1573                         in6_prefixlen2mask(&mask, iflr->prefixlen);
 1574 
 1575                         sin6 = (struct sockaddr_in6 *)&iflr->addr;
 1576                         bcopy(&sin6->sin6_addr, &match, sizeof(match));
 1577                         match.s6_addr32[0] &= mask.s6_addr32[0];
 1578                         match.s6_addr32[1] &= mask.s6_addr32[1];
 1579                         match.s6_addr32[2] &= mask.s6_addr32[2];
 1580                         match.s6_addr32[3] &= mask.s6_addr32[3];
 1581 
 1582                         /* if you set extra bits, that's wrong */
 1583                         if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
 1584                                 return EINVAL;
 1585 
 1586                         cmp = 1;
 1587                 } else {
 1588                         if (cmd == SIOCGLIFADDR) {
 1589                                 /* on getting an address, take the 1st match */
 1590                                 cmp = 0;        /* XXX */
 1591                         } else {
 1592                                 /* on deleting an address, do exact match */
 1593                                 in6_prefixlen2mask(&mask, 128);
 1594                                 sin6 = (struct sockaddr_in6 *)&iflr->addr;
 1595                                 bcopy(&sin6->sin6_addr, &match, sizeof(match));
 1596 
 1597                                 cmp = 1;
 1598                         }
 1599                 }
 1600 
 1601                 IFADDR_FOREACH(ifa, ifp) {
 1602                         if (ifa->ifa_addr->sa_family != AF_INET6)
 1603                                 continue;
 1604                         if (!cmp)
 1605                                 break;
 1606 
 1607                         /*
 1608                          * XXX: this is adhoc, but is necessary to allow
 1609                          * a user to specify fe80::/64 (not /10) for a
 1610                          * link-local address.
 1611                          */
 1612                         bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
 1613                         in6_clearscope(&candidate);
 1614                         candidate.s6_addr32[0] &= mask.s6_addr32[0];
 1615                         candidate.s6_addr32[1] &= mask.s6_addr32[1];
 1616                         candidate.s6_addr32[2] &= mask.s6_addr32[2];
 1617                         candidate.s6_addr32[3] &= mask.s6_addr32[3];
 1618                         if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
 1619                                 break;
 1620                 }
 1621                 if (!ifa)
 1622                         return EADDRNOTAVAIL;
 1623                 ia = ifa2ia6(ifa);
 1624 
 1625                 if (cmd == SIOCGLIFADDR) {
 1626                         int error;
 1627 
 1628                         /* fill in the if_laddrreq structure */
 1629                         bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
 1630                         error = sa6_recoverscope(
 1631                             (struct sockaddr_in6 *)&iflr->addr);
 1632                         if (error != 0)
 1633                                 return error;
 1634 
 1635                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
 1636                                 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
 1637                                     ia->ia_dstaddr.sin6_len);
 1638                                 error = sa6_recoverscope(
 1639                                     (struct sockaddr_in6 *)&iflr->dstaddr);
 1640                                 if (error != 0)
 1641                                         return error;
 1642                         } else
 1643                                 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
 1644 
 1645                         iflr->prefixlen =
 1646                             in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
 1647 
 1648                         iflr->flags = ia->ia6_flags;    /* XXX */
 1649 
 1650                         return 0;
 1651                 } else {
 1652                         struct in6_aliasreq ifra;
 1653 
 1654                         /* fill in6_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
 1655                         bzero(&ifra, sizeof(ifra));
 1656                         bcopy(iflr->iflr_name, ifra.ifra_name,
 1657                             sizeof(ifra.ifra_name));
 1658 
 1659                         bcopy(&ia->ia_addr, &ifra.ifra_addr,
 1660                             ia->ia_addr.sin6_len);
 1661                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
 1662                                 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
 1663                                     ia->ia_dstaddr.sin6_len);
 1664                         } else {
 1665                                 bzero(&ifra.ifra_dstaddr,
 1666                                     sizeof(ifra.ifra_dstaddr));
 1667                         }
 1668                         bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
 1669                             ia->ia_prefixmask.sin6_len);
 1670 
 1671                         ifra.ifra_flags = ia->ia6_flags;
 1672                         return in6_control(so, SIOCDIFADDR_IN6, (void *)&ifra,
 1673                             ifp, l);
 1674                 }
 1675             }
 1676         }
 1677 
 1678         return EOPNOTSUPP;      /* just for safety */
 1679 }
 1680 
 1681 /*
 1682  * Initialize an interface's internet6 address
 1683  * and routing table entry.
 1684  */
 1685 static int
 1686 in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, 
 1687         struct sockaddr_in6 *sin6, int newhost)
 1688 {
 1689         int     error = 0, plen, ifacount = 0;
 1690         int     s = splnet();
 1691         struct ifaddr *ifa;
 1692 
 1693         /*
 1694          * Give the interface a chance to initialize
 1695          * if this is its first address,
 1696          * and to validate the address if necessary.
 1697          */
 1698         IFADDR_FOREACH(ifa, ifp) {
 1699                 if (ifa->ifa_addr == NULL)
 1700                         continue;       /* just for safety */
 1701                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1702                         continue;
 1703                 ifacount++;
 1704         }
 1705 
 1706         ia->ia_addr = *sin6;
 1707 
 1708         if (ifacount <= 1 && ifp->if_ioctl &&
 1709             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) {
 1710                 splx(s);
 1711                 return error;
 1712         }
 1713         splx(s);
 1714 
 1715         ia->ia_ifa.ifa_metric = ifp->if_metric;
 1716 
 1717         /* we could do in(6)_socktrim here, but just omit it at this moment. */
 1718 
 1719         /*
 1720          * Special case:
 1721          * If the destination address is specified for a point-to-point
 1722          * interface, install a route to the destination as an interface
 1723          * direct route.
 1724          */
 1725         plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
 1726         if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {
 1727                 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
 1728                                     RTF_UP | RTF_HOST)) != 0)
 1729                         return error;
 1730                 ia->ia_flags |= IFA_ROUTE;
 1731         }
 1732 
 1733         /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
 1734         if (newhost) {
 1735                 /* set the rtrequest function to create llinfo */
 1736                 ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
 1737                 in6_ifaddloop(&(ia->ia_ifa));
 1738         }
 1739 
 1740         if (ifp->if_flags & IFF_MULTICAST)
 1741                 in6_restoremkludge(ia, ifp);
 1742 
 1743         return error;
 1744 }
 1745 
 1746 /*
 1747  * Find an IPv6 interface link-local address specific to an interface.
 1748  */
 1749 struct in6_ifaddr *
 1750 in6ifa_ifpforlinklocal(const struct ifnet *ifp, const int ignoreflags)
 1751 {
 1752         struct ifaddr *ifa;
 1753 
 1754         IFADDR_FOREACH(ifa, ifp) {
 1755                 if (ifa->ifa_addr == NULL)
 1756                         continue;       /* just for safety */
 1757                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1758                         continue;
 1759                 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
 1760                         if ((((struct in6_ifaddr *)ifa)->ia6_flags &
 1761                              ignoreflags) != 0)
 1762                                 continue;
 1763                         break;
 1764                 }
 1765         }
 1766 
 1767         return (struct in6_ifaddr *)ifa;
 1768 }
 1769 
 1770 
 1771 /*
 1772  * find the internet address corresponding to a given interface and address.
 1773  */
 1774 struct in6_ifaddr *
 1775 in6ifa_ifpwithaddr(const struct ifnet *ifp, const struct in6_addr *addr)
 1776 {
 1777         struct ifaddr *ifa;
 1778 
 1779         IFADDR_FOREACH(ifa, ifp) {
 1780                 if (ifa->ifa_addr == NULL)
 1781                         continue;       /* just for safety */
 1782                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1783                         continue;
 1784                 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
 1785                         break;
 1786         }
 1787 
 1788         return (struct in6_ifaddr *)ifa;
 1789 }
 1790 
 1791 /*
 1792  * find the internet address on a given interface corresponding to a neighbor's
 1793  * address.
 1794  */
 1795 struct in6_ifaddr *
 1796 in6ifa_ifplocaladdr(const struct ifnet *ifp, const struct in6_addr *addr)
 1797 {
 1798         struct ifaddr *ifa;
 1799         struct in6_ifaddr *ia;
 1800 
 1801         IFADDR_FOREACH(ifa, ifp) {
 1802                 if (ifa->ifa_addr == NULL)
 1803                         continue;       /* just for safety */
 1804                 if (ifa->ifa_addr->sa_family != AF_INET6)
 1805                         continue;
 1806                 ia = (struct in6_ifaddr *)ifa;
 1807                 if (IN6_ARE_MASKED_ADDR_EQUAL(addr,
 1808                                 &ia->ia_addr.sin6_addr,
 1809                                 &ia->ia_prefixmask.sin6_addr))
 1810                         return ia;
 1811         }
 1812 
 1813         return NULL;
 1814 }
 1815 
 1816 /*
 1817  * Convert IP6 address to printable (loggable) representation.
 1818  */
 1819 static int ip6round = 0;
 1820 char *
 1821 ip6_sprintf(const struct in6_addr *addr)
 1822 {
 1823         static char ip6buf[8][48];
 1824         int i;
 1825         char *cp;
 1826         const u_int16_t *a = (const u_int16_t *)addr;
 1827         const u_int8_t *d;
 1828         int dcolon = 0;
 1829 
 1830         ip6round = (ip6round + 1) & 7;
 1831         cp = ip6buf[ip6round];
 1832 
 1833         for (i = 0; i < 8; i++) {
 1834                 if (dcolon == 1) {
 1835                         if (*a == 0) {
 1836                                 if (i == 7)
 1837                                         *cp++ = ':';
 1838                                 a++;
 1839                                 continue;
 1840                         } else
 1841                                 dcolon = 2;
 1842                 }
 1843                 if (*a == 0) {
 1844                         if (dcolon == 0 && *(a + 1) == 0) {
 1845                                 if (i == 0)
 1846                                         *cp++ = ':';
 1847                                 *cp++ = ':';
 1848                                 dcolon = 1;
 1849                         } else {
 1850                                 *cp++ = '';
 1851                                 *cp++ = ':';
 1852                         }
 1853                         a++;
 1854                         continue;
 1855                 }
 1856                 d = (const u_char *)a;
 1857                 *cp++ = hexdigits[*d >> 4];
 1858                 *cp++ = hexdigits[*d++ & 0xf];
 1859                 *cp++ = hexdigits[*d >> 4];
 1860                 *cp++ = hexdigits[*d & 0xf];
 1861                 *cp++ = ':';
 1862                 a++;
 1863         }
 1864         *--cp = 0;
 1865         return ip6buf[ip6round];
 1866 }
 1867 
 1868 /*
 1869  * Determine if an address is on a local network.
 1870  */
 1871 int
 1872 in6_localaddr(const struct in6_addr *in6)
 1873 {
 1874         struct in6_ifaddr *ia;
 1875 
 1876         if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
 1877                 return 1;
 1878 
 1879         for (ia = in6_ifaddr; ia; ia = ia->ia_next)
 1880                 if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
 1881                                               &ia->ia_prefixmask.sin6_addr))
 1882                         return 1;
 1883 
 1884         return 0;
 1885 }
 1886 
 1887 int
 1888 in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
 1889 {
 1890         struct in6_ifaddr *ia;
 1891 
 1892         for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
 1893                 if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
 1894                     &sa6->sin6_addr) &&
 1895 #ifdef SCOPEDROUTING
 1896                     ia->ia_addr.sin6_scope_id == sa6->sin6_scope_id &&
 1897 #endif
 1898                     (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
 1899                         return 1; /* true */
 1900 
 1901                 /* XXX: do we still have to go thru the rest of the list? */
 1902         }
 1903 
 1904         return 0;               /* false */
 1905 }
 1906 
 1907 /*
 1908  * return length of part which dst and src are equal
 1909  * hard coding...
 1910  */
 1911 int
 1912 in6_matchlen(struct in6_addr *src, struct in6_addr *dst)
 1913 {
 1914         int match = 0;
 1915         u_char *s = (u_char *)src, *d = (u_char *)dst;
 1916         u_char *lim = s + 16, r;
 1917 
 1918         while (s < lim)
 1919                 if ((r = (*d++ ^ *s++)) != 0) {
 1920                         while (r < 128) {
 1921                                 match++;
 1922                                 r <<= 1;
 1923                         }
 1924                         break;
 1925                 } else
 1926                         match += NBBY;
 1927         return match;
 1928 }
 1929 
 1930 /* XXX: to be scope conscious */
 1931 int
 1932 in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
 1933 {
 1934         int bytelen, bitlen;
 1935 
 1936         /* sanity check */
 1937         if (len < 0 || len > 128) {
 1938                 log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
 1939                     len);
 1940                 return 0;
 1941         }
 1942 
 1943         bytelen = len / NBBY;
 1944         bitlen = len % NBBY;
 1945 
 1946         if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
 1947                 return 0;
 1948         if (bitlen != 0 &&
 1949             p1->s6_addr[bytelen] >> (NBBY - bitlen) !=
 1950             p2->s6_addr[bytelen] >> (NBBY - bitlen))
 1951                 return 0;
 1952 
 1953         return 1;
 1954 }
 1955 
 1956 void
 1957 in6_prefixlen2mask(struct in6_addr *maskp, int len)
 1958 {
 1959         static const u_char maskarray[NBBY] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
 1960         int bytelen, bitlen, i;
 1961 
 1962         /* sanity check */
 1963         if (len < 0 || len > 128) {
 1964                 log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
 1965                     len);
 1966                 return;
 1967         }
 1968 
 1969         bzero(maskp, sizeof(*maskp));
 1970         bytelen = len / NBBY;
 1971         bitlen = len % NBBY;
 1972         for (i = 0; i < bytelen; i++)
 1973                 maskp->s6_addr[i] = 0xff;
 1974         if (bitlen)
 1975                 maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
 1976 }
 1977 
 1978 /*
 1979  * return the best address out of the same scope. if no address was
 1980  * found, return the first valid address from designated IF.
 1981  */
 1982 struct in6_ifaddr *
 1983 in6_ifawithifp(struct ifnet *ifp, struct in6_addr *dst)
 1984 {
 1985         int dst_scope = in6_addrscope(dst), blen = -1, tlen;
 1986         struct ifaddr *ifa;
 1987         struct in6_ifaddr *besta = 0;
 1988         struct in6_ifaddr *dep[2];      /* last-resort: deprecated */
 1989 
 1990         dep[0] = dep[1] = NULL;
 1991 
 1992         /*
 1993          * We first look for addresses in the same scope.
 1994          * If there is one, return it.
 1995          * If two or more, return one which matches the dst longest.
 1996          * If none, return one of global addresses assigned other ifs.
 1997          */
 1998         IFADDR_FOREACH(ifa, ifp) {
 1999                 if (ifa->ifa_addr->sa_family != AF_INET6)
 2000                         continue;
 2001                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
 2002                         continue; /* XXX: is there any case to allow anycast? */
 2003                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
 2004                         continue; /* don't use this interface */
 2005                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
 2006                         continue;
 2007                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
 2008                         if (ip6_use_deprecated)
 2009                                 dep[0] = (struct in6_ifaddr *)ifa;
 2010                         continue;
 2011                 }
 2012 
 2013                 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
 2014                         /*
 2015                          * call in6_matchlen() as few as possible
 2016                          */
 2017                         if (besta) {
 2018                                 if (blen == -1)
 2019                                         blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
 2020                                 tlen = in6_matchlen(IFA_IN6(ifa), dst);
 2021                                 if (tlen > blen) {
 2022                                         blen = tlen;
 2023                                         besta = (struct in6_ifaddr *)ifa;
 2024                                 }
 2025                         } else
 2026                                 besta = (struct in6_ifaddr *)ifa;
 2027                 }
 2028         }
 2029         if (besta)
 2030                 return besta;
 2031 
 2032         IFADDR_FOREACH(ifa, ifp) {
 2033                 if (ifa->ifa_addr->sa_family != AF_INET6)
 2034                         continue;
 2035                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
 2036                         continue; /* XXX: is there any case to allow anycast? */
 2037                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
 2038                         continue; /* don't use this interface */
 2039                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
 2040                         continue;
 2041                 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
 2042                         if (ip6_use_deprecated)
 2043                                 dep[1] = (struct in6_ifaddr *)ifa;
 2044                         continue;
 2045                 }
 2046 
 2047                 return (struct in6_ifaddr *)ifa;
 2048         }
 2049 
 2050         /* use the last-resort values, that are, deprecated addresses */
 2051         if (dep[0])
 2052                 return dep[0];
 2053         if (dep[1])
 2054                 return dep[1];
 2055 
 2056         return NULL;
 2057 }
 2058 
 2059 /*
 2060  * perform DAD when interface becomes IFF_UP.
 2061  */
 2062 void
 2063 in6_if_up(struct ifnet *ifp)
 2064 {
 2065         struct ifaddr *ifa;
 2066         struct in6_ifaddr *ia;
 2067 
 2068         IFADDR_FOREACH(ifa, ifp) {
 2069                 if (ifa->ifa_addr->sa_family != AF_INET6)
 2070                         continue;
 2071                 ia = (struct in6_ifaddr *)ifa;
 2072                 if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
 2073                         /*
 2074                          * The TENTATIVE flag was likely set by hand
 2075                          * beforehand, implicitly indicating the need for DAD.
 2076                          * We may be able to skip the random delay in this
 2077                          * case, but we impose delays just in case.
 2078                          */
 2079                         nd6_dad_start(ifa,
 2080                             arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz));
 2081                 }
 2082         }
 2083 
 2084         /*
 2085          * special cases, like 6to4, are handled in in6_ifattach
 2086          */
 2087         in6_ifattach(ifp, NULL);
 2088 }
 2089 
 2090 int
 2091 in6if_do_dad(struct ifnet *ifp)
 2092 {
 2093         if ((ifp->if_flags & IFF_LOOPBACK) != 0)
 2094                 return 0;
 2095 
 2096         switch (ifp->if_type) {
 2097         case IFT_FAITH:
 2098                 /*
 2099                  * These interfaces do not have the IFF_LOOPBACK flag,
 2100                  * but loop packets back.  We do not have to do DAD on such
 2101                  * interfaces.  We should even omit it, because loop-backed
 2102                  * NS would confuse the DAD procedure.
 2103                  */
 2104                 return 0;
 2105         default:
 2106                 /*
 2107                  * Our DAD routine requires the interface up and running.
 2108                  * However, some interfaces can be up before the RUNNING
 2109                  * status.  Additionaly, users may try to assign addresses
 2110                  * before the interface becomes up (or running).
 2111                  * We simply skip DAD in such a case as a work around.
 2112                  * XXX: we should rather mark "tentative" on such addresses,
 2113                  * and do DAD after the interface becomes ready.
 2114                  */
 2115                 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
 2116                     (IFF_UP|IFF_RUNNING))
 2117                         return 0;
 2118 
 2119                 return 1;
 2120         }
 2121 }
 2122 
 2123 /*
 2124  * Calculate max IPv6 MTU through all the interfaces and store it
 2125  * to in6_maxmtu.
 2126  */
 2127 void
 2128 in6_setmaxmtu(void)
 2129 {
 2130         unsigned long maxmtu = 0;
 2131         struct ifnet *ifp;
 2132 
 2133         TAILQ_FOREACH(ifp, &ifnet, if_list) {
 2134                 /* this function can be called during ifnet initialization */
 2135                 if (!ifp->if_afdata[AF_INET6])
 2136                         continue;
 2137                 if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
 2138                     IN6_LINKMTU(ifp) > maxmtu)
 2139                         maxmtu = IN6_LINKMTU(ifp);
 2140         }
 2141         if (maxmtu)          /* update only when maxmtu is positive */
 2142                 in6_maxmtu = maxmtu;
 2143 }
 2144 
 2145 /*
 2146  * Provide the length of interface identifiers to be used for the link attached
 2147  * to the given interface.  The length should be defined in "IPv6 over
 2148  * xxx-link" document.  Note that address architecture might also define
 2149  * the length for a particular set of address prefixes, regardless of the
 2150  * link type.  As clarified in rfc2462bis, those two definitions should be
 2151  * consistent, and those really are as of August 2004.
 2152  */
 2153 int
 2154 in6_if2idlen(struct ifnet *ifp)
 2155 {
 2156         switch (ifp->if_type) {
 2157         case IFT_ETHER:         /* RFC2464 */
 2158         case IFT_PROPVIRTUAL:   /* XXX: no RFC. treat it as ether */
 2159         case IFT_L2VLAN:        /* ditto */
 2160         case IFT_IEEE80211:     /* ditto */
 2161         case IFT_FDDI:          /* RFC2467 */
 2162         case IFT_ISO88025:      /* RFC2470 (IPv6 over Token Ring) */
 2163         case IFT_PPP:           /* RFC2472 */
 2164         case IFT_ARCNET:        /* RFC2497 */
 2165         case IFT_FRELAY:        /* RFC2590 */
 2166         case IFT_IEEE1394:      /* RFC3146 */
 2167         case IFT_GIF:           /* draft-ietf-v6ops-mech-v2-07 */
 2168         case IFT_LOOP:          /* XXX: is this really correct? */
 2169                 return 64;
 2170         default:
 2171                 /*
 2172                  * Unknown link type:
 2173                  * It might be controversial to use the today's common constant
 2174                  * of 64 for these cases unconditionally.  For full compliance,
 2175                  * we should return an error in this case.  On the other hand,
 2176                  * if we simply miss the standard for the link type or a new
 2177                  * standard is defined for a new link type, the IFID length
 2178                  * is very likely to be the common constant.  As a compromise,
 2179                  * we always use the constant, but make an explicit notice
 2180                  * indicating the "unknown" case.
 2181                  */
 2182                 printf("in6_if2idlen: unknown link type (%d)\n", ifp->if_type);
 2183                 return 64;
 2184         }
 2185 }
 2186 
 2187 void *
 2188 in6_domifattach(struct ifnet *ifp)
 2189 {
 2190         struct in6_ifextra *ext;
 2191 
 2192         ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
 2193         bzero(ext, sizeof(*ext));
 2194 
 2195         ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
 2196             M_IFADDR, M_WAITOK);
 2197         bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
 2198 
 2199         ext->icmp6_ifstat =
 2200             (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
 2201             M_IFADDR, M_WAITOK);
 2202         bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
 2203 
 2204         ext->nd_ifinfo = nd6_ifattach(ifp);
 2205         ext->scope6_id = scope6_ifattach(ifp);
 2206         return ext;
 2207 }
 2208 
 2209 void
 2210 in6_domifdetach(struct ifnet *ifp, void *aux)
 2211 {
 2212         struct in6_ifextra *ext = (struct in6_ifextra *)aux;
 2213 
 2214         nd6_ifdetach(ext->nd_ifinfo);
 2215         free(ext->in6_ifstat, M_IFADDR);
 2216         free(ext->icmp6_ifstat, M_IFADDR);
 2217         scope6_ifdetach(ext->scope6_id);
 2218         free(ext, M_IFADDR);
 2219 }
 2220 
 2221 /*
 2222  * Convert sockaddr_in6 to sockaddr_in.  Original sockaddr_in6 must be
 2223  * v4 mapped addr or v4 compat addr
 2224  */
 2225 void
 2226 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
 2227 {
 2228         bzero(sin, sizeof(*sin));
 2229         sin->sin_len = sizeof(struct sockaddr_in);
 2230         sin->sin_family = AF_INET;
 2231         sin->sin_port = sin6->sin6_port;
 2232         sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
 2233 }
 2234 
 2235 /* Convert sockaddr_in to sockaddr_in6 in v4 mapped addr format. */
 2236 void
 2237 in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
 2238 {
 2239         bzero(sin6, sizeof(*sin6));
 2240         sin6->sin6_len = sizeof(struct sockaddr_in6);
 2241         sin6->sin6_family = AF_INET6;
 2242         sin6->sin6_port = sin->sin_port;
 2243         sin6->sin6_addr.s6_addr32[0] = 0;
 2244         sin6->sin6_addr.s6_addr32[1] = 0;
 2245         sin6->sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
 2246         sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
 2247 }
 2248 
 2249 /* Convert sockaddr_in6 into sockaddr_in. */
 2250 void
 2251 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
 2252 {
 2253         struct sockaddr_in *sin_p;
 2254         struct sockaddr_in6 sin6;
 2255 
 2256         /*
 2257          * Save original sockaddr_in6 addr and convert it
 2258          * to sockaddr_in.
 2259          */
 2260         sin6 = *(struct sockaddr_in6 *)nam;
 2261         sin_p = (struct sockaddr_in *)nam;
 2262         in6_sin6_2_sin(sin_p, &sin6);
 2263 }
 2264 
 2265 /* Convert sockaddr_in into sockaddr_in6 in v4 mapped addr format. */
 2266 void
 2267 in6_sin_2_v4mapsin6_in_sock(struct sockaddr **nam)
 2268 {
 2269         struct sockaddr_in *sin_p;
 2270         struct sockaddr_in6 *sin6_p;
 2271 
 2272         sin6_p = malloc(sizeof(*sin6_p), M_SONAME, M_WAITOK);
 2273         sin_p = (struct sockaddr_in *)*nam;
 2274         in6_sin_2_v4mapsin6(sin_p, sin6_p);
 2275         free(*nam, M_SONAME);
 2276         *nam = (struct sockaddr *)sin6_p;
 2277 }

Cache object: 738293a436a53fb6efe16e4d62cb1ec8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.