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/bsd/netinet6/in6_ifattach.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2003-2008 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*      $FreeBSD: src/sys/netinet6/in6_ifattach.c,v 1.8 2002/04/19 04:46:22 suz Exp $   */
   29 /*      $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $  */
   30 
   31 /*
   32  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   33  * All rights reserved.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. Neither the name of the project nor the names of its contributors
   44  *    may be used to endorse or promote products derived from this software
   45  *    without specific prior written permission.
   46  *
   47  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   57  * SUCH DAMAGE.
   58  */
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/malloc.h>
   63 #include <sys/socket.h>
   64 #include <sys/socketvar.h>
   65 #include <sys/sockio.h>
   66 #include <sys/kernel.h>
   67 #include <sys/syslog.h>
   68 #include <libkern/crypto/md5.h>
   69 #include <libkern/OSAtomic.h>
   70 #include <kern/lock.h>
   71 
   72 #include <net/if.h>
   73 #include <net/if_dl.h>
   74 #include <net/if_types.h>
   75 #include <net/route.h>
   76 #include <net/kpi_protocol.h>
   77 
   78 #include <netinet/in.h>
   79 #include <netinet/in_var.h>
   80 #include <netinet/if_ether.h>
   81 #include <netinet/in_pcb.h>
   82 
   83 #include <netinet/ip6.h>
   84 #include <netinet6/ip6_var.h>
   85 #include <netinet6/in6_var.h>
   86 #include <netinet6/in6_pcb.h>
   87 #include <netinet6/in6_ifattach.h>
   88 #include <netinet6/ip6_var.h>
   89 #include <netinet6/nd6.h>
   90 #include <netinet6/scope6_var.h>
   91 
   92 #include <net/net_osdep.h>
   93 
   94 struct in6_ifstat **in6_ifstat = NULL;
   95 struct icmp6_ifstat **icmp6_ifstat = NULL;
   96 size_t in6_ifstatmax = 0;
   97 size_t icmp6_ifstatmax = 0;
   98 u_int32_t in6_maxmtu = 0;
   99 extern lck_mtx_t *nd6_mutex;
  100 extern lck_mtx_t *inet6_domain_mutex;
  101 
  102 #if IP6_AUTO_LINKLOCAL
  103 int ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
  104 #else
  105 int ip6_auto_linklocal = 1;     /* enable by default */
  106 #endif
  107 
  108 extern struct inpcbinfo udbinfo;
  109 extern struct inpcbinfo ripcbinfo;
  110 extern lck_mtx_t *ip6_mutex;
  111 
  112 static int get_rand_ifid(struct ifnet *, struct in6_addr *);
  113 static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
  114 static int get_hw_ifid(struct ifnet *, struct in6_addr *);
  115 static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
  116 static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *, struct in6_aliasreq *);
  117 static int in6_ifattach_loopback(struct ifnet *);
  118 
  119 #define EUI64_GBIT      0x01
  120 #define EUI64_UBIT      0x02
  121 #define EUI64_TO_IFID(in6)      do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
  122 #define EUI64_GROUP(in6)        ((in6)->s6_addr[8] & EUI64_GBIT)
  123 #define EUI64_INDIVIDUAL(in6)   (!EUI64_GROUP(in6))
  124 #define EUI64_LOCAL(in6)        ((in6)->s6_addr[8] & EUI64_UBIT)
  125 #define EUI64_UNIVERSAL(in6)    (!EUI64_LOCAL(in6))
  126 
  127 #define IFID_LOCAL(in6)         (!EUI64_LOCAL(in6))
  128 #define IFID_UNIVERSAL(in6)     (!EUI64_UNIVERSAL(in6))
  129 
  130 /*
  131  * Generate a last-resort interface identifier, when the machine has no
  132  * IEEE802/EUI64 address sources.
  133  * The goal here is to get an interface identifier that is
  134  * (1) random enough and (2) does not change across reboot.
  135  * We currently use MD5(hostname) for it.
  136  */
  137 static int
  138 get_rand_ifid(
  139         __unused struct ifnet *ifp,
  140         struct in6_addr *in6)   /* upper 64bits are preserved */
  141 {
  142         MD5_CTX ctxt;
  143         u_int8_t digest[16];
  144         int len = strlen(hostname);
  145 
  146 #if 0
  147         /* we need at least several letters as seed for ifid */
  148         if (len < 3)
  149                 return -1;
  150 #endif
  151 
  152         /* generate 8 bytes of pseudo-random value. */
  153         bzero(&ctxt, sizeof(ctxt));
  154         MD5Init(&ctxt);
  155         MD5Update(&ctxt, hostname, len);
  156         MD5Final(digest, &ctxt);
  157 
  158         /* assumes sizeof(digest) > sizeof(ifid) */
  159         bcopy(digest, &in6->s6_addr[8], 8);
  160 
  161         /* make sure to set "u" bit to local, and "g" bit to individual. */
  162         in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
  163         in6->s6_addr[8] |= EUI64_UBIT;  /* u bit to "local" */
  164 
  165         /* convert EUI64 into IPv6 interface identifier */
  166         EUI64_TO_IFID(in6);
  167 
  168         return 0;
  169 }
  170 
  171 static int
  172 generate_tmp_ifid(
  173         u_int8_t *seed0,
  174         const u_int8_t *seed1,
  175         u_int8_t *ret)
  176 {
  177         MD5_CTX ctxt;
  178         u_int8_t seed[16], digest[16], nullbuf[8];
  179         u_int32_t val32;
  180         struct timeval tv;
  181 
  182         /* If there's no hisotry, start with a random seed. */
  183         bzero(nullbuf, sizeof(nullbuf));
  184         if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
  185                 int i;
  186 
  187                 for (i = 0; i < 2; i++) {
  188                         microtime(&tv);
  189                         val32 = random() ^ tv.tv_usec;
  190                         bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
  191                 }
  192         } else {
  193                 bcopy(seed0, seed, 8);
  194         }
  195 
  196         /* copy the right-most 64-bits of the given address */
  197         /* XXX assumption on the size of IFID */
  198         bcopy(seed1, &seed[8], 8);
  199 
  200         if (0) {                /* for debugging purposes only */
  201                 int i;
  202 
  203                 printf("generate_tmp_ifid: new randomized ID from: ");
  204                 for (i = 0; i < 16; i++)
  205                         printf("%02x", seed[i]);
  206                 printf(" ");
  207         }
  208 
  209         /* generate 16 bytes of pseudo-random value. */
  210         bzero(&ctxt, sizeof(ctxt));
  211         MD5Init(&ctxt);
  212         MD5Update(&ctxt, seed, sizeof(seed));
  213         MD5Final(digest, &ctxt);
  214 
  215         /*
  216          * RFC 3041 3.2.1. (3)
  217          * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
  218          * left-most bit is numbered 0) to zero.
  219          */
  220         bcopy(digest, ret, 8);
  221         ret[0] &= ~EUI64_UBIT;
  222 
  223         /*
  224          * XXX: we'd like to ensure that the generated value is not zero
  225          * for simplicity.  If the caclculated digest happens to be zero,
  226          * use a random non-zero value as the last resort.
  227          */
  228         if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
  229                 log(LOG_INFO,
  230                     "generate_tmp_ifid: computed MD5 value is zero.\n");
  231 
  232                 microtime(&tv);
  233                 val32 = random() ^ tv.tv_usec;
  234                 val32 = 1 + (val32 % (0xffffffff - 1));
  235         }
  236 
  237         /*
  238          * RFC 3041 3.2.1. (4)
  239          * Take the rightmost 64-bits of the MD5 digest and save them in
  240          * stable storage as the history value to be used in the next
  241          * iteration of the algorithm. 
  242          */
  243         bcopy(&digest[8], seed0, 8);
  244 
  245         if (0) {                /* for debugging purposes only */
  246                 int i;
  247 
  248                 printf("to: ");
  249                 for (i = 0; i < 16; i++)
  250                         printf("%02x", digest[i]);
  251                 printf("\n");
  252         }
  253 
  254         return 0;
  255 }
  256 
  257 /*
  258  * Get interface identifier for the specified interface.
  259  * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
  260  */
  261 static int
  262 get_hw_ifid(
  263         struct ifnet *ifp,
  264         struct in6_addr *in6)   /* upper 64bits are preserved */
  265 {
  266         struct ifaddr *ifa;
  267         struct sockaddr_dl *sdl;
  268         u_int8_t *addr;
  269         size_t addrlen;
  270         static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  271         static u_int8_t allone[8] =
  272                 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  273 
  274         /* Why doesn't this code use ifnet_addrs? */
  275         ifnet_lock_shared(ifp);
  276         for (ifa = ifp->if_addrlist.tqh_first;
  277              ifa;
  278              ifa = ifa->ifa_list.tqe_next)
  279         {
  280                 if (ifa->ifa_addr->sa_family != AF_LINK)
  281                         continue;
  282                 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
  283                 if (sdl == NULL)
  284                         continue;
  285                 if (sdl->sdl_alen == 0)
  286                         continue;
  287 
  288                 goto found;
  289         }
  290         ifnet_lock_done(ifp);
  291 
  292         return -1;
  293 
  294 found:
  295         ifnet_lock_done(ifp);
  296         addr = (u_int8_t *) LLADDR(sdl);
  297         addrlen = sdl->sdl_alen;
  298 
  299         /* get EUI64 */
  300         switch (ifp->if_type) {
  301         case IFT_ETHER:
  302         case IFT_FDDI:
  303         case IFT_ATM:
  304         case IFT_IEEE1394:
  305         case IFT_L2VLAN:
  306         case IFT_IEEE8023ADLAG:
  307 #if IFT_IEEE80211
  308         case IFT_IEEE80211:
  309 #endif
  310                 /* IEEE802/EUI64 cases - what others? */
  311                 /* IEEE1394 uses 16byte length address starting with EUI64 */
  312                 if (addrlen > 8)
  313                         addrlen = 8;
  314 
  315                 /* look at IEEE802/EUI64 only */
  316                 if (addrlen != 8 && addrlen != 6)
  317                         return -1;
  318 
  319                 /*
  320                  * check for invalid MAC address - on bsdi, we see it a lot
  321                  * since wildboar configures all-zero MAC on pccard before
  322                  * card insertion.
  323                  */
  324                 if (bcmp(addr, allzero, addrlen) == 0)
  325                         return -1;
  326                 if (bcmp(addr, allone, addrlen) == 0)
  327                         return -1;
  328 
  329                 /* make EUI64 address */
  330                 if (addrlen == 8)
  331                         bcopy(addr, &in6->s6_addr[8], 8);
  332                 else if (addrlen == 6) {
  333                         in6->s6_addr[8] = addr[0];
  334                         in6->s6_addr[9] = addr[1];
  335                         in6->s6_addr[10] = addr[2];
  336                         in6->s6_addr[11] = 0xff;
  337                         in6->s6_addr[12] = 0xfe;
  338                         in6->s6_addr[13] = addr[3];
  339                         in6->s6_addr[14] = addr[4];
  340                         in6->s6_addr[15] = addr[5];
  341                 }
  342                 break;
  343 
  344         case IFT_ARCNET:
  345                 if (addrlen != 1)
  346                         return -1;
  347                 if (!addr[0])
  348                         return -1;
  349 
  350                 bzero(&in6->s6_addr[8], 8);
  351                 in6->s6_addr[15] = addr[0];
  352 
  353                 /*
  354                  * due to insufficient bitwidth, we mark it local.
  355                  */
  356                 in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
  357                 in6->s6_addr[8] |= EUI64_UBIT;  /* u bit to "local" */
  358                 break;
  359 
  360         case IFT_GIF:
  361 #if IFT_STF
  362         case IFT_STF:
  363 #endif
  364                 /*
  365                  * RFC2893 says: "SHOULD use IPv4 address as ifid source".
  366                  * however, IPv4 address is not very suitable as unique
  367                  * identifier source (can be renumbered).
  368                  * we don't do this.
  369                  */
  370                 return -1;
  371 
  372         default:
  373                 return -1;
  374         }
  375 
  376         /* sanity check: g bit must not indicate "group" */
  377         if (EUI64_GROUP(in6))
  378                 return -1;
  379 
  380         /* convert EUI64 into IPv6 interface identifier */
  381         EUI64_TO_IFID(in6);
  382 
  383         /*
  384          * sanity check: ifid must not be all zero, avoid conflict with
  385          * subnet router anycast
  386          */
  387         if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
  388             bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
  389                 return -1;
  390         }
  391 
  392         return 0;
  393 }
  394 
  395 /*
  396  * Get interface identifier for the specified interface.  If it is not
  397  * available on ifp0, borrow interface identifier from other information
  398  * sources.
  399  */
  400 static int
  401 get_ifid(
  402         struct ifnet *ifp0,
  403         struct ifnet *altifp,   /* secondary EUI64 source */
  404         struct in6_addr *in6)
  405 {
  406         struct ifnet *ifp;
  407 
  408         /* first, try to get it from the interface itself */
  409         if (get_hw_ifid(ifp0, in6) == 0) {
  410                 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
  411                     if_name(ifp0)));
  412                 goto success;
  413         }
  414 
  415         /* try secondary EUI64 source. this basically is for ATM PVC */
  416         if (altifp && get_hw_ifid(altifp, in6) == 0) {
  417                 nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
  418                     if_name(ifp0), if_name(altifp)));
  419                 goto success;
  420         }
  421 
  422         /* next, try to get it from some other hardware interface */
  423         ifnet_head_lock_shared();
  424         TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
  425                 if (ifp == ifp0)
  426                         continue;
  427                 if (get_hw_ifid(ifp, in6) != 0)
  428                         continue;
  429 
  430                 /*
  431                  * to borrow ifid from other interface, ifid needs to be
  432                  * globally unique
  433                  */
  434                 if (IFID_UNIVERSAL(in6)) {
  435                         nd6log((LOG_DEBUG,
  436                             "%s: borrow interface identifier from %s\n",
  437                             if_name(ifp0), if_name(ifp)));
  438                         ifnet_head_done();
  439                         goto success;
  440                 }
  441         }
  442         ifnet_head_done();
  443 
  444         /* last resort: get from random number source */
  445         if (get_rand_ifid(ifp, in6) == 0) {
  446                 nd6log((LOG_DEBUG,
  447                     "%s: interface identifier generated by random number\n",
  448                     if_name(ifp0)));
  449                 goto success;
  450         }
  451 
  452         printf("%s: failed to get interface identifier\n", if_name(ifp0));
  453         return -1;
  454 
  455 success:
  456         nd6log((LOG_INFO, "%s: ifid: "
  457                 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
  458                 if_name(ifp0),
  459                 in6->s6_addr[8], in6->s6_addr[9],
  460                 in6->s6_addr[10], in6->s6_addr[11],
  461                 in6->s6_addr[12], in6->s6_addr[13],
  462                 in6->s6_addr[14], in6->s6_addr[15]));
  463         return 0;
  464 }
  465 
  466 static int
  467 in6_ifattach_linklocal(
  468         struct ifnet *ifp,
  469         struct ifnet *altifp,   /* secondary EUI64 source */
  470         struct in6_aliasreq *ifra_passed)
  471 {
  472         struct in6_ifaddr *ia;
  473         struct in6_aliasreq ifra;
  474         struct nd_prefix pr0, *pr;
  475         int i, error;
  476 
  477         /*
  478          * configure link-local address.
  479          */
  480         bzero(&ifra, sizeof(ifra));
  481 
  482         proto_plumb(PF_INET6, ifp);
  483 
  484         /*
  485          * in6_update_ifa() does not use ifra_name, but we accurately set it
  486          * for safety.
  487          */
  488         strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
  489 
  490         if (((ifp->if_type == IFT_PPP) ||  ((ifp->if_eflags & IFEF_NOAUTOIPV6LL) != 0)) &&
  491                          ifra_passed != NULL)  /* PPP provided both addresses for us */
  492                 bcopy(&ifra_passed->ifra_addr, &(ifra.ifra_addr), sizeof(struct sockaddr_in6));
  493         else {
  494                 ifra.ifra_addr.sin6_family = AF_INET6;
  495                 ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
  496                 ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
  497 #if SCOPEDROUTING
  498                 ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0
  499 #else
  500                 ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */
  501 #endif
  502                 ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
  503                 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
  504                         ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
  505                         ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
  506                 } else {
  507                         if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
  508                                 nd6log((LOG_ERR,
  509                             "   %s: no ifid available\n", if_name(ifp)));
  510                                 return -1;
  511                         }
  512                 }
  513 #if SCOPEDROUTING
  514                 ifra.ifra_addr.sin6_scope_id =
  515                         in6_addr2scopeid(ifp,  &ifra.ifra_addr.sin6_addr);
  516 #endif
  517         }
  518         ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
  519         ifra.ifra_prefixmask.sin6_family = AF_INET6;
  520         ifra.ifra_prefixmask.sin6_addr = in6mask64;
  521 #if SCOPEDROUTING
  522         /* take into accound the sin6_scope_id field for routing */
  523         ifra.ifra_prefixmask.sin6_scope_id = 0xffffffff;
  524 #endif
  525         /* link-local addresses should NEVER expire. */
  526         ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
  527         ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
  528 
  529         /*
  530          * Do not let in6_update_ifa() do DAD, since we need a random delay
  531          * before sending an NS at the first time the interface becomes up.
  532          * Instead, in6_if_up() will start DAD with a proper random delay.
  533          */
  534         ifra.ifra_flags |= IN6_IFF_NODAD;
  535 
  536         /*
  537          * Now call in6_update_ifa() to do a bunch of procedures to configure
  538          * a link-local address. We can set NULL to the 3rd argument, because
  539          * we know there's no other link-local address on the interface
  540          * and therefore we are adding one (instead of updating one).
  541          */
  542         if ((error = in6_update_ifa(ifp, &ifra, NULL, M_WAITOK)) != 0) {
  543                 /*
  544                  * XXX: When the interface does not support IPv6, this call
  545                  * would fail in the SIOCSIFADDR ioctl.  I believe the
  546                  * notification is rather confusing in this case, so just
  547                  * supress it.  (jinmei@kame.net 20010130)
  548                  */
  549                 if (error != EAFNOSUPPORT)
  550                         log(LOG_NOTICE, "in6_ifattach_linklocal: failed to "
  551                             "configure a link-local address on %s "
  552                             "(errno=%d)\n",
  553                             if_name(ifp), error);
  554                 return(-1);
  555         }
  556 
  557         /*
  558          * Adjust ia6_flags so that in6_if_up will perform DAD.
  559          * XXX: Some P2P interfaces seem not to send packets just after
  560          * becoming up, so we skip p2p interfaces for safety.
  561          */
  562         ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
  563 #if DIAGNOSTIC
  564         if (!ia) {
  565                 panic("ia == NULL in in6_ifattach_linklocal");
  566                 /*NOTREACHED*/
  567         }
  568 #endif
  569         if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) {
  570                 ia->ia6_flags &= ~IN6_IFF_NODAD;
  571                 ia->ia6_flags |= IN6_IFF_TENTATIVE;
  572         }
  573 
  574         /*
  575          * Make the link-local prefix (fe80::/64%link) as on-link.
  576          * Since we'd like to manage prefixes separately from addresses,
  577          * we make an ND6 prefix structure for the link-local prefix,
  578          * and add it to the prefix list as a never-expire prefix.
  579          * XXX: this change might affect some existing code base...
  580          */
  581         bzero(&pr0, sizeof(pr0));
  582         pr0.ndpr_ifp = ifp;
  583         /* this should be 64 at this moment. */
  584         pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
  585         pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
  586         pr0.ndpr_prefix = ifra.ifra_addr;
  587         /* apply the mask for safety. (nd6_prelist_add will apply it again) */
  588         for (i = 0; i < 4; i++) {
  589                 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
  590                         in6mask64.s6_addr32[i];
  591         }
  592         /*
  593          * Initialize parameters.  The link-local prefix must always be
  594          * on-link, and its lifetimes never expire.
  595          */
  596         pr0.ndpr_raf_onlink = 1;
  597         pr0.ndpr_raf_auto = 1;  /* probably meaningless */
  598         pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
  599         pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
  600         /*
  601          * Since there is no other link-local addresses, nd6_prefix_lookup()
  602          * probably returns NULL.  However, we cannot always expect the result.
  603          * For example, if we first remove the (only) existing link-local
  604          * address, and then reconfigure another one, the prefix is still
  605          * valid with referring to the old link-local address.
  606          */
  607         if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
  608                 if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0) {
  609                         printf("in6_ifattach_linklocal: nd6_prelist_add failed %d\n", error);
  610                         ifafree(&ia->ia_ifa);
  611                         return(error);
  612                 }
  613         }
  614 
  615         if (ia != NULL) {
  616                 in6_post_msg(ifp, KEV_INET6_NEW_LL_ADDR, ia);
  617                 ifafree(&ia->ia_ifa);
  618         }
  619 
  620         /* Drop use count held above during lookup/add */
  621         if (pr != NULL)
  622                 ndpr_rele(pr, FALSE);
  623 
  624         return 0;
  625 }
  626 
  627 static int
  628 in6_ifattach_loopback(
  629         struct ifnet *ifp)      /* must be IFT_LOOP */
  630 {
  631         struct in6_aliasreq ifra;
  632         int error;
  633 
  634         bzero(&ifra, sizeof(ifra));
  635 
  636         /*
  637          * in6_update_ifa() does not use ifra_name, but we accurately set it
  638          * for safety.
  639          */
  640         strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
  641 
  642         ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
  643         ifra.ifra_prefixmask.sin6_family = AF_INET6;
  644         ifra.ifra_prefixmask.sin6_addr = in6mask128;
  645 
  646         /*
  647          * Always initialize ia_dstaddr (= broadcast address) to loopback
  648          * address.  Follows IPv4 practice - see in_ifinit().
  649          */
  650         ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
  651         ifra.ifra_dstaddr.sin6_family = AF_INET6;
  652         ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
  653 
  654         ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
  655         ifra.ifra_addr.sin6_family = AF_INET6;
  656         ifra.ifra_addr.sin6_addr = in6addr_loopback;
  657 
  658         /* the loopback  address should NEVER expire. */
  659         ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
  660         ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
  661 
  662         /* we don't need to perform DAD on loopback interfaces. */
  663         ifra.ifra_flags |= IN6_IFF_NODAD;
  664 
  665         /* skip registration to the prefix list. XXX should be temporary. */
  666         ifra.ifra_flags |= IN6_IFF_NOPFX;
  667 
  668         /*
  669          * We are sure that this is a newly assigned address, so we can set
  670          * NULL to the 3rd arg.
  671          */
  672         if ((error = in6_update_ifa(ifp, &ifra, NULL, M_WAITOK)) != 0) {
  673                 log(LOG_ERR, "in6_ifattach_loopback: failed to configure "
  674                     "the loopback address on %s (errno=%d)\n",
  675                     if_name(ifp), error);
  676                 return(-1);
  677         }
  678 
  679         return 0;
  680 }
  681 
  682 /*
  683  * compute NI group address, based on the current hostname setting.
  684  * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
  685  *
  686  * when ifp == NULL, the caller is responsible for filling scopeid.
  687  */
  688 int
  689 in6_nigroup(
  690         struct ifnet *ifp,
  691         const char *name,
  692         int namelen,
  693         struct in6_addr *in6)
  694 {
  695         const char *p;
  696         u_char *q;
  697         MD5_CTX ctxt;
  698         u_int8_t digest[16];
  699         char l;
  700         char n[64];     /* a single label must not exceed 63 chars */
  701 
  702         if (!namelen || !name)
  703                 return -1;
  704 
  705         p = name;
  706         while (p && *p && *p != '.' && p - name < namelen)
  707                 p++;
  708         if (p - name > sizeof(n) - 1)
  709                 return -1;      /* label too long */
  710         l = p - name;
  711         strncpy(n, name, l);
  712         n[(int)l] = '\0';
  713         for (q = (u_char *) n; *q; q++) {
  714                 if ('A' <= *q && *q <= 'Z')
  715                         *q = *q - 'A' + 'a';
  716         }
  717 
  718         /* generate 8 bytes of pseudo-random value. */
  719         bzero(&ctxt, sizeof(ctxt));
  720         MD5Init(&ctxt);
  721         MD5Update(&ctxt, &l, sizeof(l));
  722         MD5Update(&ctxt, n, l);
  723         MD5Final(digest, &ctxt);
  724 
  725         bzero(in6, sizeof(*in6));
  726         in6->s6_addr16[0] = htons(0xff02);
  727         if (ifp)
  728                 in6->s6_addr16[1] = htons(ifp->if_index);
  729         in6->s6_addr8[11] = 2;
  730         bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
  731 
  732         return 0;
  733 }
  734 
  735 void
  736 in6_nigroup_attach(
  737         const char *name,
  738         int namelen)
  739 {
  740         struct ifnet *ifp;
  741         struct sockaddr_in6 mltaddr;
  742         struct in6_multi *in6m;
  743         int error;
  744 
  745         bzero(&mltaddr, sizeof(mltaddr));
  746         mltaddr.sin6_family = AF_INET6;
  747         mltaddr.sin6_len = sizeof(struct sockaddr_in6);
  748         if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
  749                 return;
  750 
  751         ifnet_head_lock_shared();
  752         TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
  753                 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
  754                 ifnet_lock_shared(ifp);
  755                 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
  756                 ifnet_lock_done(ifp);
  757                 if (!in6m) {
  758                         if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error, 0)) {
  759                                 nd6log((LOG_ERR, "%s: failed to join %s "
  760                                     "(errno=%d)\n", if_name(ifp),
  761                                     ip6_sprintf(&mltaddr.sin6_addr), 
  762                                     error));
  763                         }
  764                 }
  765         }
  766         ifnet_head_done();
  767 }
  768 
  769 void
  770 in6_nigroup_detach(
  771         const char *name,
  772         int namelen)
  773 {
  774         struct ifnet *ifp;
  775         struct sockaddr_in6 mltaddr;
  776         struct in6_multi *in6m;
  777 
  778         bzero(&mltaddr, sizeof(mltaddr));
  779         mltaddr.sin6_family = AF_INET6;
  780         mltaddr.sin6_len = sizeof(struct sockaddr_in6);
  781         if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0)
  782                 return;
  783 
  784         ifnet_head_lock_shared();
  785         TAILQ_FOREACH(ifp, &ifnet_head, if_list) {
  786                 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
  787                 ifnet_lock_shared(ifp);
  788                 IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
  789                 ifnet_lock_done(ifp);
  790                 if (in6m)
  791                         in6_delmulti(in6m, 0);
  792         }
  793         ifnet_head_done();
  794 }
  795 
  796 /*
  797  * XXX multiple loopback interface needs more care.  for instance,
  798  * nodelocal address needs to be configured onto only one of them.
  799  * XXX multiple link-local address case
  800  */
  801 int
  802 in6_ifattach(
  803         struct ifnet *ifp,
  804         struct ifnet *altifp,   /* secondary EUI64 source */
  805         struct  in6_aliasreq *ifra)
  806 {
  807         static size_t if_indexlim = 8;
  808         struct in6_ifaddr *ia;
  809         int error;
  810 
  811         /*
  812          * We have some arrays that should be indexed by if_index.
  813          * since if_index will grow dynamically, they should grow too.
  814          *      struct in6_ifstat **in6_ifstat
  815          *      struct icmp6_ifstat **icmp6_ifstat
  816          */
  817         if (in6_ifstat == NULL || icmp6_ifstat == NULL ||
  818             if_index >= if_indexlim) {
  819                 while (if_index >= if_indexlim)
  820                         if_indexlim <<= 1;
  821         }
  822     
  823         lck_mtx_lock(ip6_mutex);
  824         /* grow in6_ifstat */
  825         if (in6_ifstatmax < if_indexlim) {
  826                 size_t n;
  827                 caddr_t q;
  828         
  829                 n = if_indexlim * sizeof(struct in6_ifstat *);
  830                 q = (caddr_t)_MALLOC(n, M_IFADDR, M_WAITOK);
  831                 if (q == NULL) {
  832                         lck_mtx_unlock(ip6_mutex);
  833                         return ENOBUFS;
  834                 }
  835                 bzero(q, n);
  836                 if (in6_ifstat) {
  837                         bcopy((caddr_t)in6_ifstat, q,
  838                                 in6_ifstatmax * sizeof(struct in6_ifstat *));
  839                         FREE((caddr_t)in6_ifstat, M_IFADDR);
  840                 }
  841                 in6_ifstat = (struct in6_ifstat **)q;
  842                 in6_ifstatmax = if_indexlim;
  843         }
  844     
  845         if (in6_ifstat[ifp->if_index] == NULL) {
  846                 in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
  847                         _MALLOC(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
  848                 if (in6_ifstat[ifp->if_index] == NULL) {
  849                         lck_mtx_unlock(ip6_mutex);
  850                         return ENOBUFS;
  851                 }
  852                 bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
  853         }
  854         lck_mtx_unlock(ip6_mutex);
  855 
  856         /* grow icmp6_ifstat, use inet6_domain_mutex as that is used in 
  857          * icmp6 routines 
  858          */
  859         lck_mtx_lock(inet6_domain_mutex);
  860         if (icmp6_ifstatmax < if_indexlim) {
  861                 size_t n;
  862                 caddr_t q;
  863         
  864                 n = if_indexlim * sizeof(struct icmp6_ifstat *);
  865                 q = (caddr_t)_MALLOC(n, M_IFADDR, M_WAITOK);
  866                 if (q == NULL) {
  867                         lck_mtx_unlock(inet6_domain_mutex);
  868                         return ENOBUFS;
  869                 }
  870                 bzero(q, n);
  871                 if (icmp6_ifstat) {
  872                         bcopy((caddr_t)icmp6_ifstat, q,
  873                                 icmp6_ifstatmax * sizeof(struct icmp6_ifstat *));
  874                         FREE((caddr_t)icmp6_ifstat, M_IFADDR);
  875                 }
  876                 icmp6_ifstat = (struct icmp6_ifstat **)q;
  877                 icmp6_ifstatmax = if_indexlim;
  878         }
  879 
  880         if (icmp6_ifstat[ifp->if_index] == NULL) {
  881                 icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
  882                         _MALLOC(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
  883                 if (icmp6_ifstat[ifp->if_index] == NULL) {
  884                         lck_mtx_unlock(inet6_domain_mutex);
  885                         return ENOBUFS;
  886                 }
  887                 bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
  888         }
  889         lck_mtx_unlock(inet6_domain_mutex);
  890 
  891         /* initialize NDP variables */
  892         if ((error = nd6_ifattach(ifp)) != 0)
  893                 return error;
  894 
  895         /* initialize scope identifiers */
  896         if ((error = scope6_ifattach(ifp)) != 0)
  897                 return error;
  898 
  899         /*
  900          * quirks based on interface type
  901          */
  902         switch (ifp->if_type) {
  903 #if IFT_STF
  904         case IFT_STF:
  905                 /*
  906                  * 6to4 interface is a very special kind of beast.
  907                  * no multicast, no linklocal.  RFC2529 specifies how to make
  908                  * linklocals for 6to4 interface, but there's no use and
  909                  * it is rather harmful to have one.
  910                  */
  911                 goto statinit;
  912 #endif
  913         default:
  914                 break;
  915         }
  916 
  917         /*
  918          * usually, we require multicast capability to the interface
  919          */
  920         if ((ifp->if_flags & IFF_MULTICAST) == 0) {
  921                 log(LOG_INFO, "in6_ifattach: "
  922                     "%s is not multicast capable, IPv6 not enabled\n",
  923                     if_name(ifp));
  924                 return EINVAL;
  925         }
  926 
  927         /*
  928          * assign loopback address for loopback interface.
  929          * XXX multiple loopback interface case.
  930          */
  931         if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
  932                 if (in6_ifattach_loopback(ifp) != 0)
  933                         printf("in6_ifattach: in6_ifattach_loopback failed\n");
  934         }
  935 
  936         /*
  937          * assign a link-local address, if there's none. 
  938          */
  939         if (ip6_auto_linklocal) {
  940                 ia = in6ifa_ifpforlinklocal(ifp, 0);
  941                 if (ia == NULL) {
  942                         if (in6_ifattach_linklocal(ifp, altifp, ifra) == 0) {
  943                                 /* linklocal address assigned */
  944                         } else {
  945                                 log(LOG_INFO, "in6_ifattach: %s failed to "
  946                                     "attach a linklocal address.\n",
  947                                     if_name(ifp));
  948                                 /* failed to assign linklocal address. bark? */
  949                         }
  950                 } else {
  951                         ifafree(&ia->ia_ifa);
  952                 }
  953         }
  954 
  955 #if IFT_STF                     /* XXX */
  956 statinit:       
  957 #endif
  958 
  959         /* update dynamically. */
  960         if (in6_maxmtu < ifp->if_mtu)
  961                 in6_maxmtu = ifp->if_mtu;
  962 
  963     return 0;
  964 }
  965 
  966 /*
  967  * NOTE: in6_ifdetach() does not support loopback if at this moment.
  968  * We don't need this function in bsdi, because interfaces are never removed
  969  * from the ifnet list in bsdi.
  970  */
  971 void
  972 in6_ifdetach(
  973         struct ifnet *ifp)
  974 {
  975         struct in6_ifaddr *ia, *oia, *nia;
  976         struct ifaddr *ifa, *next;
  977         struct rtentry *rt;
  978         struct sockaddr_in6 sin6;
  979 
  980         /* nuke prefix list.  this may try to remove some of ifaddrs as well */
  981         in6_purgeprefix(ifp);
  982 
  983         /* remove neighbor management table */
  984         nd6_purge(ifp);
  985 
  986         /* nuke any of IPv6 addresses we have */
  987         
  988         lck_mtx_lock(nd6_mutex);
  989         for (ia = in6_ifaddrs; ia != NULL; ia = nia) {
  990                 nia = ia->ia_next;
  991                 if (ia->ia_ifa.ifa_ifp != ifp)
  992                         continue;
  993                 in6_purgeaddr(&ia->ia_ifa, 1);
  994         }
  995         lck_mtx_unlock(nd6_mutex);
  996 
  997         ifnet_lock_exclusive(ifp);
  998 
  999         /* undo everything done by in6_ifattach(), just in case */
 1000         for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)
 1001         {
 1002                 next = ifa->ifa_list.tqe_next;
 1003 
 1004 
 1005                 if (ifa->ifa_addr->sa_family != AF_INET6
 1006                  || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
 1007                         continue;
 1008                 }
 1009 
 1010                 ia = (struct in6_ifaddr *)ifa;
 1011 
 1012                 /* remove from the routing table */
 1013                 if ((ia->ia_flags & IFA_ROUTE) &&
 1014                     (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0))) {
 1015                         (void) rtrequest(RTM_DELETE,
 1016                                 (struct sockaddr *)&ia->ia_addr,
 1017                                 (struct sockaddr *)&ia->ia_addr,
 1018                                 (struct sockaddr *)&ia->ia_prefixmask,
 1019                                 rt->rt_flags, (struct rtentry **)0);
 1020                         rtfree(rt);
 1021                 }
 1022 
 1023                 /* remove from the linked list */
 1024                 if_detach_ifa(ifp, &ia->ia_ifa);
 1025 
 1026                 /* also remove from the IPv6 address chain(itojun&jinmei) */
 1027                 oia = ia;
 1028                 lck_mtx_lock(nd6_mutex);
 1029                 if (oia == (ia = in6_ifaddrs))
 1030                         in6_ifaddrs = ia->ia_next;
 1031                 else {
 1032                         while (ia->ia_next && (ia->ia_next != oia))
 1033                                 ia = ia->ia_next;
 1034                         if (ia->ia_next)
 1035                                 ia->ia_next = oia->ia_next;
 1036                         else {
 1037                                 nd6log((LOG_ERR, 
 1038                                     "%s: didn't unlink in6ifaddr from "
 1039                                     "list\n", if_name(ifp)));
 1040                         }
 1041                 }
 1042                 lck_mtx_unlock(nd6_mutex);
 1043 
 1044                 ifafree(&oia->ia_ifa);
 1045         }
 1046         ifnet_lock_done(ifp);
 1047 
 1048         /*
 1049          * remove neighbor management table.  we call it twice just to make
 1050          * sure we nuke everything.  maybe we need just one call.
 1051          * XXX: since the first call did not release addresses, some prefixes
 1052          * might remain.  We should call nd6_purge() again to release the
 1053          * prefixes after removing all addresses above.
 1054          * (Or can we just delay calling nd6_purge until at this point?)
 1055          */
 1056         nd6_purge(ifp);
 1057 
 1058         /* remove route to link-local allnodes multicast (ff02::1) */
 1059         bzero(&sin6, sizeof(sin6));
 1060         sin6.sin6_len = sizeof(struct sockaddr_in6);
 1061         sin6.sin6_family = AF_INET6;
 1062         sin6.sin6_addr = in6addr_linklocal_allnodes;
 1063         sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
 1064         rt = rtalloc1((struct sockaddr *)&sin6, 0, 0);
 1065         if (rt != NULL) {
 1066                 RT_LOCK(rt);
 1067                 if (rt->rt_ifp == ifp) {
 1068                         /*
 1069                          * Prevent another thread from modifying rt_key,
 1070                          * rt_gateway via rt_setgate() after the rt_lock
 1071                          * is dropped by marking the route as defunct.
 1072                          */
 1073                         rt->rt_flags |= RTF_CONDEMNED;
 1074                         RT_UNLOCK(rt);
 1075                         (void) rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
 1076                             rt_mask(rt), rt->rt_flags, 0);
 1077                 } else {
 1078                         RT_UNLOCK(rt);
 1079                 }
 1080                 rtfree(rt);
 1081         }
 1082 }
 1083 
 1084 void
 1085 in6_get_tmpifid(
 1086         struct ifnet *ifp,
 1087         u_int8_t *retbuf,
 1088         const u_int8_t *baseid,
 1089         int generate)
 1090 {
 1091         u_int8_t nullbuf[8];
 1092         struct nd_ifinfo *ndi;
 1093 
 1094         lck_rw_lock_shared(nd_if_rwlock);
 1095         ndi = &nd_ifinfo[ifp->if_index];
 1096         bzero(nullbuf, sizeof(nullbuf));
 1097         if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
 1098                 /* we've never created a random ID.  Create a new one. */
 1099                 generate = 1;
 1100         }
 1101 
 1102         if (generate) {
 1103                 bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
 1104 
 1105                 /* generate_tmp_ifid will update seedn and buf */
 1106                 (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
 1107                                         ndi->randomid);
 1108         }
 1109         bcopy(ndi->randomid, retbuf, 8);
 1110         lck_rw_done(nd_if_rwlock);
 1111 }
 1112 
 1113 void
 1114 in6_tmpaddrtimer(
 1115         __unused void *ignored_arg)
 1116 {
 1117         int i;
 1118         struct nd_ifinfo *ndi;
 1119         u_int8_t nullbuf[8];
 1120 
 1121         timeout(in6_tmpaddrtimer, (caddr_t)0,
 1122                       (ip6_temp_preferred_lifetime - ip6_desync_factor -
 1123                        ip6_temp_regen_advance) * hz);
 1124 
 1125         if (ip6_use_tempaddr) {
 1126                 lck_rw_lock_shared(nd_if_rwlock);
 1127                 bzero(nullbuf, sizeof(nullbuf));
 1128                 for (i = 1; i < nd_ifinfo_indexlim + 1; i++) {
 1129                         ndi = &nd_ifinfo[i];
 1130                         if (ndi->flags != ND6_IFF_PERFORMNUD)
 1131                                 continue;
 1132                         if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
 1133                                 /*
 1134                                  * We've been generating a random ID on this interface.
 1135                                  * Create a new one.
 1136                                  */
 1137                                 (void)generate_tmp_ifid(ndi->randomseed0,
 1138                                                         ndi->randomseed1,
 1139                                                         ndi->randomid);
 1140                         }
 1141                 }
 1142                 lck_rw_done(nd_if_rwlock);
 1143         }
 1144 }

Cache object: 27bc5941e23d357382d943c604975839


[ 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.