LCOV - code coverage report
Current view: top level - netinet6 - nd6.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 597 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: nd6.c,v 1.226 2018/08/03 09:11:56 florian Exp $       */
       2             : /*      $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 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             : #include <sys/param.h>
      34             : #include <sys/systm.h>
      35             : #include <sys/timeout.h>
      36             : #include <sys/malloc.h>
      37             : #include <sys/mbuf.h>
      38             : #include <sys/socket.h>
      39             : #include <sys/sockio.h>
      40             : #include <sys/time.h>
      41             : #include <sys/kernel.h>
      42             : #include <sys/pool.h>
      43             : #include <sys/protosw.h>
      44             : #include <sys/errno.h>
      45             : #include <sys/ioctl.h>
      46             : #include <sys/syslog.h>
      47             : #include <sys/queue.h>
      48             : #include <sys/stdint.h>
      49             : #include <sys/task.h>
      50             : 
      51             : #include <net/if.h>
      52             : #include <net/if_dl.h>
      53             : #include <net/if_types.h>
      54             : #include <net/route.h>
      55             : 
      56             : #include <netinet/in.h>
      57             : #include <netinet/if_ether.h>
      58             : #include <netinet/ip_ipsp.h>
      59             : 
      60             : #include <netinet6/in6_var.h>
      61             : #include <netinet/ip6.h>
      62             : #include <netinet6/ip6_var.h>
      63             : #include <netinet6/nd6.h>
      64             : #include <netinet/icmp6.h>
      65             : 
      66             : #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
      67             : #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */
      68             : 
      69             : /* timer values */
      70             : int     nd6_timer_next  = -1;   /* at which time_uptime nd6_timer runs */
      71             : time_t  nd6_expire_next = -1;   /* at which time_uptime nd6_expire runs */
      72             : int     nd6_delay       = 5;    /* delay first probe time 5 second */
      73             : int     nd6_umaxtries   = 3;    /* maximum unicast query */
      74             : int     nd6_mmaxtries   = 3;    /* maximum multicast query */
      75             : int     nd6_gctimer     = (60 * 60 * 24); /* 1 day: garbage collection timer */
      76             : 
      77             : /* preventing too many loops in ND option parsing */
      78             : int nd6_maxndopt = 10;  /* max # of ND options allowed */
      79             : 
      80             : int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */
      81             : 
      82             : #ifdef ND6_DEBUG
      83             : int nd6_debug = 1;
      84             : #else
      85             : int nd6_debug = 0;
      86             : #endif
      87             : 
      88             : TAILQ_HEAD(llinfo_nd6_head, llinfo_nd6) nd6_list;
      89             : struct  pool nd6_pool;          /* pool for llinfo_nd6 structures */
      90             : int     nd6_inuse, nd6_allocated;
      91             : 
      92             : int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
      93             : 
      94             : void nd6_timer(void *);
      95             : void nd6_slowtimo(void *);
      96             : void nd6_expire(void *);
      97             : void nd6_expire_timer(void *);
      98             : void nd6_invalidate(struct rtentry *);
      99             : void nd6_free(struct rtentry *);
     100             : int nd6_llinfo_timer(struct rtentry *);
     101             : 
     102             : struct timeout nd6_timer_to;
     103             : struct timeout nd6_slowtimo_ch;
     104             : struct timeout nd6_expire_timeout;
     105             : struct task nd6_expire_task;
     106             : 
     107             : void
     108           0 : nd6_init(void)
     109             : {
     110             :         static int nd6_init_done = 0;
     111             : 
     112           0 :         if (nd6_init_done) {
     113           0 :                 log(LOG_NOTICE, "%s called more than once\n", __func__);
     114           0 :                 return;
     115             :         }
     116             : 
     117           0 :         TAILQ_INIT(&nd6_list);
     118           0 :         pool_init(&nd6_pool, sizeof(struct llinfo_nd6), 0,
     119             :             IPL_SOFTNET, 0, "nd6", NULL);
     120             : 
     121           0 :         task_set(&nd6_expire_task, nd6_expire, NULL);
     122             : 
     123           0 :         nd6_init_done = 1;
     124             : 
     125             :         /* start timer */
     126           0 :         timeout_set_proc(&nd6_timer_to, nd6_timer, &nd6_timer_to);
     127           0 :         timeout_set_proc(&nd6_slowtimo_ch, nd6_slowtimo, NULL);
     128           0 :         timeout_add_sec(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL);
     129           0 :         timeout_set(&nd6_expire_timeout, nd6_expire_timer, NULL);
     130           0 : }
     131             : 
     132             : struct nd_ifinfo *
     133           0 : nd6_ifattach(struct ifnet *ifp)
     134             : {
     135             :         struct nd_ifinfo *nd;
     136             : 
     137           0 :         nd = malloc(sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO);
     138             : 
     139           0 :         nd->initialized = 1;
     140             : 
     141           0 :         nd->basereachable = REACHABLE_TIME;
     142           0 :         nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
     143           0 :         nd->retrans = RETRANS_TIMER;
     144             :         /* per-interface IFXF_AUTOCONF6 needs to be set too to accept RAs */
     145             : 
     146           0 :         return nd;
     147             : }
     148             : 
     149             : void
     150           0 : nd6_ifdetach(struct nd_ifinfo *nd)
     151             : {
     152             : 
     153           0 :         free(nd, M_IP6NDP, sizeof(*nd));
     154           0 : }
     155             : 
     156             : void
     157           0 : nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
     158             : {
     159           0 :         bzero(ndopts, sizeof(*ndopts));
     160           0 :         ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
     161           0 :         ndopts->nd_opts_last
     162           0 :                 = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
     163             : 
     164           0 :         if (icmp6len == 0) {
     165           0 :                 ndopts->nd_opts_done = 1;
     166           0 :                 ndopts->nd_opts_search = NULL;
     167           0 :         }
     168           0 : }
     169             : 
     170             : /*
     171             :  * Take one ND option.
     172             :  */
     173             : struct nd_opt_hdr *
     174           0 : nd6_option(union nd_opts *ndopts)
     175             : {
     176             :         struct nd_opt_hdr *nd_opt;
     177             :         int olen;
     178             : 
     179           0 :         if (!ndopts)
     180           0 :                 panic("ndopts == NULL in nd6_option");
     181           0 :         if (!ndopts->nd_opts_last)
     182           0 :                 panic("%s: uninitialized ndopts", __func__);
     183           0 :         if (!ndopts->nd_opts_search)
     184           0 :                 return NULL;
     185           0 :         if (ndopts->nd_opts_done)
     186           0 :                 return NULL;
     187             : 
     188             :         nd_opt = ndopts->nd_opts_search;
     189             : 
     190             :         /* make sure nd_opt_len is inside the buffer */
     191           0 :         if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
     192           0 :                 bzero(ndopts, sizeof(*ndopts));
     193           0 :                 return NULL;
     194             :         }
     195             : 
     196           0 :         olen = nd_opt->nd_opt_len << 3;
     197           0 :         if (olen == 0) {
     198             :                 /*
     199             :                  * Message validation requires that all included
     200             :                  * options have a length that is greater than zero.
     201             :                  */
     202           0 :                 bzero(ndopts, sizeof(*ndopts));
     203           0 :                 return NULL;
     204             :         }
     205             : 
     206           0 :         ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
     207           0 :         if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
     208             :                 /* option overruns the end of buffer, invalid */
     209           0 :                 bzero(ndopts, sizeof(*ndopts));
     210           0 :                 return NULL;
     211           0 :         } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
     212             :                 /* reached the end of options chain */
     213           0 :                 ndopts->nd_opts_done = 1;
     214           0 :                 ndopts->nd_opts_search = NULL;
     215           0 :         }
     216           0 :         return nd_opt;
     217           0 : }
     218             : 
     219             : /*
     220             :  * Parse multiple ND options.
     221             :  * This function is much easier to use, for ND routines that do not need
     222             :  * multiple options of the same type.
     223             :  */
     224             : int
     225           0 : nd6_options(union nd_opts *ndopts)
     226             : {
     227             :         struct nd_opt_hdr *nd_opt;
     228             :         int i = 0;
     229             : 
     230           0 :         if (!ndopts)
     231           0 :                 panic("ndopts == NULL in nd6_options");
     232           0 :         if (!ndopts->nd_opts_last)
     233           0 :                 panic("%s: uninitialized ndopts", __func__);
     234           0 :         if (!ndopts->nd_opts_search)
     235           0 :                 return 0;
     236             : 
     237           0 :         while (1) {
     238           0 :                 nd_opt = nd6_option(ndopts);
     239           0 :                 if (!nd_opt && !ndopts->nd_opts_last) {
     240             :                         /*
     241             :                          * Message validation requires that all included
     242             :                          * options have a length that is greater than zero.
     243             :                          */
     244           0 :                         icmp6stat_inc(icp6s_nd_badopt);
     245           0 :                         bzero(ndopts, sizeof(*ndopts));
     246           0 :                         return -1;
     247             :                 }
     248             : 
     249           0 :                 if (!nd_opt)
     250             :                         goto skip1;
     251             : 
     252           0 :                 switch (nd_opt->nd_opt_type) {
     253             :                 case ND_OPT_SOURCE_LINKADDR:
     254             :                 case ND_OPT_TARGET_LINKADDR:
     255             :                 case ND_OPT_MTU:
     256             :                 case ND_OPT_REDIRECTED_HEADER:
     257           0 :                         if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
     258           0 :                                 nd6log((LOG_INFO,
     259             :                                     "duplicated ND6 option found (type=%d)\n",
     260             :                                     nd_opt->nd_opt_type));
     261             :                                 /* XXX bark? */
     262             :                         } else {
     263             :                                 ndopts->nd_opt_array[nd_opt->nd_opt_type]
     264           0 :                                         = nd_opt;
     265             :                         }
     266             :                         break;
     267             :                 case ND_OPT_PREFIX_INFORMATION:
     268           0 :                         if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
     269             :                                 ndopts->nd_opt_array[nd_opt->nd_opt_type]
     270           0 :                                         = nd_opt;
     271           0 :                         }
     272           0 :                         ndopts->nd_opts_pi_end =
     273           0 :                                 (struct nd_opt_prefix_info *)nd_opt;
     274           0 :                         break;
     275             :                 default:
     276             :                         /*
     277             :                          * Unknown options must be silently ignored,
     278             :                          * to accommodate future extension to the protocol.
     279             :                          */
     280           0 :                         nd6log((LOG_DEBUG,
     281             :                             "nd6_options: unsupported option %d - "
     282             :                             "option ignored\n", nd_opt->nd_opt_type));
     283             :                 }
     284             : 
     285             : skip1:
     286           0 :                 i++;
     287           0 :                 if (i > nd6_maxndopt) {
     288           0 :                         icmp6stat_inc(icp6s_nd_toomanyopt);
     289           0 :                         nd6log((LOG_INFO, "too many loop in nd opt\n"));
     290             :                         break;
     291             :                 }
     292             : 
     293           0 :                 if (ndopts->nd_opts_done)
     294             :                         break;
     295             :         }
     296             : 
     297           0 :         return 0;
     298           0 : }
     299             : 
     300             : /*
     301             :  * ND6 timer routine to handle ND6 entries
     302             :  */
     303             : void
     304           0 : nd6_llinfo_settimer(struct llinfo_nd6 *ln, unsigned int secs)
     305             : {
     306           0 :         time_t expire = time_uptime + secs;
     307             : 
     308           0 :         NET_ASSERT_LOCKED();
     309             : 
     310           0 :         ln->ln_rt->rt_expire = expire;
     311           0 :         if (!timeout_pending(&nd6_timer_to) || expire < nd6_timer_next) {
     312           0 :                 nd6_timer_next = expire;
     313           0 :                 timeout_add_sec(&nd6_timer_to, secs);
     314           0 :         }
     315           0 : }
     316             : 
     317             : void
     318           0 : nd6_timer(void *arg)
     319             : {
     320             :         struct llinfo_nd6 *ln, *nln;
     321           0 :         time_t expire = time_uptime + nd6_gctimer;
     322             :         int secs;
     323             : 
     324           0 :         NET_LOCK();
     325           0 :         TAILQ_FOREACH_SAFE(ln, &nd6_list, ln_list, nln) {
     326           0 :                 struct rtentry *rt = ln->ln_rt;
     327             : 
     328           0 :                 if (rt->rt_expire && rt->rt_expire <= time_uptime)
     329           0 :                         if (nd6_llinfo_timer(rt))
     330           0 :                                 continue;
     331             : 
     332           0 :                 if (rt->rt_expire && rt->rt_expire < expire)
     333           0 :                         expire = rt->rt_expire;
     334           0 :         }
     335             : 
     336           0 :         secs = expire - time_uptime;
     337           0 :         if (secs < 0)
     338             :                 secs = 0;
     339           0 :         if (!TAILQ_EMPTY(&nd6_list)) {
     340           0 :                 nd6_timer_next = time_uptime + secs;
     341           0 :                 timeout_add_sec(&nd6_timer_to, secs);
     342           0 :         }
     343             : 
     344           0 :         NET_UNLOCK();
     345           0 : }
     346             : 
     347             : /*
     348             :  * ND timer state handling.
     349             :  *
     350             :  * Returns 1 if `rt' should no longer be used, 0 otherwise.
     351             :  */
     352             : int
     353           0 : nd6_llinfo_timer(struct rtentry *rt)
     354             : {
     355           0 :         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
     356           0 :         struct sockaddr_in6 *dst = satosin6(rt_key(rt));
     357             :         struct ifnet *ifp;
     358             :         struct nd_ifinfo *ndi = NULL;
     359             : 
     360           0 :         NET_ASSERT_LOCKED();
     361             : 
     362           0 :         if ((ifp = if_get(rt->rt_ifidx)) == NULL)
     363           0 :                 return 1;
     364             : 
     365           0 :         ndi = ND_IFINFO(ifp);
     366             : 
     367           0 :         switch (ln->ln_state) {
     368             :         case ND6_LLINFO_INCOMPLETE:
     369           0 :                 if (ln->ln_asked < nd6_mmaxtries) {
     370           0 :                         ln->ln_asked++;
     371           0 :                         nd6_llinfo_settimer(ln, ndi->retrans / 1000);
     372           0 :                         nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
     373           0 :                 } else {
     374           0 :                         struct mbuf *m = ln->ln_hold;
     375           0 :                         if (m) {
     376           0 :                                 ln->ln_hold = NULL;
     377             :                                 /*
     378             :                                  * Fake rcvif to make the ICMP error
     379             :                                  * more helpful in diagnosing for the
     380             :                                  * receiver.
     381             :                                  * XXX: should we consider
     382             :                                  * older rcvif?
     383             :                                  */
     384           0 :                                 m->m_pkthdr.ph_ifidx = rt->rt_ifidx;
     385             : 
     386           0 :                                 icmp6_error(m, ICMP6_DST_UNREACH,
     387             :                                     ICMP6_DST_UNREACH_ADDR, 0);
     388           0 :                                 if (ln->ln_hold == m) {
     389             :                                         /* m is back in ln_hold. Discard. */
     390           0 :                                         m_freem(ln->ln_hold);
     391           0 :                                         ln->ln_hold = NULL;
     392           0 :                                 }
     393             :                         }
     394           0 :                         nd6_free(rt);
     395             :                         ln = NULL;
     396             :                 }
     397             :                 break;
     398             :         case ND6_LLINFO_REACHABLE:
     399           0 :                 if (!ND6_LLINFO_PERMANENT(ln)) {
     400           0 :                         ln->ln_state = ND6_LLINFO_STALE;
     401           0 :                         nd6_llinfo_settimer(ln, nd6_gctimer);
     402           0 :                 }
     403             :                 break;
     404             : 
     405             :         case ND6_LLINFO_STALE:
     406             :         case ND6_LLINFO_PURGE:
     407             :                 /* Garbage Collection(RFC 2461 5.3) */
     408           0 :                 if (!ND6_LLINFO_PERMANENT(ln)) {
     409           0 :                         nd6_free(rt);
     410             :                         ln = NULL;
     411           0 :                 }
     412             :                 break;
     413             : 
     414             :         case ND6_LLINFO_DELAY:
     415           0 :                 if (ndi) {
     416             :                         /* We need NUD */
     417           0 :                         ln->ln_asked = 1;
     418           0 :                         ln->ln_state = ND6_LLINFO_PROBE;
     419           0 :                         nd6_llinfo_settimer(ln, ndi->retrans / 1000);
     420           0 :                         nd6_ns_output(ifp, &dst->sin6_addr,
     421             :                             &dst->sin6_addr, ln, 0);
     422           0 :                 }
     423             :                 break;
     424             :         case ND6_LLINFO_PROBE:
     425           0 :                 if (ln->ln_asked < nd6_umaxtries) {
     426           0 :                         ln->ln_asked++;
     427           0 :                         nd6_llinfo_settimer(ln, ndi->retrans / 1000);
     428           0 :                         nd6_ns_output(ifp, &dst->sin6_addr,
     429             :                             &dst->sin6_addr, ln, 0);
     430           0 :                 } else {
     431           0 :                         nd6_free(rt);
     432             :                         ln = NULL;
     433             :                 }
     434             :                 break;
     435             :         }
     436             : 
     437           0 :         if_put(ifp);
     438             : 
     439           0 :         return (ln == NULL);
     440           0 : }
     441             : 
     442             : void
     443           0 : nd6_expire_timer_update(struct in6_ifaddr *ia6)
     444             : {
     445             :         time_t expire_time = INT64_MAX;
     446             :         int secs;
     447             : 
     448           0 :         KERNEL_ASSERT_LOCKED();
     449             : 
     450           0 :         if (ia6->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME)
     451           0 :                 expire_time = ia6->ia6_lifetime.ia6t_expire;
     452             : 
     453           0 :         if (!(ia6->ia6_flags & IN6_IFF_DEPRECATED) &&
     454           0 :             ia6->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME &&
     455           0 :             expire_time > ia6->ia6_lifetime.ia6t_preferred)
     456           0 :                 expire_time = ia6->ia6_lifetime.ia6t_preferred;
     457             : 
     458           0 :         if (expire_time == INT64_MAX)
     459           0 :                 return;
     460             : 
     461             :         /*
     462             :          * IFA6_IS_INVALID() and IFA6_IS_DEPRECATED() check for uptime
     463             :          * greater than ia6t_expire or ia6t_preferred, not greater or equal.
     464             :          * Schedule timeout one second later so that either IFA6_IS_INVALID()
     465             :          * or IFA6_IS_DEPRECATED() is true.
     466             :          */
     467           0 :         expire_time++;
     468             : 
     469           0 :         if (!timeout_pending(&nd6_expire_timeout) ||
     470           0 :             nd6_expire_next > expire_time) {
     471           0 :                 secs = expire_time - time_uptime;
     472           0 :                 if (secs < 0)
     473             :                         secs = 0;
     474             : 
     475           0 :                 timeout_add_sec(&nd6_expire_timeout, secs);
     476           0 :                 nd6_expire_next = expire_time;
     477           0 :         }
     478           0 : }
     479             : 
     480             : /*
     481             :  * Expire interface addresses.
     482             :  */
     483             : void
     484           0 : nd6_expire(void *unused)
     485             : {
     486             :         struct ifnet *ifp;
     487             : 
     488           0 :         KERNEL_LOCK();
     489           0 :         NET_LOCK();
     490             : 
     491           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
     492             :                 struct ifaddr *ifa, *nifa;
     493             :                 struct in6_ifaddr *ia6;
     494             : 
     495           0 :                 TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, nifa) {
     496           0 :                         if (ifa->ifa_addr->sa_family != AF_INET6)
     497             :                                 continue;
     498           0 :                         ia6 = ifatoia6(ifa);
     499             :                         /* check address lifetime */
     500           0 :                         if (IFA6_IS_INVALID(ia6)) {
     501           0 :                                 in6_purgeaddr(&ia6->ia_ifa);
     502           0 :                         } else {
     503           0 :                                 if (IFA6_IS_DEPRECATED(ia6))
     504           0 :                                         ia6->ia6_flags |= IN6_IFF_DEPRECATED;
     505           0 :                                 nd6_expire_timer_update(ia6);
     506             :                         }
     507             :                 }
     508             :         }
     509             : 
     510           0 :         NET_UNLOCK();
     511           0 :         KERNEL_UNLOCK();
     512           0 : }
     513             : 
     514             : void
     515           0 : nd6_expire_timer(void *unused)
     516             : {
     517           0 :         task_add(net_tq(0), &nd6_expire_task);
     518           0 : }
     519             : 
     520             : /*
     521             :  * Nuke neighbor cache/prefix/default router management table, right before
     522             :  * ifp goes away.
     523             :  */
     524             : void
     525           0 : nd6_purge(struct ifnet *ifp)
     526             : {
     527             :         struct llinfo_nd6 *ln, *nln;
     528             : 
     529           0 :         NET_ASSERT_LOCKED();
     530             : 
     531             :         /*
     532             :          * Nuke neighbor cache entries for the ifp.
     533             :          */
     534           0 :         TAILQ_FOREACH_SAFE(ln, &nd6_list, ln_list, nln) {
     535             :                 struct rtentry *rt;
     536             :                 struct sockaddr_dl *sdl;
     537             : 
     538           0 :                 rt = ln->ln_rt;
     539           0 :                 if (rt != NULL && rt->rt_gateway != NULL &&
     540           0 :                     rt->rt_gateway->sa_family == AF_LINK) {
     541           0 :                         sdl = satosdl(rt->rt_gateway);
     542           0 :                         if (sdl->sdl_index == ifp->if_index)
     543           0 :                                 nd6_free(rt);
     544             :                 }
     545             :         }
     546           0 : }
     547             : 
     548             : struct rtentry *
     549           0 : nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp,
     550             :     u_int rtableid)
     551             : {
     552           0 :         struct rtentry *rt;
     553           0 :         struct sockaddr_in6 sin6;
     554             :         int flags;
     555             : 
     556           0 :         bzero(&sin6, sizeof(sin6));
     557           0 :         sin6.sin6_len = sizeof(struct sockaddr_in6);
     558           0 :         sin6.sin6_family = AF_INET6;
     559           0 :         sin6.sin6_addr = *addr6;
     560           0 :         flags = (create) ? RT_RESOLVE : 0;
     561             : 
     562           0 :         rt = rtalloc(sin6tosa(&sin6), flags, rtableid);
     563           0 :         if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) {
     564             :                 /*
     565             :                  * This is the case for the default route.
     566             :                  * If we want to create a neighbor cache for the address, we
     567             :                  * should free the route for the destination and allocate an
     568             :                  * interface route.
     569             :                  */
     570             :                 if (create) {
     571           0 :                         rtfree(rt);
     572           0 :                         rt = NULL;
     573           0 :                 }
     574             :         }
     575           0 :         if (rt == NULL) {
     576           0 :                 if (create && ifp) {
     577           0 :                         struct rt_addrinfo info;
     578             :                         struct ifaddr *ifa;
     579             :                         int error;
     580             : 
     581             :                         /*
     582             :                          * If no route is available and create is set,
     583             :                          * we allocate a host route for the destination
     584             :                          * and treat it like an interface route.
     585             :                          * This hack is necessary for a neighbor which can't
     586             :                          * be covered by our own prefix.
     587             :                          */
     588           0 :                         ifa = ifaof_ifpforaddr(sin6tosa(&sin6), ifp);
     589           0 :                         if (ifa == NULL)
     590           0 :                                 return (NULL);
     591             : 
     592             :                         /*
     593             :                          * Create a new route.  RTF_LLINFO is necessary
     594             :                          * to create a Neighbor Cache entry for the
     595             :                          * destination in nd6_rtrequest which will be
     596             :                          * called in rtrequest.
     597             :                          */
     598           0 :                         bzero(&info, sizeof(info));
     599           0 :                         info.rti_ifa = ifa;
     600           0 :                         info.rti_flags = RTF_HOST | RTF_LLINFO;
     601           0 :                         info.rti_info[RTAX_DST] = sin6tosa(&sin6);
     602           0 :                         info.rti_info[RTAX_GATEWAY] = sdltosa(ifp->if_sadl);
     603           0 :                         error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, &rt,
     604             :                             rtableid);
     605           0 :                         if (error)
     606           0 :                                 return (NULL);
     607           0 :                         if (rt->rt_llinfo != NULL) {
     608             :                                 struct llinfo_nd6 *ln =
     609           0 :                                     (struct llinfo_nd6 *)rt->rt_llinfo;
     610           0 :                                 ln->ln_state = ND6_LLINFO_NOSTATE;
     611           0 :                         }
     612           0 :                 } else
     613           0 :                         return (NULL);
     614             :         }
     615             :         /*
     616             :          * Validation for the entry.
     617             :          * Note that the check for rt_llinfo is necessary because a cloned
     618             :          * route from a parent route that has the L flag (e.g. the default
     619             :          * route to a p2p interface) may have the flag, too, while the
     620             :          * destination is not actually a neighbor.
     621             :          */
     622           0 :         if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
     623           0 :             rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
     624           0 :             (ifp != NULL && rt->rt_ifidx != ifp->if_index)) {
     625           0 :                 if (create) {
     626           0 :                         char addr[INET6_ADDRSTRLEN];
     627           0 :                         nd6log((LOG_DEBUG, "%s: failed to lookup %s (if=%s)\n",
     628             :                             __func__,
     629             :                             inet_ntop(AF_INET6, addr6, addr, sizeof(addr)),
     630             :                             ifp ? ifp->if_xname : "unspec"));
     631           0 :                 }
     632           0 :                 rtfree(rt);
     633           0 :                 return (NULL);
     634             :         }
     635           0 :         return (rt);
     636           0 : }
     637             : 
     638             : /*
     639             :  * Detect if a given IPv6 address identifies a neighbor on a given link.
     640             :  * XXX: should take care of the destination of a p2p link?
     641             :  */
     642             : int
     643           0 : nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
     644             : {
     645             :         struct in6_ifaddr *ia6;
     646             :         struct ifaddr *ifa;
     647             :         struct rtentry *rt;
     648             : 
     649             :         /*
     650             :          * A link-local address is always a neighbor.
     651             :          * XXX: we should use the sin6_scope_id field rather than the embedded
     652             :          * interface index.
     653             :          * XXX: a link does not necessarily specify a single interface.
     654             :          */
     655           0 :         if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr) &&
     656           0 :             ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]) == ifp->if_index)
     657           0 :                 return (1);
     658             : 
     659           0 :         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
     660           0 :                 if (ifa->ifa_addr->sa_family != AF_INET6)
     661             :                         continue;
     662             : 
     663           0 :                 ia6 = ifatoia6(ifa);
     664             : 
     665             :                 /* Prefix check down below. */
     666           0 :                 if (ia6->ia6_flags & IN6_IFF_AUTOCONF)
     667             :                         continue;
     668             : 
     669           0 :                 if (IN6_ARE_MASKED_ADDR_EQUAL(&addr->sin6_addr,
     670             :                     &ia6->ia_addr.sin6_addr,
     671             :                     &ia6->ia_prefixmask.sin6_addr))
     672           0 :                         return (1);
     673             :         }
     674             : 
     675             :         /*
     676             :          * Even if the address matches none of our addresses, it might be
     677             :          * in the neighbor cache.
     678             :          */
     679           0 :         rt = nd6_lookup(&addr->sin6_addr, 0, ifp, ifp->if_rdomain);
     680           0 :         if (rt != NULL) {
     681           0 :                 rtfree(rt);
     682           0 :                 return (1);
     683             :         }
     684             : 
     685           0 :         return (0);
     686           0 : }
     687             : 
     688             : void
     689           0 : nd6_invalidate(struct rtentry *rt)
     690             : {
     691           0 :         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
     692             : 
     693           0 :         m_freem(ln->ln_hold);
     694           0 :         ln->ln_hold = NULL;
     695           0 :         ln->ln_state = ND6_LLINFO_INCOMPLETE;
     696           0 :         ln->ln_asked = 0;
     697           0 : }
     698             : 
     699             : /*
     700             :  * Free an nd6 llinfo entry.
     701             :  * Since the function would cause significant changes in the kernel, DO NOT
     702             :  * make it global, unless you have a strong reason for the change, and are sure
     703             :  * that the change is safe.
     704             :  */
     705             : void
     706           0 : nd6_free(struct rtentry *rt)
     707             : {
     708           0 :         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
     709           0 :         struct in6_addr in6 = satosin6(rt_key(rt))->sin6_addr;
     710             :         struct ifnet *ifp;
     711             : 
     712           0 :         NET_ASSERT_LOCKED();
     713             : 
     714           0 :         ifp = if_get(rt->rt_ifidx);
     715             : 
     716           0 :         if (!ip6_forwarding) {
     717           0 :                 if (ln->ln_router) {
     718             :                         /*
     719             :                          * rt6_flush must be called whether or not the neighbor
     720             :                          * is in the Default Router List.
     721             :                          * See a corresponding comment in nd6_na_input().
     722             :                          */
     723           0 :                         rt6_flush(&in6, ifp);
     724           0 :                 }
     725             :         }
     726             : 
     727           0 :         KASSERT(!ISSET(rt->rt_flags, RTF_LOCAL));
     728           0 :         nd6_invalidate(rt);
     729             : 
     730             :         /*
     731             :          * Detach the route from the routing tree and the list of neighbor
     732             :          * caches, and disable the route entry not to be used in already
     733             :          * cached routes.
     734             :          */
     735           0 :         if (!ISSET(rt->rt_flags, RTF_STATIC|RTF_CACHED))
     736           0 :                 rtdeletemsg(rt, ifp, ifp->if_rdomain);
     737             : 
     738           0 :         if_put(ifp);
     739           0 : }
     740             : 
     741             : /*
     742             :  * Upper-layer reachability hint for Neighbor Unreachability Detection.
     743             :  *
     744             :  * XXX cost-effective methods?
     745             :  */
     746             : void
     747           0 : nd6_nud_hint(struct rtentry *rt)
     748             : {
     749             :         struct llinfo_nd6 *ln;
     750             :         struct ifnet *ifp;
     751             : 
     752           0 :         ifp = if_get(rt->rt_ifidx);
     753           0 :         if (ifp == NULL)
     754           0 :                 return;
     755             : 
     756           0 :         if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
     757           0 :             (rt->rt_flags & RTF_LLINFO) == 0 ||
     758           0 :             rt->rt_llinfo == NULL || rt->rt_gateway == NULL ||
     759           0 :             rt->rt_gateway->sa_family != AF_LINK) {
     760             :                 /* This is not a host route. */
     761             :                 goto out;
     762             :         }
     763             : 
     764           0 :         ln = (struct llinfo_nd6 *)rt->rt_llinfo;
     765           0 :         if (ln->ln_state < ND6_LLINFO_REACHABLE)
     766             :                 goto out;
     767             : 
     768             :         /*
     769             :          * if we get upper-layer reachability confirmation many times,
     770             :          * it is possible we have false information.
     771             :          */
     772           0 :         ln->ln_byhint++;
     773           0 :         if (ln->ln_byhint > nd6_maxnudhint)
     774             :                 goto out;
     775             : 
     776           0 :         ln->ln_state = ND6_LLINFO_REACHABLE;
     777           0 :         if (!ND6_LLINFO_PERMANENT(ln))
     778           0 :                 nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->reachable);
     779             : out:
     780           0 :         if_put(ifp);
     781           0 : }
     782             : 
     783             : void
     784           0 : nd6_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
     785             : {
     786           0 :         struct sockaddr *gate = rt->rt_gateway;
     787           0 :         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
     788             :         struct ifaddr *ifa;
     789             : 
     790           0 :         if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_MULTICAST))
     791           0 :                 return;
     792             : 
     793           0 :         if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
     794             :                 /*
     795             :                  * This is probably an interface direct route for a link
     796             :                  * which does not need neighbor caches (e.g. fe80::%lo0/64).
     797             :                  * We do not need special treatment below for such a route.
     798             :                  * Moreover, the RTF_LLINFO flag which would be set below
     799             :                  * would annoy the ndp(8) command.
     800             :                  */
     801           0 :                 return;
     802             :         }
     803             : 
     804           0 :         if (req == RTM_RESOLVE && nd6_need_cache(ifp) == 0) {
     805             :                 /*
     806             :                  * For routing daemons like ospf6d we allow neighbor discovery
     807             :                  * based on the cloning route only.  This allows us to sent
     808             :                  * packets directly into a network without having an address
     809             :                  * with matching prefix on the interface.  If the cloning
     810             :                  * route is used for an stf interface, we would mistakenly
     811             :                  * make a neighbor cache for the host route, and would see
     812             :                  * strange neighbor solicitation for the corresponding
     813             :                  * destination.  In order to avoid confusion, we check if the
     814             :                  * interface is suitable for neighbor discovery, and stop the
     815             :                  * process if not.  Additionally, we remove the LLINFO flag
     816             :                  * so that ndp(8) will not try to get the neighbor information
     817             :                  * of the destination.
     818             :                  */
     819           0 :                 rt->rt_flags &= ~RTF_LLINFO;
     820           0 :                 return;
     821             :         }
     822             : 
     823           0 :         switch (req) {
     824             :         case RTM_ADD:
     825           0 :                 if ((rt->rt_flags & RTF_CLONING) ||
     826           0 :                     ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && ln == NULL)) {
     827           0 :                         if (ln != NULL)
     828           0 :                                 nd6_llinfo_settimer(ln, 0);
     829           0 :                         if ((rt->rt_flags & RTF_CLONING) != 0)
     830             :                                 break;
     831             :                 }
     832             :                 /*
     833             :                  * In IPv4 code, we try to announce new RTF_ANNOUNCE entry here.
     834             :                  * We don't do that here since llinfo is not ready yet.
     835             :                  *
     836             :                  * There are also couple of other things to be discussed:
     837             :                  * - unsolicited NA code needs improvement beforehand
     838             :                  * - RFC2461 says we MAY send multicast unsolicited NA
     839             :                  *   (7.2.6 paragraph 4), however, it also says that we
     840             :                  *   SHOULD provide a mechanism to prevent multicast NA storm.
     841             :                  *   we don't have anything like it right now.
     842             :                  *   note that the mechanism needs a mutual agreement
     843             :                  *   between proxies, which means that we need to implement
     844             :                  *   a new protocol, or a new kludge.
     845             :                  * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
     846             :                  *   we need to check ip6forwarding before sending it.
     847             :                  *   (or should we allow proxy ND configuration only for
     848             :                  *   routers?  there's no mention about proxy ND from hosts)
     849             :                  */
     850             : #if 0
     851             :                 /* XXX it does not work */
     852             :                 if (rt->rt_flags & RTF_ANNOUNCE)
     853             :                         nd6_na_output(ifp,
     854             :                               &satosin6(rt_key(rt))->sin6_addr,
     855             :                               &satosin6(rt_key(rt))->sin6_addr,
     856             :                               ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
     857             :                               1, NULL);
     858             : #endif
     859             :                 /* FALLTHROUGH */
     860             :         case RTM_RESOLVE:
     861           0 :                 if (gate->sa_family != AF_LINK ||
     862           0 :                     gate->sa_len < sizeof(struct sockaddr_dl)) {
     863           0 :                         log(LOG_DEBUG, "%s: bad gateway value: %s\n",
     864           0 :                             __func__, ifp->if_xname);
     865           0 :                         break;
     866             :                 }
     867           0 :                 satosdl(gate)->sdl_type = ifp->if_type;
     868           0 :                 satosdl(gate)->sdl_index = ifp->if_index;
     869           0 :                 if (ln != NULL)
     870             :                         break;  /* This happens on a route change */
     871             :                 /*
     872             :                  * Case 2: This route may come from cloning, or a manual route
     873             :                  * add with a LL address.
     874             :                  */
     875           0 :                 ln = pool_get(&nd6_pool, PR_NOWAIT | PR_ZERO);
     876           0 :                 rt->rt_llinfo = (caddr_t)ln;
     877           0 :                 if (ln == NULL) {
     878           0 :                         log(LOG_DEBUG, "%s: pool get failed\n", __func__);
     879           0 :                         break;
     880             :                 }
     881           0 :                 nd6_inuse++;
     882           0 :                 nd6_allocated++;
     883           0 :                 ln->ln_rt = rt;
     884             :                 /* this is required for "ndp" command. - shin */
     885           0 :                 if (req == RTM_ADD) {
     886             :                         /*
     887             :                          * gate should have some valid AF_LINK entry,
     888             :                          * and ln expire should have some lifetime
     889             :                          * which is specified by ndp command.
     890             :                          */
     891           0 :                         ln->ln_state = ND6_LLINFO_REACHABLE;
     892           0 :                         ln->ln_byhint = 0;
     893           0 :                 } else {
     894             :                         /*
     895             :                          * When req == RTM_RESOLVE, rt is created and
     896             :                          * initialized in rtrequest(), so rt_expire is 0.
     897             :                          */
     898           0 :                         ln->ln_state = ND6_LLINFO_NOSTATE;
     899           0 :                         nd6_llinfo_settimer(ln, 0);
     900             :                 }
     901           0 :                 rt->rt_flags |= RTF_LLINFO;
     902           0 :                 TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list);
     903             : 
     904             :                 /*
     905             :                  * If we have too many cache entries, initiate immediate
     906             :                  * purging for some "less recently used" entries.  Note that
     907             :                  * we cannot directly call nd6_free() here because it would
     908             :                  * cause re-entering rtable related routines triggering an LOR
     909             :                  * problem for FreeBSD.
     910             :                  */
     911           0 :                 if (ip6_neighborgcthresh >= 0 &&
     912           0 :                     nd6_inuse >= ip6_neighborgcthresh) {
     913             :                         int i;
     914             : 
     915           0 :                         for (i = 0; i < 10; i++) {
     916             :                                 struct llinfo_nd6 *ln_end;
     917             : 
     918           0 :                                 ln_end = TAILQ_LAST(&nd6_list, llinfo_nd6_head);
     919           0 :                                 if (ln_end == ln)
     920           0 :                                         break;
     921             : 
     922             :                                 /* Move this entry to the head */
     923           0 :                                 TAILQ_REMOVE(&nd6_list, ln_end, ln_list);
     924           0 :                                 TAILQ_INSERT_HEAD(&nd6_list, ln_end, ln_list);
     925             : 
     926           0 :                                 if (ND6_LLINFO_PERMANENT(ln_end))
     927           0 :                                         continue;
     928             : 
     929           0 :                                 if (ln_end->ln_state > ND6_LLINFO_INCOMPLETE)
     930           0 :                                         ln_end->ln_state = ND6_LLINFO_STALE;
     931             :                                 else
     932           0 :                                         ln_end->ln_state = ND6_LLINFO_PURGE;
     933           0 :                                 nd6_llinfo_settimer(ln_end, 0);
     934           0 :                         }
     935           0 :                 }
     936             : 
     937             :                 /*
     938             :                  * check if rt_key(rt) is one of my address assigned
     939             :                  * to the interface.
     940             :                  */
     941           0 :                 ifa = &in6ifa_ifpwithaddr(ifp,
     942           0 :                     &satosin6(rt_key(rt))->sin6_addr)->ia_ifa;
     943           0 :                 if (ifa) {
     944           0 :                         ln->ln_state = ND6_LLINFO_REACHABLE;
     945           0 :                         ln->ln_byhint = 0;
     946           0 :                         rt->rt_expire = 0;
     947           0 :                         KASSERT(ifa == rt->rt_ifa);
     948           0 :                 } else if (rt->rt_flags & RTF_ANNOUNCE) {
     949           0 :                         ln->ln_state = ND6_LLINFO_REACHABLE;
     950           0 :                         ln->ln_byhint = 0;
     951           0 :                         rt->rt_expire = 0;
     952             : 
     953             :                         /* join solicited node multicast for proxy ND */
     954           0 :                         if (ifp->if_flags & IFF_MULTICAST) {
     955           0 :                                 struct in6_addr llsol;
     956           0 :                                 int error;
     957             : 
     958           0 :                                 llsol = satosin6(rt_key(rt))->sin6_addr;
     959           0 :                                 llsol.s6_addr16[0] = htons(0xff02);
     960           0 :                                 llsol.s6_addr16[1] = htons(ifp->if_index);
     961           0 :                                 llsol.s6_addr32[1] = 0;
     962           0 :                                 llsol.s6_addr32[2] = htonl(1);
     963           0 :                                 llsol.s6_addr8[12] = 0xff;
     964             : 
     965           0 :                                 if (in6_addmulti(&llsol, ifp, &error)) {
     966           0 :                                         char addr[INET6_ADDRSTRLEN];
     967           0 :                                         nd6log((LOG_ERR, "%s: failed to join "
     968             :                                             "%s (errno=%d)\n", ifp->if_xname,
     969             :                                             inet_ntop(AF_INET6, &llsol,
     970             :                                                 addr, sizeof(addr)),
     971             :                                             error));
     972           0 :                                 }
     973           0 :                         }
     974             :                 }
     975             :                 break;
     976             : 
     977             :         case RTM_DELETE:
     978           0 :                 if (ln == NULL)
     979             :                         break;
     980             :                 /* leave from solicited node multicast for proxy ND */
     981           0 :                 if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
     982           0 :                     (ifp->if_flags & IFF_MULTICAST) != 0) {
     983           0 :                         struct in6_addr llsol;
     984             :                         struct in6_multi *in6m;
     985             : 
     986           0 :                         llsol = satosin6(rt_key(rt))->sin6_addr;
     987           0 :                         llsol.s6_addr16[0] = htons(0xff02);
     988           0 :                         llsol.s6_addr16[1] = htons(ifp->if_index);
     989           0 :                         llsol.s6_addr32[1] = 0;
     990           0 :                         llsol.s6_addr32[2] = htonl(1);
     991           0 :                         llsol.s6_addr8[12] = 0xff;
     992             : 
     993           0 :                         IN6_LOOKUP_MULTI(llsol, ifp, in6m);
     994           0 :                         if (in6m)
     995           0 :                                 in6_delmulti(in6m);
     996           0 :                 }
     997           0 :                 nd6_inuse--;
     998           0 :                 TAILQ_REMOVE(&nd6_list, ln, ln_list);
     999           0 :                 rt->rt_expire = 0;
    1000           0 :                 rt->rt_llinfo = NULL;
    1001           0 :                 rt->rt_flags &= ~RTF_LLINFO;
    1002           0 :                 m_freem(ln->ln_hold);
    1003           0 :                 pool_put(&nd6_pool, ln);
    1004           0 :                 break;
    1005             : 
    1006             :         case RTM_INVALIDATE:
    1007           0 :                 if (!ISSET(rt->rt_flags, RTF_LOCAL))
    1008           0 :                         nd6_invalidate(rt);
    1009             :                 break;
    1010             :         }
    1011           0 : }
    1012             : 
    1013             : int
    1014           0 : nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
    1015             : {
    1016           0 :         struct in6_ndireq *ndi = (struct in6_ndireq *)data;
    1017           0 :         struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
    1018             :         struct rtentry *rt;
    1019             : 
    1020           0 :         switch (cmd) {
    1021             :         case SIOCGIFINFO_IN6:
    1022           0 :                 NET_RLOCK();
    1023           0 :                 ndi->ndi = *ND_IFINFO(ifp);
    1024           0 :                 NET_RUNLOCK();
    1025           0 :                 return (0);
    1026             :         case SIOCGNBRINFO_IN6:
    1027             :         {
    1028             :                 struct llinfo_nd6 *ln;
    1029           0 :                 struct in6_addr nb_addr = nbi->addr; /* make local for safety */
    1030             :                 time_t expire;
    1031             : 
    1032           0 :                 NET_RLOCK();
    1033             :                 /*
    1034             :                  * XXX: KAME specific hack for scoped addresses
    1035             :                  *      XXXX: for other scopes than link-local?
    1036             :                  */
    1037           0 :                 if (IN6_IS_ADDR_LINKLOCAL(&nbi->addr) ||
    1038           0 :                     IN6_IS_ADDR_MC_LINKLOCAL(&nbi->addr)) {
    1039           0 :                         u_int16_t *idp = (u_int16_t *)&nb_addr.s6_addr[2];
    1040             : 
    1041           0 :                         if (*idp == 0)
    1042           0 :                                 *idp = htons(ifp->if_index);
    1043           0 :                 }
    1044             : 
    1045           0 :                 rt = nd6_lookup(&nb_addr, 0, ifp, ifp->if_rdomain);
    1046           0 :                 if (rt == NULL ||
    1047           0 :                     (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
    1048           0 :                         rtfree(rt);
    1049           0 :                         NET_RUNLOCK();
    1050           0 :                         return (EINVAL);
    1051             :                 }
    1052           0 :                 expire = ln->ln_rt->rt_expire;
    1053           0 :                 if (expire != 0) {
    1054           0 :                         expire -= time_uptime;
    1055           0 :                         expire += time_second;
    1056           0 :                 }
    1057             : 
    1058           0 :                 nbi->state = ln->ln_state;
    1059           0 :                 nbi->asked = ln->ln_asked;
    1060           0 :                 nbi->isrouter = ln->ln_router;
    1061           0 :                 nbi->expire = expire;
    1062             : 
    1063           0 :                 rtfree(rt);
    1064           0 :                 NET_RUNLOCK();
    1065           0 :                 return (0);
    1066           0 :         }
    1067             :         }
    1068           0 :         return (0);
    1069           0 : }
    1070             : 
    1071             : /*
    1072             :  * Create neighbor cache entry and cache link-layer address,
    1073             :  * on reception of inbound ND6 packets.  (RS/RA/NS/redirect)
    1074             :  *
    1075             :  * type - ICMP6 type
    1076             :  * code - type dependent information
    1077             :  */
    1078             : void
    1079           0 : nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
    1080             :     int lladdrlen, int type, int code)
    1081             : {
    1082             :         struct rtentry *rt = NULL;
    1083             :         struct llinfo_nd6 *ln = NULL;
    1084             :         int is_newentry;
    1085             :         struct sockaddr_dl *sdl = NULL;
    1086             :         int do_update;
    1087             :         int olladdr;
    1088             :         int llchange;
    1089             :         int newstate = 0;
    1090             : 
    1091           0 :         if (!ifp)
    1092           0 :                 panic("ifp == NULL in nd6_cache_lladdr");
    1093           0 :         if (!from)
    1094           0 :                 panic("from == NULL in nd6_cache_lladdr");
    1095             : 
    1096             :         /* nothing must be updated for unspecified address */
    1097           0 :         if (IN6_IS_ADDR_UNSPECIFIED(from))
    1098           0 :                 return;
    1099             : 
    1100             :         /*
    1101             :          * Validation about ifp->if_addrlen and lladdrlen must be done in
    1102             :          * the caller.
    1103             :          *
    1104             :          * XXX If the link does not have link-layer address, what should
    1105             :          * we do? (ifp->if_addrlen == 0)
    1106             :          * Spec says nothing in sections for RA, RS and NA.  There's small
    1107             :          * description on it in NS section (RFC 2461 7.2.3).
    1108             :          */
    1109             : 
    1110           0 :         rt = nd6_lookup(from, 0, ifp, ifp->if_rdomain);
    1111           0 :         if (rt == NULL) {
    1112             : #if 0
    1113             :                 /* nothing must be done if there's no lladdr */
    1114             :                 if (!lladdr || !lladdrlen)
    1115             :                         return NULL;
    1116             : #endif
    1117             : 
    1118           0 :                 rt = nd6_lookup(from, 1, ifp, ifp->if_rdomain);
    1119             :                 is_newentry = 1;
    1120           0 :         } else {
    1121             :                 /* do nothing if static ndp is set */
    1122           0 :                 if (rt->rt_flags & RTF_STATIC) {
    1123           0 :                         rtfree(rt);
    1124           0 :                         return;
    1125             :                 }
    1126             :                 is_newentry = 0;
    1127             :         }
    1128             : 
    1129           0 :         if (!rt)
    1130           0 :                 return;
    1131           0 :         if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
    1132             : fail:
    1133           0 :                 nd6_free(rt);
    1134           0 :                 rtfree(rt);
    1135           0 :                 return;
    1136             :         }
    1137           0 :         ln = (struct llinfo_nd6 *)rt->rt_llinfo;
    1138           0 :         if (ln == NULL)
    1139             :                 goto fail;
    1140           0 :         if (rt->rt_gateway == NULL)
    1141             :                 goto fail;
    1142           0 :         if (rt->rt_gateway->sa_family != AF_LINK)
    1143             :                 goto fail;
    1144           0 :         sdl = satosdl(rt->rt_gateway);
    1145             : 
    1146           0 :         olladdr = (sdl->sdl_alen) ? 1 : 0;
    1147           0 :         if (olladdr && lladdr) {
    1148           0 :                 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
    1149           0 :                         llchange = 1;
    1150             :                 else
    1151             :                         llchange = 0;
    1152             :         } else
    1153             :                 llchange = 0;
    1154             : 
    1155             :         /*
    1156             :          * newentry olladdr  lladdr  llchange   (*=record)
    1157             :          *      0       n       n       --      (1)
    1158             :          *      0       y       n       --      (2)
    1159             :          *      0       n       y       --      (3) * STALE
    1160             :          *      0       y       y       n       (4) *
    1161             :          *      0       y       y       y       (5) * STALE
    1162             :          *      1       --      n       --      (6)   NOSTATE(= PASSIVE)
    1163             :          *      1       --      y       --      (7) * STALE
    1164             :          */
    1165             : 
    1166           0 :         if (llchange) {
    1167           0 :                 char addr[INET6_ADDRSTRLEN];
    1168           0 :                 log(LOG_INFO, "ndp info overwritten for %s by %s on %s\n",
    1169           0 :                     inet_ntop(AF_INET6, from, addr, sizeof(addr)),
    1170           0 :                     ether_sprintf(lladdr), ifp->if_xname);
    1171           0 :         }
    1172           0 :         if (lladdr) {           /* (3-5) and (7) */
    1173             :                 /*
    1174             :                  * Record source link-layer address
    1175             :                  * XXX is it dependent to ifp->if_type?
    1176             :                  */
    1177           0 :                 sdl->sdl_alen = ifp->if_addrlen;
    1178           0 :                 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
    1179           0 :         }
    1180             : 
    1181           0 :         if (!is_newentry) {
    1182           0 :                 if ((!olladdr && lladdr) ||             /* (3) */
    1183           0 :                     (olladdr && lladdr && llchange)) {  /* (5) */
    1184             :                         do_update = 1;
    1185             :                         newstate = ND6_LLINFO_STALE;
    1186           0 :                 } else                                  /* (1-2,4) */
    1187             :                         do_update = 0;
    1188             :         } else {
    1189             :                 do_update = 1;
    1190           0 :                 if (!lladdr)                            /* (6) */
    1191           0 :                         newstate = ND6_LLINFO_NOSTATE;
    1192             :                 else                                    /* (7) */
    1193             :                         newstate = ND6_LLINFO_STALE;
    1194             :         }
    1195             : 
    1196           0 :         if (do_update) {
    1197             :                 /*
    1198             :                  * Update the state of the neighbor cache.
    1199             :                  */
    1200           0 :                 ln->ln_state = newstate;
    1201             : 
    1202           0 :                 if (ln->ln_state == ND6_LLINFO_STALE) {
    1203             :                         /*
    1204             :                          * Since nd6_resolve() in ifp->if_output() will cause
    1205             :                          * state transition to DELAY and reset the timer,
    1206             :                          * we must set the timer now, although it is actually
    1207             :                          * meaningless.
    1208             :                          */
    1209           0 :                         nd6_llinfo_settimer(ln, nd6_gctimer);
    1210             : 
    1211           0 :                         if (ln->ln_hold) {
    1212             :                                 struct mbuf *n = ln->ln_hold;
    1213           0 :                                 ln->ln_hold = NULL;
    1214             :                                 /*
    1215             :                                  * we assume ifp is not a p2p here, so just
    1216             :                                  * set the 2nd argument as the 1st one.
    1217             :                                  */
    1218           0 :                                 ifp->if_output(ifp, n, rt_key(rt), rt);
    1219           0 :                                 if (ln->ln_hold == n) {
    1220             :                                         /* n is back in ln_hold. Discard. */
    1221           0 :                                         m_freem(ln->ln_hold);
    1222           0 :                                         ln->ln_hold = NULL;
    1223           0 :                                 }
    1224           0 :                         }
    1225           0 :                 } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
    1226             :                         /* probe right away */
    1227           0 :                         nd6_llinfo_settimer(ln, 0);
    1228           0 :                 }
    1229             :         }
    1230             : 
    1231             :         /*
    1232             :          * ICMP6 type dependent behavior.
    1233             :          *
    1234             :          * NS: clear IsRouter if new entry
    1235             :          * RS: clear IsRouter
    1236             :          * RA: set IsRouter if there's lladdr
    1237             :          * redir: clear IsRouter if new entry
    1238             :          *
    1239             :          * RA case, (1):
    1240             :          * The spec says that we must set IsRouter in the following cases:
    1241             :          * - If lladdr exist, set IsRouter.  This means (1-5).
    1242             :          * - If it is old entry (!newentry), set IsRouter.  This means (7).
    1243             :          * So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
    1244             :          * A question arises for (1) case.  (1) case has no lladdr in the
    1245             :          * neighbor cache, this is similar to (6).
    1246             :          * This case is rare but we figured that we MUST NOT set IsRouter.
    1247             :          *
    1248             :          * newentry olladdr  lladdr  llchange       NS  RS  RA  redir
    1249             :          *                                                      D R
    1250             :          *      0       n       n       --      (1)     c   ?     s
    1251             :          *      0       y       n       --      (2)     c   s     s
    1252             :          *      0       n       y       --      (3)     c   s     s
    1253             :          *      0       y       y       n       (4)     c   s     s
    1254             :          *      0       y       y       y       (5)     c   s     s
    1255             :          *      1       --      n       --      (6) c   c       c s
    1256             :          *      1       --      y       --      (7) c   c   s   c s
    1257             :          *
    1258             :          *                                      (c=clear s=set)
    1259             :          */
    1260           0 :         switch (type & 0xff) {
    1261             :         case ND_NEIGHBOR_SOLICIT:
    1262             :                 /*
    1263             :                  * New entry must have is_router flag cleared.
    1264             :                  */
    1265           0 :                 if (is_newentry)        /* (6-7) */
    1266           0 :                         ln->ln_router = 0;
    1267             :                 break;
    1268             :         case ND_REDIRECT:
    1269             :                 /*
    1270             :                  * If the icmp is a redirect to a better router, always set the
    1271             :                  * is_router flag.  Otherwise, if the entry is newly created,
    1272             :                  * clear the flag.  [RFC 2461, sec 8.3]
    1273             :                  */
    1274           0 :                 if (code == ND_REDIRECT_ROUTER)
    1275           0 :                         ln->ln_router = 1;
    1276           0 :                 else if (is_newentry) /* (6-7) */
    1277           0 :                         ln->ln_router = 0;
    1278             :                 break;
    1279             :         case ND_ROUTER_SOLICIT:
    1280             :                 /*
    1281             :                  * is_router flag must always be cleared.
    1282             :                  */
    1283           0 :                 ln->ln_router = 0;
    1284           0 :                 break;
    1285             :         case ND_ROUTER_ADVERT:
    1286             :                 /*
    1287             :                  * Mark an entry with lladdr as a router.
    1288             :                  */
    1289           0 :                 if ((!is_newentry && (olladdr || lladdr)) ||    /* (2-5) */
    1290           0 :                     (is_newentry && lladdr)) {                  /* (7) */
    1291           0 :                         ln->ln_router = 1;
    1292           0 :                 }
    1293             :                 break;
    1294             :         }
    1295             : 
    1296           0 :         rtfree(rt);
    1297           0 : }
    1298             : 
    1299             : void
    1300           0 : nd6_slowtimo(void *ignored_arg)
    1301             : {
    1302             :         struct nd_ifinfo *nd6if;
    1303             :         struct ifnet *ifp;
    1304             : 
    1305           0 :         NET_LOCK();
    1306             : 
    1307           0 :         timeout_add_sec(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL);
    1308             : 
    1309           0 :         TAILQ_FOREACH(ifp, &ifnet, if_list) {
    1310           0 :                 nd6if = ND_IFINFO(ifp);
    1311           0 :                 if (nd6if->basereachable && /* already initialized */
    1312           0 :                     (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
    1313             :                         /*
    1314             :                          * Since reachable time rarely changes by router
    1315             :                          * advertisements, we SHOULD insure that a new random
    1316             :                          * value gets recomputed at least once every few hours.
    1317             :                          * (RFC 2461, 6.3.4)
    1318             :                          */
    1319           0 :                         nd6if->recalctm = nd6_recalc_reachtm_interval;
    1320           0 :                         nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
    1321           0 :                 }
    1322             :         }
    1323           0 :         NET_UNLOCK();
    1324           0 : }
    1325             : 
    1326             : int
    1327           0 : nd6_resolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
    1328             :     struct sockaddr *dst, u_char *desten)
    1329             : {
    1330             :         struct sockaddr_dl *sdl;
    1331             :         struct rtentry *rt;
    1332             :         struct llinfo_nd6 *ln = NULL;
    1333             : 
    1334           0 :         if (m->m_flags & M_MCAST) {
    1335           0 :                 ETHER_MAP_IPV6_MULTICAST(&satosin6(dst)->sin6_addr, desten);
    1336           0 :                 return (0);
    1337             :         }
    1338             : 
    1339           0 :         rt = rt_getll(rt0);
    1340             : 
    1341           0 :         if (ISSET(rt->rt_flags, RTF_REJECT) &&
    1342           0 :             (rt->rt_expire == 0 || time_uptime < rt->rt_expire)) {
    1343           0 :                 m_freem(m);
    1344           0 :                 return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
    1345             :         }
    1346             : 
    1347             :         /*
    1348             :          * Address resolution or Neighbor Unreachability Detection
    1349             :          * for the next hop.
    1350             :          * At this point, the destination of the packet must be a unicast
    1351             :          * or an anycast address(i.e. not a multicast).
    1352             :          */
    1353           0 :         if (!ISSET(rt->rt_flags, RTF_LLINFO)) {
    1354           0 :                 char addr[INET6_ADDRSTRLEN];
    1355           0 :                 log(LOG_DEBUG, "%s: %s: route contains no ND information\n",
    1356           0 :                     __func__, inet_ntop(AF_INET6,
    1357           0 :                     &satosin6(rt_key(rt))->sin6_addr, addr, sizeof(addr)));
    1358           0 :                 m_freem(m);
    1359             :                 return (EINVAL);
    1360           0 :         }
    1361             : 
    1362           0 :         if (rt->rt_gateway->sa_family != AF_LINK) {
    1363           0 :                 printf("%s: something odd happens\n", __func__);
    1364           0 :                 m_freem(m);
    1365           0 :                 return (EINVAL);
    1366             :         }
    1367             : 
    1368           0 :         ln = (struct llinfo_nd6 *)rt->rt_llinfo;
    1369           0 :         KASSERT(ln != NULL);
    1370             : 
    1371             :         /*
    1372             :          * Move this entry to the head of the queue so that it is less likely
    1373             :          * for this entry to be a target of forced garbage collection (see
    1374             :          * nd6_rtrequest()).
    1375             :          */
    1376           0 :         TAILQ_REMOVE(&nd6_list, ln, ln_list);
    1377           0 :         TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list);
    1378             : 
    1379             :         /*
    1380             :          * The first time we send a packet to a neighbor whose entry is
    1381             :          * STALE, we have to change the state to DELAY and a sets a timer to
    1382             :          * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
    1383             :          * neighbor unreachability detection on expiration.
    1384             :          * (RFC 2461 7.3.3)
    1385             :          */
    1386           0 :         if (ln->ln_state == ND6_LLINFO_STALE) {
    1387           0 :                 ln->ln_asked = 0;
    1388           0 :                 ln->ln_state = ND6_LLINFO_DELAY;
    1389           0 :                 nd6_llinfo_settimer(ln, nd6_delay);
    1390           0 :         }
    1391             : 
    1392             :         /*
    1393             :          * If the neighbor cache entry has a state other than INCOMPLETE
    1394             :          * (i.e. its link-layer address is already resolved), just
    1395             :          * send the packet.
    1396             :          */
    1397           0 :         if (ln->ln_state > ND6_LLINFO_INCOMPLETE) {
    1398           0 :                 sdl = satosdl(rt->rt_gateway);
    1399           0 :                 if (sdl->sdl_alen != ETHER_ADDR_LEN) {
    1400           0 :                         char addr[INET6_ADDRSTRLEN];
    1401           0 :                         log(LOG_DEBUG, "%s: %s: incorrect nd6 information\n",
    1402             :                             __func__,
    1403           0 :                             inet_ntop(AF_INET6, &satosin6(dst)->sin6_addr,
    1404           0 :                                 addr, sizeof(addr)));
    1405           0 :                         m_freem(m);
    1406             :                         return (EINVAL);
    1407           0 :                 }
    1408             : 
    1409           0 :                 bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
    1410           0 :                 return (0);
    1411             :         }
    1412             : 
    1413             :         /*
    1414             :          * There is a neighbor cache entry, but no ethernet address
    1415             :          * response yet.  Replace the held mbuf (if any) with this
    1416             :          * latest one.
    1417             :          */
    1418           0 :         if (ln->ln_state == ND6_LLINFO_NOSTATE)
    1419           0 :                 ln->ln_state = ND6_LLINFO_INCOMPLETE;
    1420           0 :         m_freem(ln->ln_hold);
    1421           0 :         ln->ln_hold = m;
    1422             : 
    1423             :         /*
    1424             :          * If there has been no NS for the neighbor after entering the
    1425             :          * INCOMPLETE state, send the first solicitation.
    1426             :          */
    1427           0 :         if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
    1428           0 :                 ln->ln_asked++;
    1429           0 :                 nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans / 1000);
    1430           0 :                 nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, ln, 0);
    1431           0 :         }
    1432           0 :         return (EAGAIN);
    1433           0 : }
    1434             : 
    1435             : int
    1436           0 : nd6_need_cache(struct ifnet *ifp)
    1437             : {
    1438             :         /*
    1439             :          * RFC2893 says:
    1440             :          * - unidirectional tunnels needs no ND
    1441             :          */
    1442           0 :         switch (ifp->if_type) {
    1443             :         case IFT_ETHER:
    1444             :         case IFT_IEEE80211:
    1445             :         case IFT_CARP:
    1446           0 :                 return (1);
    1447             :         default:
    1448           0 :                 return (0);
    1449             :         }
    1450           0 : }

Generated by: LCOV version 1.13