Annotation of src/sys/netinet6/nd6.c, Revision 1.130
1.130 ! dyoung 1: /* $NetBSD: nd6.c,v 1.129 2008/10/24 16:54:18 dyoung Exp $ */
1.65 itojun 2: /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
1.4 thorpej 3:
1.2 itojun 4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
1.25 itojun 7: *
1.2 itojun 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.
1.25 itojun 19: *
1.2 itojun 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:
1.55 lukem 33: #include <sys/cdefs.h>
1.130 ! dyoung 34: __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.129 2008/10/24 16:54:18 dyoung Exp $");
1.87 itojun 35:
36: #include "opt_ipsec.h"
1.2 itojun 37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
1.20 thorpej 40: #include <sys/callout.h>
1.2 itojun 41: #include <sys/malloc.h>
42: #include <sys/mbuf.h>
43: #include <sys/socket.h>
1.126 ad 44: #include <sys/socketvar.h>
1.2 itojun 45: #include <sys/sockio.h>
46: #include <sys/time.h>
47: #include <sys/kernel.h>
1.18 itojun 48: #include <sys/protosw.h>
1.2 itojun 49: #include <sys/errno.h>
50: #include <sys/ioctl.h>
51: #include <sys/syslog.h>
52: #include <sys/queue.h>
53:
54: #include <net/if.h>
55: #include <net/if_dl.h>
56: #include <net/if_types.h>
57: #include <net/route.h>
1.62 itojun 58: #include <net/if_ether.h>
59: #include <net/if_fddi.h>
60: #include <net/if_arc.h>
1.2 itojun 61:
62: #include <netinet/in.h>
63: #include <netinet6/in6_var.h>
1.17 itojun 64: #include <netinet/ip6.h>
1.2 itojun 65: #include <netinet6/ip6_var.h>
1.96 rpaulo 66: #include <netinet6/scope6_var.h>
1.2 itojun 67: #include <netinet6/nd6.h>
1.17 itojun 68: #include <netinet/icmp6.h>
1.125 thorpej 69: #include <netinet6/icmp6_private.h>
1.87 itojun 70:
71: #ifdef IPSEC
72: #include <netinet6/ipsec.h>
73: #endif
1.2 itojun 74:
1.12 itojun 75: #include <net/net_osdep.h>
76:
1.2 itojun 77: #define ND6_SLOWTIMER_INTERVAL (60 * 60) /* 1 hour */
78: #define ND6_RECALC_REACHTM_INTERVAL (60 * 120) /* 2 hours */
79:
80: /* timer values */
81: int nd6_prune = 1; /* walk list every 1 seconds */
82: int nd6_delay = 5; /* delay first probe time 5 second */
83: int nd6_umaxtries = 3; /* maximum unicast query */
84: int nd6_mmaxtries = 3; /* maximum multicast query */
85: int nd6_useloopback = 1; /* use loopback interface for local traffic */
1.42 itojun 86: int nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */
1.2 itojun 87:
1.12 itojun 88: /* preventing too many loops in ND option parsing */
89: int nd6_maxndopt = 10; /* max # of ND options allowed */
90:
1.31 itojun 91: int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */
92:
1.99 rpaulo 93: int nd6_maxqueuelen = 1; /* max # of packets cached in unresolved ND entries */
94:
1.36 itojun 95: #ifdef ND6_DEBUG
96: int nd6_debug = 1;
97: #else
98: int nd6_debug = 0;
99: #endif
100:
1.2 itojun 101: /* for debugging? */
102: static int nd6_inuse, nd6_allocated;
103:
1.104 christos 104: struct llinfo_nd6 llinfo_nd6 = {
105: .ln_prev = &llinfo_nd6,
106: .ln_next = &llinfo_nd6,
107: };
1.12 itojun 108: struct nd_drhead nd_defrouter;
1.2 itojun 109: struct nd_prhead nd_prefix = { 0 };
110:
111: int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
1.122 dyoung 112: static const struct sockaddr_in6 all1_sa = {
113: .sin6_family = AF_INET6
114: , .sin6_len = sizeof(struct sockaddr_in6)
115: , .sin6_addr = {.s6_addr = {0xff, 0xff, 0xff, 0xff,
116: 0xff, 0xff, 0xff, 0xff,
117: 0xff, 0xff, 0xff, 0xff,
118: 0xff, 0xff, 0xff, 0xff}}
119: };
1.2 itojun 120:
1.121 dyoung 121: static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
122: static void nd6_slowtimo(void *);
123: static int regen_tmpaddr(struct in6_ifaddr *);
124: static struct llinfo_nd6 *nd6_free(struct rtentry *, int);
125: static void nd6_llinfo_timer(void *);
126: static void clear_llinfo_pqueue(struct llinfo_nd6 *);
1.2 itojun 127:
1.116 ad 128: callout_t nd6_slowtimo_ch;
129: callout_t nd6_timer_ch;
130: extern callout_t in6_tmpaddrtimer_ch;
1.20 thorpej 131:
1.121 dyoung 132: static int fill_drlist(void *, size_t *, size_t);
133: static int fill_prlist(void *, size_t *, size_t);
1.79 thorpej 134:
135: MALLOC_DEFINE(M_IP6NDP, "NDP", "IPv6 Neighbour Discovery");
1.65 itojun 136:
1.2 itojun 137: void
1.112 dyoung 138: nd6_init(void)
1.2 itojun 139: {
140: static int nd6_init_done = 0;
141:
142: if (nd6_init_done) {
143: log(LOG_NOTICE, "nd6_init called more than once(ignored)\n");
144: return;
145: }
1.12 itojun 146:
147: /* initialization of the default router list */
148: TAILQ_INIT(&nd_defrouter);
149:
1.2 itojun 150: nd6_init_done = 1;
151:
1.126 ad 152: callout_init(&nd6_slowtimo_ch, CALLOUT_MPSAFE);
153: callout_init(&nd6_timer_ch, CALLOUT_MPSAFE);
1.116 ad 154:
1.2 itojun 155: /* start timer */
1.20 thorpej 156: callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
157: nd6_slowtimo, NULL);
1.2 itojun 158: }
159:
1.58 itojun 160: struct nd_ifinfo *
1.112 dyoung 161: nd6_ifattach(struct ifnet *ifp)
1.2 itojun 162: {
1.58 itojun 163: struct nd_ifinfo *nd;
1.2 itojun 164:
1.58 itojun 165: nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
1.129 dyoung 166: memset(nd, 0, sizeof(*nd));
1.2 itojun 167:
1.58 itojun 168: nd->initialized = 1;
1.2 itojun 169:
1.58 itojun 170: nd->chlim = IPV6_DEFHLIM;
171: nd->basereachable = REACHABLE_TIME;
172: nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
173: nd->retrans = RETRANS_TIMER;
1.65 itojun 174: /*
175: * Note that the default value of ip6_accept_rtadv is 0, which means
176: * we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV
177: * here.
178: */
179: nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
1.61 itojun 180:
181: /* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
182: nd6_setmtu0(ifp, nd);
1.2 itojun 183:
1.58 itojun 184: return nd;
185: }
1.21 itojun 186:
1.58 itojun 187: void
1.112 dyoung 188: nd6_ifdetach(struct nd_ifinfo *nd)
1.58 itojun 189: {
1.21 itojun 190:
1.58 itojun 191: free(nd, M_IP6NDP);
1.2 itojun 192: }
193:
194: void
1.112 dyoung 195: nd6_setmtu(struct ifnet *ifp)
1.61 itojun 196: {
197: nd6_setmtu0(ifp, ND_IFINFO(ifp));
198: }
199:
200: void
1.112 dyoung 201: nd6_setmtu0(struct ifnet *ifp, struct nd_ifinfo *ndi)
1.2 itojun 202: {
1.61 itojun 203: u_int32_t omaxmtu;
204:
205: omaxmtu = ndi->maxmtu;
1.2 itojun 206:
1.40 itojun 207: switch (ifp->if_type) {
1.62 itojun 208: case IFT_ARCNET:
209: ndi->maxmtu = MIN(ARC_PHDS_MAXMTU, ifp->if_mtu); /* RFC2497 */
1.39 itojun 210: break;
1.58 itojun 211: case IFT_FDDI:
212: ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);
213: break;
1.39 itojun 214: default:
215: ndi->maxmtu = ifp->if_mtu;
216: break;
1.2 itojun 217: }
218:
1.61 itojun 219: /*
220: * Decreasing the interface MTU under IPV6 minimum MTU may cause
221: * undesirable situation. We thus notify the operator of the change
222: * explicitly. The check for omaxmtu is necessary to restrict the
1.63 itojun 223: * log to the case of changing the MTU, not initializing it.
1.61 itojun 224: */
225: if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) {
1.81 christos 226: log(LOG_NOTICE, "nd6_setmtu0: new link MTU on %s (%lu) is too"
227: " small for IPv6 which needs %lu\n",
228: if_name(ifp), (unsigned long)ndi->maxmtu, (unsigned long)
229: IPV6_MMTU);
1.2 itojun 230: }
1.58 itojun 231:
232: if (ndi->maxmtu > in6_maxmtu)
233: in6_setmaxmtu(); /* check all interfaces just in case */
1.2 itojun 234: }
235:
236: void
1.112 dyoung 237: nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
1.2 itojun 238: {
1.58 itojun 239:
1.129 dyoung 240: memset(ndopts, 0, sizeof(*ndopts));
1.2 itojun 241: ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
242: ndopts->nd_opts_last
243: = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
244:
245: if (icmp6len == 0) {
246: ndopts->nd_opts_done = 1;
247: ndopts->nd_opts_search = NULL;
248: }
249: }
250:
251: /*
252: * Take one ND option.
253: */
254: struct nd_opt_hdr *
1.112 dyoung 255: nd6_option(union nd_opts *ndopts)
1.2 itojun 256: {
257: struct nd_opt_hdr *nd_opt;
258: int olen;
259:
1.99 rpaulo 260: if (ndopts == NULL)
1.76 provos 261: panic("ndopts == NULL in nd6_option");
1.99 rpaulo 262: if (ndopts->nd_opts_last == NULL)
1.76 provos 263: panic("uninitialized ndopts in nd6_option");
1.99 rpaulo 264: if (ndopts->nd_opts_search == NULL)
1.2 itojun 265: return NULL;
266: if (ndopts->nd_opts_done)
267: return NULL;
268:
269: nd_opt = ndopts->nd_opts_search;
270:
1.40 itojun 271: /* make sure nd_opt_len is inside the buffer */
1.111 christos 272: if ((void *)&nd_opt->nd_opt_len >= (void *)ndopts->nd_opts_last) {
1.129 dyoung 273: memset(ndopts, 0, sizeof(*ndopts));
1.40 itojun 274: return NULL;
275: }
276:
1.2 itojun 277: olen = nd_opt->nd_opt_len << 3;
278: if (olen == 0) {
279: /*
280: * Message validation requires that all included
281: * options have a length that is greater than zero.
282: */
1.129 dyoung 283: memset(ndopts, 0, sizeof(*ndopts));
1.2 itojun 284: return NULL;
285: }
286:
1.111 christos 287: ndopts->nd_opts_search = (struct nd_opt_hdr *)((char *)nd_opt + olen);
1.40 itojun 288: if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
289: /* option overruns the end of buffer, invalid */
1.129 dyoung 290: memset(ndopts, 0, sizeof(*ndopts));
1.40 itojun 291: return NULL;
292: } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
293: /* reached the end of options chain */
1.2 itojun 294: ndopts->nd_opts_done = 1;
295: ndopts->nd_opts_search = NULL;
296: }
297: return nd_opt;
298: }
299:
300: /*
301: * Parse multiple ND options.
302: * This function is much easier to use, for ND routines that do not need
303: * multiple options of the same type.
304: */
305: int
1.112 dyoung 306: nd6_options(union nd_opts *ndopts)
1.2 itojun 307: {
308: struct nd_opt_hdr *nd_opt;
309: int i = 0;
310:
1.99 rpaulo 311: if (ndopts == NULL)
1.76 provos 312: panic("ndopts == NULL in nd6_options");
1.99 rpaulo 313: if (ndopts->nd_opts_last == NULL)
1.76 provos 314: panic("uninitialized ndopts in nd6_options");
1.99 rpaulo 315: if (ndopts->nd_opts_search == NULL)
1.2 itojun 316: return 0;
1.99 rpaulo 317:
1.2 itojun 318: while (1) {
319: nd_opt = nd6_option(ndopts);
1.99 rpaulo 320: if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
1.2 itojun 321: /*
322: * Message validation requires that all included
323: * options have a length that is greater than zero.
324: */
1.125 thorpej 325: ICMP6_STATINC(ICMP6_STAT_ND_BADOPT);
1.129 dyoung 326: memset(ndopts, 0, sizeof(*ndopts));
1.2 itojun 327: return -1;
328: }
329:
1.99 rpaulo 330: if (nd_opt == NULL)
1.2 itojun 331: goto skip1;
332:
333: switch (nd_opt->nd_opt_type) {
334: case ND_OPT_SOURCE_LINKADDR:
335: case ND_OPT_TARGET_LINKADDR:
336: case ND_OPT_MTU:
337: case ND_OPT_REDIRECTED_HEADER:
338: if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
1.36 itojun 339: nd6log((LOG_INFO,
340: "duplicated ND6 option found (type=%d)\n",
341: nd_opt->nd_opt_type));
1.2 itojun 342: /* XXX bark? */
343: } else {
344: ndopts->nd_opt_array[nd_opt->nd_opt_type]
345: = nd_opt;
346: }
347: break;
348: case ND_OPT_PREFIX_INFORMATION:
349: if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
350: ndopts->nd_opt_array[nd_opt->nd_opt_type]
351: = nd_opt;
352: }
353: ndopts->nd_opts_pi_end =
354: (struct nd_opt_prefix_info *)nd_opt;
355: break;
356: default:
357: /*
358: * Unknown options must be silently ignored,
1.109 christos 359: * to accommodate future extension to the protocol.
1.2 itojun 360: */
1.36 itojun 361: nd6log((LOG_DEBUG,
1.2 itojun 362: "nd6_options: unsupported option %d - "
1.36 itojun 363: "option ignored\n", nd_opt->nd_opt_type));
1.2 itojun 364: }
365:
366: skip1:
367: i++;
1.12 itojun 368: if (i > nd6_maxndopt) {
1.125 thorpej 369: ICMP6_STATINC(ICMP6_STAT_ND_TOOMANYOPT);
1.36 itojun 370: nd6log((LOG_INFO, "too many loop in nd opt\n"));
1.2 itojun 371: break;
372: }
373:
374: if (ndopts->nd_opts_done)
375: break;
376: }
377:
378: return 0;
379: }
380:
381: /*
1.86 itojun 382: * ND6 timer routine to handle ND6 entries
1.2 itojun 383: */
384: void
1.112 dyoung 385: nd6_llinfo_settimer(struct llinfo_nd6 *ln, long xtick)
1.86 itojun 386: {
387: int s;
388:
389: s = splsoftnet();
390:
1.94 christos 391: if (xtick < 0) {
1.86 itojun 392: ln->ln_expire = 0;
393: ln->ln_ntick = 0;
394: callout_stop(&ln->ln_timer_ch);
395: } else {
1.103 kardel 396: ln->ln_expire = time_second + xtick / hz;
1.94 christos 397: if (xtick > INT_MAX) {
398: ln->ln_ntick = xtick - INT_MAX;
1.86 itojun 399: callout_reset(&ln->ln_timer_ch, INT_MAX,
400: nd6_llinfo_timer, ln);
401: } else {
402: ln->ln_ntick = 0;
1.94 christos 403: callout_reset(&ln->ln_timer_ch, xtick,
1.86 itojun 404: nd6_llinfo_timer, ln);
405: }
406: }
407:
408: splx(s);
409: }
410:
411: static void
1.112 dyoung 412: nd6_llinfo_timer(void *arg)
1.2 itojun 413: {
1.38 itojun 414: struct llinfo_nd6 *ln;
1.86 itojun 415: struct rtentry *rt;
416: const struct sockaddr_in6 *dst;
1.65 itojun 417: struct ifnet *ifp;
1.86 itojun 418: struct nd_ifinfo *ndi = NULL;
1.63 itojun 419:
1.126 ad 420: mutex_enter(softnet_lock);
421: KERNEL_LOCK(1, NULL);
1.2 itojun 422:
1.86 itojun 423: ln = (struct llinfo_nd6 *)arg;
424:
425: if (ln->ln_ntick > 0) {
1.97 dyoung 426: nd6_llinfo_settimer(ln, ln->ln_ntick);
1.126 ad 427: KERNEL_UNLOCK_ONE(NULL);
428: mutex_exit(softnet_lock);
1.86 itojun 429: return;
430: }
431:
432: if ((rt = ln->ln_rt) == NULL)
433: panic("ln->ln_rt == NULL");
434: if ((ifp = rt->rt_ifp) == NULL)
435: panic("ln->ln_rt->rt_ifp == NULL");
436: ndi = ND_IFINFO(ifp);
1.117 dyoung 437: dst = satocsin6(rt_getkey(rt));
1.86 itojun 438:
439: /* sanity check */
440: if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
441: panic("rt_llinfo(%p) is not equal to ln(%p)",
442: rt->rt_llinfo, ln);
443: if (!dst)
444: panic("dst=0 in nd6_timer(ln=%p)", ln);
445:
446: switch (ln->ln_state) {
447: case ND6_LLINFO_INCOMPLETE:
448: if (ln->ln_asked < nd6_mmaxtries) {
449: ln->ln_asked++;
450: nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
451: nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
452: } else {
453: struct mbuf *m = ln->ln_hold;
454: if (m) {
1.100 rpaulo 455: struct mbuf *m0;
456:
1.86 itojun 457: /*
1.96 rpaulo 458: * assuming every packet in ln_hold has
459: * the same IP header
1.86 itojun 460: */
1.100 rpaulo 461: m0 = m->m_nextpkt;
462: m->m_nextpkt = NULL;
1.96 rpaulo 463: icmp6_error2(m, ICMP6_DST_UNREACH,
464: ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp);
1.100 rpaulo 465:
466: ln->ln_hold = m0;
467: clear_llinfo_pqueue(ln);
468: }
1.86 itojun 469: (void)nd6_free(rt, 0);
470: ln = NULL;
1.2 itojun 471: }
1.86 itojun 472: break;
473: case ND6_LLINFO_REACHABLE:
474: if (!ND6_LLINFO_PERMANENT(ln)) {
475: ln->ln_state = ND6_LLINFO_STALE;
476: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.2 itojun 477: }
1.86 itojun 478: break;
1.2 itojun 479:
1.86 itojun 480: case ND6_LLINFO_STALE:
481: /* Garbage Collection(RFC 2461 5.3) */
482: if (!ND6_LLINFO_PERMANENT(ln)) {
483: (void)nd6_free(rt, 1);
484: ln = NULL;
1.2 itojun 485: }
1.86 itojun 486: break;
1.54 itojun 487:
1.86 itojun 488: case ND6_LLINFO_DELAY:
489: if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
490: /* We need NUD */
491: ln->ln_asked = 1;
492: ln->ln_state = ND6_LLINFO_PROBE;
493: nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
494: nd6_ns_output(ifp, &dst->sin6_addr,
495: &dst->sin6_addr, ln, 0);
496: } else {
497: ln->ln_state = ND6_LLINFO_STALE; /* XXX */
498: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
499: }
500: break;
501: case ND6_LLINFO_PROBE:
502: if (ln->ln_asked < nd6_umaxtries) {
503: ln->ln_asked++;
504: nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
505: nd6_ns_output(ifp, &dst->sin6_addr,
506: &dst->sin6_addr, ln, 0);
507: } else {
508: (void)nd6_free(rt, 0);
509: ln = NULL;
510: }
511: break;
512: }
1.65 itojun 513:
1.126 ad 514: KERNEL_UNLOCK_ONE(NULL);
515: mutex_exit(softnet_lock);
1.86 itojun 516: }
1.42 itojun 517:
1.86 itojun 518: /*
519: * ND6 timer routine to expire default route list and prefix list
520: */
521: void
1.107 christos 522: nd6_timer(void *ignored_arg)
1.86 itojun 523: {
1.108 dyoung 524: struct nd_defrouter *next_dr, *dr;
525: struct nd_prefix *next_pr, *pr;
1.86 itojun 526: struct in6_ifaddr *ia6, *nia6;
1.99 rpaulo 527: struct in6_addrlifetime *lt6;
1.42 itojun 528:
1.86 itojun 529: callout_reset(&nd6_timer_ch, nd6_prune * hz,
530: nd6_timer, NULL);
1.63 itojun 531:
1.126 ad 532: mutex_enter(softnet_lock);
533: KERNEL_LOCK(1, NULL);
534:
1.43 itojun 535: /* expire default router list */
1.108 dyoung 536:
537: for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = next_dr) {
538: next_dr = TAILQ_NEXT(dr, dr_entry);
1.103 kardel 539: if (dr->expire && dr->expire < time_second) {
1.2 itojun 540: defrtrlist_del(dr);
1.31 itojun 541: }
1.2 itojun 542: }
543:
1.65 itojun 544: /*
545: * expire interface addresses.
546: * in the past the loop was inside prefix expiry processing.
547: * However, from a stricter speci-confrmance standpoint, we should
548: * rather separate address lifetimes and prefix lifetimes.
549: */
1.99 rpaulo 550: addrloop:
1.65 itojun 551: for (ia6 = in6_ifaddr; ia6; ia6 = nia6) {
552: nia6 = ia6->ia_next;
553: /* check address lifetime */
1.99 rpaulo 554: lt6 = &ia6->ia6_lifetime;
1.65 itojun 555: if (IFA6_IS_INVALID(ia6)) {
1.99 rpaulo 556: int regen = 0;
557:
558: /*
559: * If the expiring address is temporary, try
560: * regenerating a new one. This would be useful when
561: * we suspended a laptop PC, then turned it on after a
562: * period that could invalidate all temporary
563: * addresses. Although we may have to restart the
564: * loop (see below), it must be after purging the
565: * address. Otherwise, we'd see an infinite loop of
566: * regeneration.
567: */
568: if (ip6_use_tempaddr &&
569: (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
570: if (regen_tmpaddr(ia6) == 0)
571: regen = 1;
572: }
573:
574: in6_purgeaddr(&ia6->ia_ifa);
575:
576: if (regen)
577: goto addrloop; /* XXX: see below */
578: } else if (IFA6_IS_DEPRECATED(ia6)) {
579: int oldflags = ia6->ia6_flags;
580:
581: ia6->ia6_flags |= IN6_IFF_DEPRECATED;
582:
583: /*
584: * If a temporary address has just become deprecated,
585: * regenerate a new one if possible.
586: */
587: if (ip6_use_tempaddr &&
588: (ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
589: (oldflags & IN6_IFF_DEPRECATED) == 0) {
590:
591: if (regen_tmpaddr(ia6) == 0) {
592: /*
593: * A new temporary address is
594: * generated.
595: * XXX: this means the address chain
596: * has changed while we are still in
597: * the loop. Although the change
598: * would not cause disaster (because
599: * it's not a deletion, but an
600: * addition,) we'd rather restart the
601: * loop just for safety. Or does this
602: * significantly reduce performance??
603: */
604: goto addrloop;
605: }
606: }
1.65 itojun 607: } else {
608: /*
609: * A new RA might have made a deprecated address
610: * preferred.
611: */
612: ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
1.2 itojun 613: }
1.65 itojun 614: }
1.2 itojun 615:
1.65 itojun 616: /* expire prefix list */
1.108 dyoung 617: for (pr = LIST_FIRST(&nd_prefix); pr != NULL; pr = next_pr) {
618: next_pr = LIST_NEXT(pr, ndpr_entry);
1.2 itojun 619: /*
620: * check prefix lifetime.
621: * since pltime is just for autoconf, pltime processing for
622: * prefix is not necessary.
623: */
1.65 itojun 624: if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
1.103 kardel 625: time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
1.2 itojun 626:
627: /*
628: * address expiration and prefix expiration are
1.65 itojun 629: * separate. NEVER perform in6_purgeaddr here.
1.2 itojun 630: */
631:
632: prelist_remove(pr);
1.108 dyoung 633: }
1.2 itojun 634: }
1.126 ad 635:
636: KERNEL_UNLOCK_ONE(NULL);
637: mutex_exit(softnet_lock);
1.16 itojun 638: }
639:
1.112 dyoung 640: /* ia6: deprecated/invalidated temporary address */
1.99 rpaulo 641: static int
1.112 dyoung 642: regen_tmpaddr(struct in6_ifaddr *ia6)
1.99 rpaulo 643: {
644: struct ifaddr *ifa;
645: struct ifnet *ifp;
646: struct in6_ifaddr *public_ifa6 = NULL;
647:
648: ifp = ia6->ia_ifa.ifa_ifp;
1.123 dyoung 649: IFADDR_FOREACH(ifa, ifp) {
1.99 rpaulo 650: struct in6_ifaddr *it6;
651:
652: if (ifa->ifa_addr->sa_family != AF_INET6)
653: continue;
654:
655: it6 = (struct in6_ifaddr *)ifa;
656:
657: /* ignore no autoconf addresses. */
658: if ((it6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
659: continue;
660:
661: /* ignore autoconf addresses with different prefixes. */
662: if (it6->ia6_ndpr == NULL || it6->ia6_ndpr != ia6->ia6_ndpr)
663: continue;
664:
665: /*
666: * Now we are looking at an autoconf address with the same
667: * prefix as ours. If the address is temporary and is still
668: * preferred, do not create another one. It would be rare, but
669: * could happen, for example, when we resume a laptop PC after
670: * a long period.
671: */
672: if ((it6->ia6_flags & IN6_IFF_TEMPORARY) != 0 &&
673: !IFA6_IS_DEPRECATED(it6)) {
674: public_ifa6 = NULL;
675: break;
676: }
677:
678: /*
679: * This is a public autoconf address that has the same prefix
680: * as ours. If it is preferred, keep it. We can't break the
681: * loop here, because there may be a still-preferred temporary
682: * address with the prefix.
683: */
684: if (!IFA6_IS_DEPRECATED(it6))
685: public_ifa6 = it6;
686: }
687:
688: if (public_ifa6 != NULL) {
689: int e;
690:
691: /*
692: * Random factor is introduced in the preferred lifetime, so
693: * we do not need additional delay (3rd arg to in6_tmpifadd).
694: */
695: if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
696: log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
697: " tmp addr, errno=%d\n", e);
1.112 dyoung 698: return -1;
1.99 rpaulo 699: }
1.112 dyoung 700: return 0;
1.99 rpaulo 701: }
702:
1.112 dyoung 703: return -1;
1.99 rpaulo 704: }
705:
1.16 itojun 706: /*
707: * Nuke neighbor cache/prefix/default router management table, right before
708: * ifp goes away.
709: */
710: void
1.112 dyoung 711: nd6_purge(struct ifnet *ifp)
1.16 itojun 712: {
713: struct llinfo_nd6 *ln, *nln;
1.65 itojun 714: struct nd_defrouter *dr, *ndr;
1.16 itojun 715: struct nd_prefix *pr, *npr;
716:
1.65 itojun 717: /*
718: * Nuke default router list entries toward ifp.
719: * We defer removal of default router list entries that is installed
720: * in the routing table, in order to keep additional side effects as
721: * small as possible.
722: */
1.129 dyoung 723: for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = ndr) {
1.65 itojun 724: ndr = TAILQ_NEXT(dr, dr_entry);
725: if (dr->installed)
726: continue;
727:
728: if (dr->ifp == ifp)
729: defrtrlist_del(dr);
730: }
1.129 dyoung 731: for (dr = TAILQ_FIRST(&nd_defrouter); dr != NULL; dr = ndr) {
1.65 itojun 732: ndr = TAILQ_NEXT(dr, dr_entry);
733: if (!dr->installed)
734: continue;
735:
1.16 itojun 736: if (dr->ifp == ifp)
737: defrtrlist_del(dr);
738: }
739:
740: /* Nuke prefix list entries toward ifp */
1.108 dyoung 741: for (pr = LIST_FIRST(&nd_prefix); pr != NULL; pr = npr) {
742: npr = LIST_NEXT(pr, ndpr_entry);
1.16 itojun 743: if (pr->ndpr_ifp == ifp) {
1.65 itojun 744: /*
1.92 tron 745: * Because if_detach() does *not* release prefixes
746: * while purging addresses the reference count will
747: * still be above zero. We therefore reset it to
748: * make sure that the prefix really gets purged.
749: */
750: pr->ndpr_refcnt = 0;
751: /*
1.65 itojun 752: * Previously, pr->ndpr_addr is removed as well,
753: * but I strongly believe we don't have to do it.
754: * nd6_purge() is only called from in6_ifdetach(),
755: * which removes all the associated interface addresses
756: * by itself.
757: * (jinmei@kame.net 20010129)
758: */
1.16 itojun 759: prelist_remove(pr);
760: }
761: }
762:
763: /* cancel default outgoing interface setting */
764: if (nd6_defifindex == ifp->if_index)
765: nd6_setdefaultiface(0);
766:
1.48 itojun 767: if (!ip6_forwarding && ip6_accept_rtadv) { /* XXX: too restrictive? */
768: /* refresh default router list */
769: defrouter_select();
770: }
1.16 itojun 771:
772: /*
773: * Nuke neighbor cache entries for the ifp.
774: * Note that rt->rt_ifp may not be the same as ifp,
775: * due to KAME goto ours hack. See RTM_RESOLVE case in
1.18 itojun 776: * nd6_rtrequest(), and ip6_input().
1.16 itojun 777: */
778: ln = llinfo_nd6.ln_next;
1.129 dyoung 779: while (ln != NULL && ln != &llinfo_nd6) {
1.16 itojun 780: struct rtentry *rt;
1.118 dyoung 781: const struct sockaddr_dl *sdl;
1.16 itojun 782:
783: nln = ln->ln_next;
784: rt = ln->ln_rt;
785: if (rt && rt->rt_gateway &&
786: rt->rt_gateway->sa_family == AF_LINK) {
1.118 dyoung 787: sdl = satocsdl(rt->rt_gateway);
1.16 itojun 788: if (sdl->sdl_index == ifp->if_index)
1.54 itojun 789: nln = nd6_free(rt, 0);
1.16 itojun 790: }
791: ln = nln;
792: }
1.2 itojun 793: }
794:
795: struct rtentry *
1.112 dyoung 796: nd6_lookup(const struct in6_addr *addr6, int create, struct ifnet *ifp)
1.2 itojun 797: {
798: struct rtentry *rt;
799: struct sockaddr_in6 sin6;
800:
1.122 dyoung 801: sockaddr_in6_init(&sin6, addr6, 0, 0, 0);
1.13 itojun 802: rt = rtalloc1((struct sockaddr *)&sin6, create);
1.129 dyoung 803: if (rt != NULL && (rt->rt_flags & RTF_LLINFO) == 0) {
1.2 itojun 804: /*
805: * This is the case for the default route.
1.25 itojun 806: * If we want to create a neighbor cache for the address, we
1.2 itojun 807: * should free the route for the destination and allocate an
808: * interface route.
809: */
810: if (create) {
811: RTFREE(rt);
1.99 rpaulo 812: rt = NULL;
1.2 itojun 813: }
814: }
1.112 dyoung 815: if (rt != NULL)
816: ;
817: else if (create && ifp) {
818: int e;
1.25 itojun 819:
1.112 dyoung 820: /*
821: * If no route is available and create is set,
822: * we allocate a host route for the destination
823: * and treat it like an interface route.
824: * This hack is necessary for a neighbor which can't
825: * be covered by our own prefix.
826: */
827: struct ifaddr *ifa =
828: ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp);
829: if (ifa == NULL)
830: return NULL;
1.2 itojun 831:
1.112 dyoung 832: /*
833: * Create a new route. RTF_LLINFO is necessary
834: * to create a Neighbor Cache entry for the
835: * destination in nd6_rtrequest which will be
836: * called in rtrequest via ifa->ifa_rtrequest.
837: */
1.122 dyoung 838: if ((e = rtrequest(RTM_ADD, (const struct sockaddr *)&sin6,
839: ifa->ifa_addr, (const struct sockaddr *)&all1_sa,
1.112 dyoung 840: (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
841: ~RTF_CLONING, &rt)) != 0) {
1.54 itojun 842: #if 0
1.112 dyoung 843: log(LOG_ERR,
844: "nd6_lookup: failed to add route for a "
845: "neighbor(%s), errno=%d\n",
846: ip6_sprintf(addr6), e);
1.54 itojun 847: #endif
1.112 dyoung 848: return NULL;
849: }
850: if (rt == NULL)
851: return NULL;
852: if (rt->rt_llinfo) {
853: struct llinfo_nd6 *ln =
854: (struct llinfo_nd6 *)rt->rt_llinfo;
855: ln->ln_state = ND6_LLINFO_NOSTATE;
856: }
857: } else
858: return NULL;
1.2 itojun 859: rt->rt_refcnt--;
1.12 itojun 860: /*
861: * Validation for the entry.
1.65 itojun 862: * Note that the check for rt_llinfo is necessary because a cloned
863: * route from a parent route that has the L flag (e.g. the default
864: * route to a p2p interface) may have the flag, too, while the
865: * destination is not actually a neighbor.
1.12 itojun 866: * XXX: we can't use rt->rt_ifp to check for the interface, since
867: * it might be the loopback interface if the entry is for our
868: * own address on a non-loopback interface. Instead, we should
1.65 itojun 869: * use rt->rt_ifa->ifa_ifp, which would specify the REAL
870: * interface.
1.99 rpaulo 871: * Note also that ifa_ifp and ifp may differ when we connect two
872: * interfaces to a same link, install a link prefix to an interface,
873: * and try to install a neighbor cache on an interface that does not
874: * have a route to the prefix.
1.12 itojun 875: */
1.2 itojun 876: if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
1.65 itojun 877: rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
1.12 itojun 878: (ifp && rt->rt_ifa->ifa_ifp != ifp)) {
1.2 itojun 879: if (create) {
1.77 itojun 880: nd6log((LOG_DEBUG,
1.65 itojun 881: "nd6_lookup: failed to lookup %s (if = %s)\n",
882: ip6_sprintf(addr6),
1.77 itojun 883: ifp ? if_name(ifp) : "unspec"));
1.2 itojun 884: }
1.112 dyoung 885: return NULL;
1.2 itojun 886: }
1.112 dyoung 887: return rt;
1.6 itojun 888: }
889:
890: /*
891: * Detect if a given IPv6 address identifies a neighbor on a given link.
1.25 itojun 892: * XXX: should take care of the destination of a p2p link?
1.6 itojun 893: */
894: int
1.110 dyoung 895: nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
1.6 itojun 896: {
1.65 itojun 897: struct nd_prefix *pr;
1.6 itojun 898:
1.29 itojun 899: /*
900: * A link-local address is always a neighbor.
1.52 itojun 901: * XXX: a link does not necessarily specify a single interface.
1.29 itojun 902: */
1.96 rpaulo 903: if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
904: struct sockaddr_in6 sin6_copy;
905: u_int32_t zone;
906:
907: /*
908: * We need sin6_copy since sa6_recoverscope() may modify the
909: * content (XXX).
910: */
911: sin6_copy = *addr;
912: if (sa6_recoverscope(&sin6_copy))
1.112 dyoung 913: return 0; /* XXX: should be impossible */
1.96 rpaulo 914: if (in6_setscope(&sin6_copy.sin6_addr, ifp, &zone))
1.112 dyoung 915: return 0;
1.96 rpaulo 916: if (sin6_copy.sin6_scope_id == zone)
1.112 dyoung 917: return 1;
1.96 rpaulo 918: else
1.112 dyoung 919: return 0;
1.96 rpaulo 920: }
1.6 itojun 921:
922: /*
1.65 itojun 923: * If the address matches one of our on-link prefixes, it should be a
924: * neighbor.
1.6 itojun 925: */
1.108 dyoung 926: LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.65 itojun 927: if (pr->ndpr_ifp != ifp)
928: continue;
929:
930: if (!(pr->ndpr_stateflags & NDPRF_ONLINK))
931: continue;
932:
933: if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
934: &addr->sin6_addr, &pr->ndpr_mask))
1.112 dyoung 935: return 1;
1.65 itojun 936: }
1.6 itojun 937:
1.65 itojun 938: /*
939: * If the default router list is empty, all addresses are regarded
940: * as on-link, and thus, as a neighbor.
941: * XXX: we restrict the condition to hosts, because routers usually do
942: * not have the "default router list".
943: */
944: if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL &&
945: nd6_defifindex == ifp->if_index) {
1.112 dyoung 946: return 1;
1.6 itojun 947: }
948:
949: /*
950: * Even if the address matches none of our addresses, it might be
951: * in the neighbor cache.
952: */
1.88 simonb 953: if (nd6_lookup(&addr->sin6_addr, 0, ifp) != NULL)
1.112 dyoung 954: return 1;
1.6 itojun 955:
1.112 dyoung 956: return 0;
1.2 itojun 957: }
958:
959: /*
960: * Free an nd6 llinfo entry.
1.54 itojun 961: * Since the function would cause significant changes in the kernel, DO NOT
962: * make it global, unless you have a strong reason for the change, and are sure
963: * that the change is safe.
1.2 itojun 964: */
1.54 itojun 965: static struct llinfo_nd6 *
1.112 dyoung 966: nd6_free(struct rtentry *rt, int gc)
1.2 itojun 967: {
1.37 itojun 968: struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
1.117 dyoung 969: struct in6_addr in6 = satocsin6(rt_getkey(rt))->sin6_addr;
1.12 itojun 970: struct nd_defrouter *dr;
1.2 itojun 971:
1.18 itojun 972: /*
1.54 itojun 973: * we used to have pfctlinput(PRC_HOSTDEAD) here.
974: * even though it is not harmful, it was not really necessary.
1.18 itojun 975: */
976:
1.86 itojun 977: /* cancel timer */
978: nd6_llinfo_settimer(ln, -1);
979:
1.85 itojun 980: if (!ip6_forwarding) {
1.2 itojun 981: int s;
1.5 itojun 982: s = splsoftnet();
1.117 dyoung 983: dr = defrouter_lookup(&satocsin6(rt_getkey(rt))->sin6_addr,
1.65 itojun 984: rt->rt_ifp);
1.54 itojun 985:
986: if (dr != NULL && dr->expire &&
987: ln->ln_state == ND6_LLINFO_STALE && gc) {
988: /*
989: * If the reason for the deletion is just garbage
990: * collection, and the neighbor is an active default
991: * router, do not delete it. Instead, reset the GC
992: * timer using the router's lifetime.
993: * Simply deleting the entry would affect default
994: * router selection, which is not necessarily a good
995: * thing, especially when we're using router preference
996: * values.
997: * XXX: the check for ln_state would be redundant,
998: * but we intentionally keep it just in case.
999: */
1.103 kardel 1000: if (dr->expire > time_second)
1.86 itojun 1001: nd6_llinfo_settimer(ln,
1.103 kardel 1002: (dr->expire - time_second) * hz);
1.86 itojun 1003: else
1004: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.54 itojun 1005: splx(s);
1.112 dyoung 1006: return ln->ln_next;
1.54 itojun 1007: }
1008:
1.12 itojun 1009: if (ln->ln_router || dr) {
1010: /*
1011: * rt6_flush must be called whether or not the neighbor
1012: * is in the Default Router List.
1013: * See a corresponding comment in nd6_na_input().
1014: */
1015: rt6_flush(&in6, rt->rt_ifp);
1016: }
1017:
1018: if (dr) {
1019: /*
1020: * Unreachablity of a router might affect the default
1021: * router selection and on-link detection of advertised
1022: * prefixes.
1023: */
1024:
1.2 itojun 1025: /*
1.12 itojun 1026: * Temporarily fake the state to choose a new default
1027: * router and to perform on-link determination of
1.54 itojun 1028: * prefixes correctly.
1.12 itojun 1029: * Below the state will be set correctly,
1030: * or the entry itself will be deleted.
1.2 itojun 1031: */
1.12 itojun 1032: ln->ln_state = ND6_LLINFO_INCOMPLETE;
1033:
1.54 itojun 1034: /*
1035: * Since defrouter_select() does not affect the
1036: * on-link determination and MIP6 needs the check
1037: * before the default router selection, we perform
1038: * the check now.
1039: */
1040: pfxlist_onlink_check();
1041:
1.65 itojun 1042: /*
1043: * refresh default router list
1044: */
1045: defrouter_select();
1.2 itojun 1046: }
1047: splx(s);
1048: }
1.12 itojun 1049:
1.37 itojun 1050: /*
1051: * Before deleting the entry, remember the next entry as the
1052: * return value. We need this because pfxlist_onlink_check() above
1053: * might have freed other entries (particularly the old next entry) as
1.52 itojun 1054: * a side effect (XXX).
1.37 itojun 1055: */
1056: next = ln->ln_next;
1057:
1058: /*
1059: * Detach the route from the routing tree and the list of neighbor
1060: * caches, and disable the route entry not to be used in already
1061: * cached routes.
1062: */
1.129 dyoung 1063: rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, NULL);
1.37 itojun 1064:
1.112 dyoung 1065: return next;
1.2 itojun 1066: }
1067:
1068: /*
1069: * Upper-layer reachability hint for Neighbor Unreachability Detection.
1070: *
1.98 rpaulo 1071: * XXX cost-effective methods?
1.2 itojun 1072: */
1073: void
1.112 dyoung 1074: nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
1.2 itojun 1075: {
1076: struct llinfo_nd6 *ln;
1077:
1078: /*
1079: * If the caller specified "rt", use that. Otherwise, resolve the
1080: * routing table by supplied "dst6".
1081: */
1.99 rpaulo 1082: if (rt == NULL) {
1083: if (dst6 == NULL)
1.2 itojun 1084: return;
1.99 rpaulo 1085: if ((rt = nd6_lookup(dst6, 0, NULL)) == NULL)
1.2 itojun 1086: return;
1087: }
1088:
1.31 itojun 1089: if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
1090: (rt->rt_flags & RTF_LLINFO) == 0 ||
1091: !rt->rt_llinfo || !rt->rt_gateway ||
1092: rt->rt_gateway->sa_family != AF_LINK) {
1.2 itojun 1093: /* This is not a host route. */
1094: return;
1095: }
1096:
1097: ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1.22 itojun 1098: if (ln->ln_state < ND6_LLINFO_REACHABLE)
1.2 itojun 1099: return;
1100:
1.31 itojun 1101: /*
1102: * if we get upper-layer reachability confirmation many times,
1103: * it is possible we have false information.
1104: */
1105: if (!force) {
1106: ln->ln_byhint++;
1107: if (ln->ln_byhint > nd6_maxnudhint)
1108: return;
1109: }
1110:
1.2 itojun 1111: ln->ln_state = ND6_LLINFO_REACHABLE;
1.86 itojun 1112: if (!ND6_LLINFO_PERMANENT(ln)) {
1113: nd6_llinfo_settimer(ln,
1114: (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
1115: }
1.2 itojun 1116: }
1117:
1118: void
1.130 ! dyoung 1119: nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
1.2 itojun 1120: {
1121: struct sockaddr *gate = rt->rt_gateway;
1122: struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1123: struct ifnet *ifp = rt->rt_ifp;
1.119 dyoung 1124: uint8_t namelen = strlen(ifp->if_xname), addrlen = ifp->if_addrlen;
1.2 itojun 1125: struct ifaddr *ifa;
1126:
1.128 dyoung 1127: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.117 dyoung 1128:
1.65 itojun 1129: if ((rt->rt_flags & RTF_GATEWAY) != 0)
1.2 itojun 1130: return;
1131:
1.54 itojun 1132: if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
1.128 dyoung 1133: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.54 itojun 1134: /*
1135: * This is probably an interface direct route for a link
1136: * which does not need neighbor caches (e.g. fe80::%lo0/64).
1137: * We do not need special treatment below for such a route.
1138: * Moreover, the RTF_LLINFO flag which would be set below
1139: * would annoy the ndp(8) command.
1140: */
1141: return;
1142: }
1143:
1.65 itojun 1144: if (req == RTM_RESOLVE &&
1145: (nd6_need_cache(ifp) == 0 || /* stf case */
1.117 dyoung 1146: !nd6_is_addr_neighbor(satocsin6(rt_getkey(rt)), ifp))) {
1.128 dyoung 1147: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.65 itojun 1148: /*
1149: * FreeBSD and BSD/OS often make a cloned host route based
1150: * on a less-specific route (e.g. the default route).
1151: * If the less specific route does not have a "gateway"
1152: * (this is the case when the route just goes to a p2p or an
1153: * stf interface), we'll mistakenly make a neighbor cache for
1154: * the host route, and will see strange neighbor solicitation
1155: * for the corresponding destination. In order to avoid the
1156: * confusion, we check if the destination of the route is
1157: * a neighbor in terms of neighbor discovery, and stop the
1158: * process if not. Additionally, we remove the LLINFO flag
1159: * so that ndp(8) will not try to get the neighbor information
1160: * of the destination.
1161: */
1162: rt->rt_flags &= ~RTF_LLINFO;
1163: return;
1164: }
1165:
1.2 itojun 1166: switch (req) {
1167: case RTM_ADD:
1.128 dyoung 1168: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1169: /*
1170: * There is no backward compatibility :)
1171: *
1172: * if ((rt->rt_flags & RTF_HOST) == 0 &&
1173: * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
1174: * rt->rt_flags |= RTF_CLONING;
1175: */
1.84 itojun 1176: if ((rt->rt_flags & RTF_CLONING) ||
1.129 dyoung 1177: ((rt->rt_flags & RTF_LLINFO) && ln == NULL)) {
1.120 dyoung 1178: union {
1179: struct sockaddr sa;
1180: struct sockaddr_dl sdl;
1181: struct sockaddr_storage ss;
1182: } u;
1.2 itojun 1183: /*
1.84 itojun 1184: * Case 1: This route should come from a route to
1185: * interface (RTF_CLONING case) or the route should be
1186: * treated as on-link but is currently not
1.129 dyoung 1187: * (RTF_LLINFO && ln == NULL case).
1.2 itojun 1188: */
1.120 dyoung 1189: sockaddr_dl_init(&u.sdl, sizeof(u.ss),
1190: ifp->if_index, ifp->if_type,
1191: NULL, namelen, NULL, addrlen);
1192: rt_setgate(rt, &u.sa);
1.119 dyoung 1193: gate = rt->rt_gateway;
1.128 dyoung 1194: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.129 dyoung 1195: if (ln != NULL)
1.86 itojun 1196: nd6_llinfo_settimer(ln, 0);
1.128 dyoung 1197: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.65 itojun 1198: if ((rt->rt_flags & RTF_CLONING) != 0)
1.2 itojun 1199: break;
1200: }
1.128 dyoung 1201: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.18 itojun 1202: /*
1203: * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here.
1204: * We don't do that here since llinfo is not ready yet.
1205: *
1206: * There are also couple of other things to be discussed:
1207: * - unsolicited NA code needs improvement beforehand
1208: * - RFC2461 says we MAY send multicast unsolicited NA
1209: * (7.2.6 paragraph 4), however, it also says that we
1210: * SHOULD provide a mechanism to prevent multicast NA storm.
1211: * we don't have anything like it right now.
1.38 itojun 1212: * note that the mechanism needs a mutual agreement
1.18 itojun 1213: * between proxies, which means that we need to implement
1.38 itojun 1214: * a new protocol, or a new kludge.
1215: * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
1.18 itojun 1216: * we need to check ip6forwarding before sending it.
1217: * (or should we allow proxy ND configuration only for
1218: * routers? there's no mention about proxy ND from hosts)
1219: */
1220: #if 0
1221: /* XXX it does not work */
1.2 itojun 1222: if (rt->rt_flags & RTF_ANNOUNCE)
1223: nd6_na_output(ifp,
1.118 dyoung 1224: &satocsin6(rt_getkey(rt))->sin6_addr,
1225: &satocsin6(rt_getkey(rt))->sin6_addr,
1.18 itojun 1226: ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
1227: 1, NULL);
1228: #endif
1.2 itojun 1229: /* FALLTHROUGH */
1230: case RTM_RESOLVE:
1.65 itojun 1231: if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
1.128 dyoung 1232: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.26 itojun 1233: /*
1234: * Address resolution isn't necessary for a point to
1235: * point link, so we can skip this test for a p2p link.
1236: */
1237: if (gate->sa_family != AF_LINK ||
1.119 dyoung 1238: gate->sa_len <
1239: sockaddr_dl_measure(namelen, addrlen)) {
1.26 itojun 1240: log(LOG_DEBUG,
1.36 itojun 1241: "nd6_rtrequest: bad gateway value: %s\n",
1242: if_name(ifp));
1.26 itojun 1243: break;
1244: }
1.118 dyoung 1245: satosdl(gate)->sdl_type = ifp->if_type;
1246: satosdl(gate)->sdl_index = ifp->if_index;
1.128 dyoung 1247: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1248: }
1.26 itojun 1249: if (ln != NULL)
1.2 itojun 1250: break; /* This happens on a route change */
1.128 dyoung 1251: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1252: /*
1253: * Case 2: This route may come from cloning, or a manual route
1254: * add with a LL address.
1255: */
1256: R_Malloc(ln, struct llinfo_nd6 *, sizeof(*ln));
1.129 dyoung 1257: rt->rt_llinfo = ln;
1.128 dyoung 1258: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.99 rpaulo 1259: if (ln == NULL) {
1.2 itojun 1260: log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n");
1261: break;
1262: }
1.128 dyoung 1263: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1264: nd6_inuse++;
1265: nd6_allocated++;
1.129 dyoung 1266: memset(ln, 0, sizeof(*ln));
1.2 itojun 1267: ln->ln_rt = rt;
1.126 ad 1268: callout_init(&ln->ln_timer_ch, CALLOUT_MPSAFE);
1.2 itojun 1269: /* this is required for "ndp" command. - shin */
1270: if (req == RTM_ADD) {
1271: /*
1272: * gate should have some valid AF_LINK entry,
1273: * and ln->ln_expire should have some lifetime
1274: * which is specified by ndp command.
1275: */
1276: ln->ln_state = ND6_LLINFO_REACHABLE;
1.31 itojun 1277: ln->ln_byhint = 0;
1.2 itojun 1278: } else {
1.25 itojun 1279: /*
1.2 itojun 1280: * When req == RTM_RESOLVE, rt is created and
1281: * initialized in rtrequest(), so rt_expire is 0.
1282: */
1.12 itojun 1283: ln->ln_state = ND6_LLINFO_NOSTATE;
1.86 itojun 1284: nd6_llinfo_settimer(ln, 0);
1.2 itojun 1285: }
1.128 dyoung 1286: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1287: rt->rt_flags |= RTF_LLINFO;
1.3 itojun 1288: ln->ln_next = llinfo_nd6.ln_next;
1289: llinfo_nd6.ln_next = ln;
1290: ln->ln_prev = &llinfo_nd6;
1291: ln->ln_next->ln_prev = ln;
1.2 itojun 1292:
1.128 dyoung 1293: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.2 itojun 1294: /*
1.117 dyoung 1295: * check if rt_getkey(rt) is an address assigned
1.2 itojun 1296: * to the interface.
1297: */
1.119 dyoung 1298: ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
1.118 dyoung 1299: &satocsin6(rt_getkey(rt))->sin6_addr);
1.128 dyoung 1300: RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
1.129 dyoung 1301: if (ifa != NULL) {
1.119 dyoung 1302: const void *mac;
1.86 itojun 1303: nd6_llinfo_settimer(ln, -1);
1.2 itojun 1304: ln->ln_state = ND6_LLINFO_REACHABLE;
1.31 itojun 1305: ln->ln_byhint = 0;
1.119 dyoung 1306: if ((mac = nd6_ifptomac(ifp)) != NULL) {
1.118 dyoung 1307: /* XXX check for error */
1.119 dyoung 1308: (void)sockaddr_dl_setaddr(satosdl(gate),
1309: gate->sa_len, mac, ifp->if_addrlen);
1.2 itojun 1310: }
1311: if (nd6_useloopback) {
1.119 dyoung 1312: ifp = rt->rt_ifp = lo0ifp; /* XXX */
1.2 itojun 1313: /*
1314: * Make sure rt_ifa be equal to the ifaddr
1315: * corresponding to the address.
1316: * We need this because when we refer
1317: * rt_ifa->ia6_flags in ip6_input, we assume
1318: * that the rt_ifa points to the address instead
1319: * of the loopback address.
1320: */
1.106 dyoung 1321: if (ifa != rt->rt_ifa)
1322: rt_replace_ifa(rt, ifa);
1.113 dyoung 1323: rt->rt_flags &= ~RTF_CLONED;
1.2 itojun 1324: }
1.18 itojun 1325: } else if (rt->rt_flags & RTF_ANNOUNCE) {
1.86 itojun 1326: nd6_llinfo_settimer(ln, -1);
1.18 itojun 1327: ln->ln_state = ND6_LLINFO_REACHABLE;
1.31 itojun 1328: ln->ln_byhint = 0;
1.18 itojun 1329:
1330: /* join solicited node multicast for proxy ND */
1331: if (ifp->if_flags & IFF_MULTICAST) {
1332: struct in6_addr llsol;
1333: int error;
1334:
1.118 dyoung 1335: llsol = satocsin6(rt_getkey(rt))->sin6_addr;
1.96 rpaulo 1336: llsol.s6_addr32[0] = htonl(0xff020000);
1.18 itojun 1337: llsol.s6_addr32[1] = 0;
1338: llsol.s6_addr32[2] = htonl(1);
1339: llsol.s6_addr8[12] = 0xff;
1.96 rpaulo 1340: if (in6_setscope(&llsol, ifp, NULL))
1341: break;
1.99 rpaulo 1342: if (!in6_addmulti(&llsol, ifp, &error, 0)) {
1.54 itojun 1343: nd6log((LOG_ERR, "%s: failed to join "
1344: "%s (errno=%d)\n", if_name(ifp),
1345: ip6_sprintf(&llsol), error));
1.46 itojun 1346: }
1.18 itojun 1347: }
1.2 itojun 1348: }
1349: break;
1350:
1351: case RTM_DELETE:
1.99 rpaulo 1352: if (ln == NULL)
1.2 itojun 1353: break;
1.18 itojun 1354: /* leave from solicited node multicast for proxy ND */
1355: if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
1356: (ifp->if_flags & IFF_MULTICAST) != 0) {
1357: struct in6_addr llsol;
1358: struct in6_multi *in6m;
1359:
1.118 dyoung 1360: llsol = satocsin6(rt_getkey(rt))->sin6_addr;
1.96 rpaulo 1361: llsol.s6_addr32[0] = htonl(0xff020000);
1.18 itojun 1362: llsol.s6_addr32[1] = 0;
1363: llsol.s6_addr32[2] = htonl(1);
1364: llsol.s6_addr8[12] = 0xff;
1.96 rpaulo 1365: if (in6_setscope(&llsol, ifp, NULL) == 0) {
1366: IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1367: if (in6m)
1368: in6_delmulti(in6m);
1.104 christos 1369: }
1.18 itojun 1370: }
1.2 itojun 1371: nd6_inuse--;
1.3 itojun 1372: ln->ln_next->ln_prev = ln->ln_prev;
1373: ln->ln_prev->ln_next = ln->ln_next;
1374: ln->ln_prev = NULL;
1.86 itojun 1375: nd6_llinfo_settimer(ln, -1);
1.2 itojun 1376: rt->rt_llinfo = 0;
1377: rt->rt_flags &= ~RTF_LLINFO;
1.100 rpaulo 1378: clear_llinfo_pqueue(ln);
1.129 dyoung 1379: Free(ln);
1.2 itojun 1380: }
1381: }
1382:
1383: int
1.112 dyoung 1384: nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
1.2 itojun 1385: {
1386: struct in6_drlist *drl = (struct in6_drlist *)data;
1.65 itojun 1387: struct in6_oprlist *oprl = (struct in6_oprlist *)data;
1.2 itojun 1388: struct in6_ndireq *ndi = (struct in6_ndireq *)data;
1389: struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
1.12 itojun 1390: struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
1.65 itojun 1391: struct nd_defrouter *dr;
1.2 itojun 1392: struct nd_prefix *pr;
1393: struct rtentry *rt;
1394: int i = 0, error = 0;
1395: int s;
1396:
1397: switch (cmd) {
1398: case SIOCGDRLST_IN6:
1.65 itojun 1399: /*
1400: * obsolete API, use sysctl under net.inet6.icmp6
1401: */
1.129 dyoung 1402: memset(drl, 0, sizeof(*drl));
1.5 itojun 1403: s = splsoftnet();
1.108 dyoung 1404: TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1405: if (i >= DRLSTSIZ)
1406: break;
1.2 itojun 1407: drl->defrouter[i].rtaddr = dr->rtaddr;
1.96 rpaulo 1408: in6_clearscope(&drl->defrouter[i].rtaddr);
1.2 itojun 1409:
1410: drl->defrouter[i].flags = dr->flags;
1411: drl->defrouter[i].rtlifetime = dr->rtlifetime;
1412: drl->defrouter[i].expire = dr->expire;
1413: drl->defrouter[i].if_index = dr->ifp->if_index;
1414: i++;
1415: }
1416: splx(s);
1417: break;
1418: case SIOCGPRLST_IN6:
1.18 itojun 1419: /*
1.65 itojun 1420: * obsolete API, use sysctl under net.inet6.icmp6
1421: *
1422: * XXX the structure in6_prlist was changed in backward-
1423: * incompatible manner. in6_oprlist is used for SIOCGPRLST_IN6,
1424: * in6_prlist is used for nd6_sysctl() - fill_prlist().
1425: */
1426: /*
1.18 itojun 1427: * XXX meaning of fields, especialy "raflags", is very
1428: * differnet between RA prefix list and RR/static prefix list.
1429: * how about separating ioctls into two?
1430: */
1.129 dyoung 1431: memset(oprl, 0, sizeof(*oprl));
1.5 itojun 1432: s = splsoftnet();
1.108 dyoung 1433: LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.2 itojun 1434: struct nd_pfxrouter *pfr;
1435: int j;
1436:
1.108 dyoung 1437: if (i >= PRLSTSIZ)
1438: break;
1.65 itojun 1439: oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
1440: oprl->prefix[i].raflags = pr->ndpr_raf;
1441: oprl->prefix[i].prefixlen = pr->ndpr_plen;
1442: oprl->prefix[i].vltime = pr->ndpr_vltime;
1443: oprl->prefix[i].pltime = pr->ndpr_pltime;
1444: oprl->prefix[i].if_index = pr->ndpr_ifp->if_index;
1.99 rpaulo 1445: if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1446: oprl->prefix[i].expire = 0;
1447: else {
1448: time_t maxexpire;
1449:
1450: /* XXX: we assume time_t is signed. */
1451: maxexpire = (-1) &
1452: ~((time_t)1 <<
1453: ((sizeof(maxexpire) * 8) - 1));
1454: if (pr->ndpr_vltime <
1455: maxexpire - pr->ndpr_lastupdate) {
1456: oprl->prefix[i].expire =
1457: pr->ndpr_lastupdate +
1458: pr->ndpr_vltime;
1459: } else
1460: oprl->prefix[i].expire = maxexpire;
1461: }
1.2 itojun 1462:
1463: j = 0;
1.108 dyoung 1464: LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
1.2 itojun 1465: if (j < DRLSTSIZ) {
1.65 itojun 1466: #define RTRADDR oprl->prefix[i].advrtr[j]
1.2 itojun 1467: RTRADDR = pfr->router->rtaddr;
1.96 rpaulo 1468: in6_clearscope(&RTRADDR);
1.2 itojun 1469: #undef RTRADDR
1470: }
1471: j++;
1472: }
1.65 itojun 1473: oprl->prefix[i].advrtrs = j;
1474: oprl->prefix[i].origin = PR_ORIG_RA;
1.2 itojun 1475:
1476: i++;
1477: }
1.18 itojun 1478: splx(s);
1.12 itojun 1479:
1.2 itojun 1480: break;
1.58 itojun 1481: case OSIOCGIFINFO_IN6:
1.99 rpaulo 1482: #define ND ndi->ndi
1.58 itojun 1483: /* XXX: old ndp(8) assumes a positive value for linkmtu. */
1.99 rpaulo 1484: memset(&ND, 0, sizeof(ND));
1485: ND.linkmtu = IN6_LINKMTU(ifp);
1486: ND.maxmtu = ND_IFINFO(ifp)->maxmtu;
1487: ND.basereachable = ND_IFINFO(ifp)->basereachable;
1488: ND.reachable = ND_IFINFO(ifp)->reachable;
1489: ND.retrans = ND_IFINFO(ifp)->retrans;
1490: ND.flags = ND_IFINFO(ifp)->flags;
1491: ND.recalctm = ND_IFINFO(ifp)->recalctm;
1492: ND.chlim = ND_IFINFO(ifp)->chlim;
1.58 itojun 1493: break;
1.2 itojun 1494: case SIOCGIFINFO_IN6:
1.99 rpaulo 1495: ND = *ND_IFINFO(ifp);
1.2 itojun 1496: break;
1.99 rpaulo 1497: case SIOCSIFINFO_IN6:
1498: /*
1499: * used to change host variables from userland.
1500: * intented for a use on router to reflect RA configurations.
1501: */
1502: /* 0 means 'unspecified' */
1503: if (ND.linkmtu != 0) {
1504: if (ND.linkmtu < IPV6_MMTU ||
1505: ND.linkmtu > IN6_LINKMTU(ifp)) {
1506: error = EINVAL;
1507: break;
1508: }
1509: ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
1510: }
1511:
1512: if (ND.basereachable != 0) {
1513: int obasereachable = ND_IFINFO(ifp)->basereachable;
1514:
1515: ND_IFINFO(ifp)->basereachable = ND.basereachable;
1516: if (ND.basereachable != obasereachable)
1517: ND_IFINFO(ifp)->reachable =
1518: ND_COMPUTE_RTIME(ND.basereachable);
1519: }
1520: if (ND.retrans != 0)
1521: ND_IFINFO(ifp)->retrans = ND.retrans;
1522: if (ND.chlim != 0)
1523: ND_IFINFO(ifp)->chlim = ND.chlim;
1524: /* FALLTHROUGH */
1.26 itojun 1525: case SIOCSIFINFO_FLAGS:
1.99 rpaulo 1526: ND_IFINFO(ifp)->flags = ND.flags;
1.26 itojun 1527: break;
1.99 rpaulo 1528: #undef ND
1.12 itojun 1529: case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
1.65 itojun 1530: /* sync kernel routing table with the default router list */
1531: defrouter_reset();
1.12 itojun 1532: defrouter_select();
1.2 itojun 1533: break;
1534: case SIOCSPFXFLUSH_IN6:
1.65 itojun 1535: {
1.2 itojun 1536: /* flush all the prefix advertised by routers */
1.94 christos 1537: struct nd_prefix *pfx, *next;
1.2 itojun 1538:
1.5 itojun 1539: s = splsoftnet();
1.108 dyoung 1540: for (pfx = LIST_FIRST(&nd_prefix); pfx; pfx = next) {
1.65 itojun 1541: struct in6_ifaddr *ia, *ia_next;
1542:
1.108 dyoung 1543: next = LIST_NEXT(pfx, ndpr_entry);
1.65 itojun 1544:
1.94 christos 1545: if (IN6_IS_ADDR_LINKLOCAL(&pfx->ndpr_prefix.sin6_addr))
1.65 itojun 1546: continue; /* XXX */
1547:
1548: /* do we really have to remove addresses as well? */
1549: for (ia = in6_ifaddr; ia; ia = ia_next) {
1550: /* ia might be removed. keep the next ptr. */
1551: ia_next = ia->ia_next;
1552:
1553: if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1554: continue;
1555:
1.94 christos 1556: if (ia->ia6_ndpr == pfx)
1.65 itojun 1557: in6_purgeaddr(&ia->ia_ifa);
1558: }
1.94 christos 1559: prelist_remove(pfx);
1.2 itojun 1560: }
1561: splx(s);
1562: break;
1.65 itojun 1563: }
1.2 itojun 1564: case SIOCSRTRFLUSH_IN6:
1.65 itojun 1565: {
1.2 itojun 1566: /* flush all the default routers */
1.94 christos 1567: struct nd_defrouter *drtr, *next;
1.2 itojun 1568:
1.5 itojun 1569: s = splsoftnet();
1.65 itojun 1570: defrouter_reset();
1.94 christos 1571: for (drtr = TAILQ_FIRST(&nd_defrouter); drtr; drtr = next) {
1572: next = TAILQ_NEXT(drtr, dr_entry);
1573: defrtrlist_del(drtr);
1.2 itojun 1574: }
1.65 itojun 1575: defrouter_select();
1.2 itojun 1576: splx(s);
1577: break;
1.65 itojun 1578: }
1.2 itojun 1579: case SIOCGNBRINFO_IN6:
1.99 rpaulo 1580: {
1.12 itojun 1581: struct llinfo_nd6 *ln;
1582: struct in6_addr nb_addr = nbi->addr; /* make local for safety */
1583:
1.96 rpaulo 1584: if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
1.112 dyoung 1585: return error;
1.2 itojun 1586:
1.12 itojun 1587: s = splsoftnet();
1.65 itojun 1588: if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL ||
1589: (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
1.12 itojun 1590: error = EINVAL;
1591: splx(s);
1592: break;
1593: }
1594: nbi->state = ln->ln_state;
1595: nbi->asked = ln->ln_asked;
1596: nbi->isrouter = ln->ln_router;
1597: nbi->expire = ln->ln_expire;
1598: splx(s);
1.63 itojun 1599:
1.12 itojun 1600: break;
1.65 itojun 1601: }
1.12 itojun 1602: case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
1603: ndif->ifindex = nd6_defifindex;
1604: break;
1605: case SIOCSDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
1.112 dyoung 1606: return nd6_setdefaultiface(ndif->ifindex);
1.2 itojun 1607: }
1.112 dyoung 1608: return error;
1.2 itojun 1609: }
1610:
1.115 dyoung 1611: void
1612: nd6_llinfo_release_pkts(struct llinfo_nd6 *ln, struct ifnet *ifp,
1613: struct rtentry *rt)
1614: {
1615: struct mbuf *m_hold, *m_hold_next;
1616:
1617: for (m_hold = ln->ln_hold, ln->ln_hold = NULL;
1618: m_hold != NULL;
1619: m_hold = m_hold_next) {
1620: m_hold_next = m_hold->m_nextpkt;
1621: m_hold->m_nextpkt = NULL;
1622:
1623: /*
1624: * we assume ifp is not a p2p here, so
1625: * just set the 2nd argument as the
1626: * 1st one.
1627: */
1.117 dyoung 1628: nd6_output(ifp, ifp, m_hold, satocsin6(rt_getkey(rt)), rt);
1.115 dyoung 1629: }
1630: }
1631:
1.2 itojun 1632: /*
1633: * Create neighbor cache entry and cache link-layer address,
1.52 itojun 1634: * on reception of inbound ND6 packets. (RS/RA/NS/redirect)
1.2 itojun 1635: */
1636: struct rtentry *
1.105 christos 1637: nd6_cache_lladdr(
1638: struct ifnet *ifp,
1639: struct in6_addr *from,
1640: char *lladdr,
1.107 christos 1641: int lladdrlen,
1.105 christos 1642: int type, /* ICMP6 type */
1643: int code /* type dependent information */
1644: )
1.2 itojun 1645: {
1646: struct rtentry *rt = NULL;
1647: struct llinfo_nd6 *ln = NULL;
1648: int is_newentry;
1649: struct sockaddr_dl *sdl = NULL;
1650: int do_update;
1651: int olladdr;
1652: int llchange;
1653: int newstate = 0;
1654:
1.99 rpaulo 1655: if (ifp == NULL)
1.2 itojun 1656: panic("ifp == NULL in nd6_cache_lladdr");
1.99 rpaulo 1657: if (from == NULL)
1.2 itojun 1658: panic("from == NULL in nd6_cache_lladdr");
1659:
1660: /* nothing must be updated for unspecified address */
1661: if (IN6_IS_ADDR_UNSPECIFIED(from))
1662: return NULL;
1663:
1664: /*
1665: * Validation about ifp->if_addrlen and lladdrlen must be done in
1666: * the caller.
1667: *
1668: * XXX If the link does not have link-layer adderss, what should
1669: * we do? (ifp->if_addrlen == 0)
1670: * Spec says nothing in sections for RA, RS and NA. There's small
1671: * description on it in NS section (RFC 2461 7.2.3).
1672: */
1673:
1674: rt = nd6_lookup(from, 0, ifp);
1.99 rpaulo 1675: if (rt == NULL) {
1.2 itojun 1676: #if 0
1677: /* nothing must be done if there's no lladdr */
1678: if (!lladdr || !lladdrlen)
1679: return NULL;
1680: #endif
1681:
1682: rt = nd6_lookup(from, 1, ifp);
1683: is_newentry = 1;
1.43 itojun 1684: } else {
1685: /* do nothing if static ndp is set */
1686: if (rt->rt_flags & RTF_STATIC)
1687: return NULL;
1.2 itojun 1688: is_newentry = 0;
1.43 itojun 1689: }
1.2 itojun 1690:
1.99 rpaulo 1691: if (rt == NULL)
1.2 itojun 1692: return NULL;
1693: if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
1694: fail:
1.54 itojun 1695: (void)nd6_free(rt, 0);
1.2 itojun 1696: return NULL;
1697: }
1698: ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1.99 rpaulo 1699: if (ln == NULL)
1.2 itojun 1700: goto fail;
1.99 rpaulo 1701: if (rt->rt_gateway == NULL)
1.2 itojun 1702: goto fail;
1703: if (rt->rt_gateway->sa_family != AF_LINK)
1704: goto fail;
1.118 dyoung 1705: sdl = satosdl(rt->rt_gateway);
1.2 itojun 1706:
1707: olladdr = (sdl->sdl_alen) ? 1 : 0;
1708: if (olladdr && lladdr) {
1.118 dyoung 1709: if (memcmp(lladdr, CLLADDR(sdl), ifp->if_addrlen))
1.2 itojun 1710: llchange = 1;
1711: else
1712: llchange = 0;
1713: } else
1714: llchange = 0;
1715:
1716: /*
1717: * newentry olladdr lladdr llchange (*=record)
1718: * 0 n n -- (1)
1719: * 0 y n -- (2)
1720: * 0 n y -- (3) * STALE
1721: * 0 y y n (4) *
1722: * 0 y y y (5) * STALE
1723: * 1 -- n -- (6) NOSTATE(= PASSIVE)
1724: * 1 -- y -- (7) * STALE
1725: */
1726:
1.52 itojun 1727: if (lladdr) { /* (3-5) and (7) */
1.2 itojun 1728: /*
1729: * Record source link-layer address
1730: * XXX is it dependent to ifp->if_type?
1731: */
1.118 dyoung 1732: /* XXX check for error */
1.119 dyoung 1733: (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, lladdr,
1734: ifp->if_addrlen);
1.2 itojun 1735: }
1736:
1737: if (!is_newentry) {
1.65 itojun 1738: if ((!olladdr && lladdr) || /* (3) */
1739: (olladdr && lladdr && llchange)) { /* (5) */
1.2 itojun 1740: do_update = 1;
1741: newstate = ND6_LLINFO_STALE;
1.52 itojun 1742: } else /* (1-2,4) */
1.2 itojun 1743: do_update = 0;
1744: } else {
1745: do_update = 1;
1.99 rpaulo 1746: if (lladdr == NULL) /* (6) */
1.2 itojun 1747: newstate = ND6_LLINFO_NOSTATE;
1.52 itojun 1748: else /* (7) */
1.2 itojun 1749: newstate = ND6_LLINFO_STALE;
1750: }
1751:
1752: if (do_update) {
1753: /*
1754: * Update the state of the neighbor cache.
1755: */
1756: ln->ln_state = newstate;
1757:
1758: if (ln->ln_state == ND6_LLINFO_STALE) {
1.44 itojun 1759: /*
1760: * XXX: since nd6_output() below will cause
1761: * state tansition to DELAY and reset the timer,
1762: * we must set the timer now, although it is actually
1763: * meaningless.
1764: */
1.86 itojun 1765: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.44 itojun 1766:
1.115 dyoung 1767: nd6_llinfo_release_pkts(ln, ifp, rt);
1.2 itojun 1768: } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
1769: /* probe right away */
1.86 itojun 1770: nd6_llinfo_settimer((void *)ln, 0);
1.2 itojun 1771: }
1772: }
1773:
1774: /*
1775: * ICMP6 type dependent behavior.
1776: *
1777: * NS: clear IsRouter if new entry
1778: * RS: clear IsRouter
1779: * RA: set IsRouter if there's lladdr
1780: * redir: clear IsRouter if new entry
1781: *
1782: * RA case, (1):
1783: * The spec says that we must set IsRouter in the following cases:
1784: * - If lladdr exist, set IsRouter. This means (1-5).
1785: * - If it is old entry (!newentry), set IsRouter. This means (7).
1786: * So, based on the spec, in (1-5) and (7) cases we must set IsRouter.
1787: * A quetion arises for (1) case. (1) case has no lladdr in the
1788: * neighbor cache, this is similar to (6).
1789: * This case is rare but we figured that we MUST NOT set IsRouter.
1790: *
1791: * newentry olladdr lladdr llchange NS RS RA redir
1.8 itojun 1792: * D R
1793: * 0 n n -- (1) c ? s
1794: * 0 y n -- (2) c s s
1795: * 0 n y -- (3) c s s
1796: * 0 y y n (4) c s s
1797: * 0 y y y (5) c s s
1798: * 1 -- n -- (6) c c c s
1799: * 1 -- y -- (7) c c s c s
1.2 itojun 1800: *
1801: * (c=clear s=set)
1802: */
1803: switch (type & 0xff) {
1804: case ND_NEIGHBOR_SOLICIT:
1805: /*
1806: * New entry must have is_router flag cleared.
1807: */
1.52 itojun 1808: if (is_newentry) /* (6-7) */
1.8 itojun 1809: ln->ln_router = 0;
1810: break;
1811: case ND_REDIRECT:
1812: /*
1813: * If the icmp is a redirect to a better router, always set the
1.52 itojun 1814: * is_router flag. Otherwise, if the entry is newly created,
1815: * clear the flag. [RFC 2461, sec 8.3]
1.8 itojun 1816: */
1817: if (code == ND_REDIRECT_ROUTER)
1818: ln->ln_router = 1;
1.52 itojun 1819: else if (is_newentry) /* (6-7) */
1.2 itojun 1820: ln->ln_router = 0;
1821: break;
1822: case ND_ROUTER_SOLICIT:
1823: /*
1824: * is_router flag must always be cleared.
1825: */
1826: ln->ln_router = 0;
1827: break;
1828: case ND_ROUTER_ADVERT:
1829: /*
1830: * Mark an entry with lladdr as a router.
1831: */
1.65 itojun 1832: if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */
1833: (is_newentry && lladdr)) { /* (7) */
1.2 itojun 1834: ln->ln_router = 1;
1835: }
1836: break;
1837: }
1.47 itojun 1838:
1839: /*
1840: * When the link-layer address of a router changes, select the
1841: * best router again. In particular, when the neighbor entry is newly
1842: * created, it might affect the selection policy.
1843: * Question: can we restrict the first condition to the "is_newentry"
1844: * case?
1845: * XXX: when we hear an RA from a new router with the link-layer
1846: * address option, defrouter_select() is called twice, since
1847: * defrtrlist_update called the function as well. However, I believe
1848: * we can compromise the overhead, since it only happens the first
1849: * time.
1.52 itojun 1850: * XXX: although defrouter_select() should not have a bad effect
1851: * for those are not autoconfigured hosts, we explicitly avoid such
1852: * cases for safety.
1.47 itojun 1853: */
1.49 itojun 1854: if (do_update && ln->ln_router && !ip6_forwarding && ip6_accept_rtadv)
1.47 itojun 1855: defrouter_select();
1.2 itojun 1856:
1857: return rt;
1858: }
1859:
1860: static void
1.107 christos 1861: nd6_slowtimo(void *ignored_arg)
1.2 itojun 1862: {
1.38 itojun 1863: struct nd_ifinfo *nd6if;
1.58 itojun 1864: struct ifnet *ifp;
1.2 itojun 1865:
1.126 ad 1866: mutex_enter(softnet_lock);
1867: KERNEL_LOCK(1, NULL);
1868: callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
1.20 thorpej 1869: nd6_slowtimo, NULL);
1.108 dyoung 1870: TAILQ_FOREACH(ifp, &ifnet, if_list) {
1.58 itojun 1871: nd6if = ND_IFINFO(ifp);
1.2 itojun 1872: if (nd6if->basereachable && /* already initialized */
1873: (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
1874: /*
1875: * Since reachable time rarely changes by router
1876: * advertisements, we SHOULD insure that a new random
1877: * value gets recomputed at least once every few hours.
1878: * (RFC 2461, 6.3.4)
1879: */
1880: nd6if->recalctm = nd6_recalc_reachtm_interval;
1881: nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
1882: }
1883: }
1.126 ad 1884: KERNEL_UNLOCK_ONE(NULL);
1885: mutex_exit(softnet_lock);
1.2 itojun 1886: }
1887:
1888: #define senderr(e) { error = (e); goto bad;}
1889: int
1.112 dyoung 1890: nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
1.114 dyoung 1891: const struct sockaddr_in6 *dst, struct rtentry *rt0)
1.2 itojun 1892: {
1.38 itojun 1893: struct mbuf *m = m0;
1894: struct rtentry *rt = rt0;
1.29 itojun 1895: struct sockaddr_in6 *gw6 = NULL;
1.2 itojun 1896: struct llinfo_nd6 *ln = NULL;
1897: int error = 0;
1898:
1899: if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
1900: goto sendpkt;
1901:
1.54 itojun 1902: if (nd6_need_cache(ifp) == 0)
1.2 itojun 1903: goto sendpkt;
1904:
1905: /*
1.98 rpaulo 1906: * next hop determination. This routine is derived from ether_output.
1.2 itojun 1907: */
1908: if (rt) {
1909: if ((rt->rt_flags & RTF_UP) == 0) {
1.114 dyoung 1910: if ((rt0 = rt = rtalloc1(sin6tocsa(dst), 1)) != NULL) {
1.2 itojun 1911: rt->rt_refcnt--;
1.90 itojun 1912: if (rt->rt_ifp != ifp)
1913: senderr(EHOSTUNREACH);
1.25 itojun 1914: } else
1.2 itojun 1915: senderr(EHOSTUNREACH);
1916: }
1.29 itojun 1917:
1.2 itojun 1918: if (rt->rt_flags & RTF_GATEWAY) {
1.29 itojun 1919: gw6 = (struct sockaddr_in6 *)rt->rt_gateway;
1920:
1921: /*
1922: * We skip link-layer address resolution and NUD
1923: * if the gateway is not a neighbor from ND point
1.65 itojun 1924: * of view, regardless of the value of nd_ifinfo.flags.
1.56 itojun 1925: * The second condition is a bit tricky; we skip
1.29 itojun 1926: * if the gateway is our own address, which is
1927: * sometimes used to install a route to a p2p link.
1928: */
1929: if (!nd6_is_addr_neighbor(gw6, ifp) ||
1930: in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
1931: /*
1932: * We allow this kind of tricky route only
1933: * when the outgoing interface is p2p.
1934: * XXX: we may need a more generic rule here.
1935: */
1936: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
1937: senderr(EHOSTUNREACH);
1938:
1939: goto sendpkt;
1940: }
1941:
1.127 dyoung 1942: if (rt->rt_gwroute == NULL)
1.2 itojun 1943: goto lookup;
1944: if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
1945: rtfree(rt); rt = rt0;
1.50 itojun 1946: lookup:
1947: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1);
1.127 dyoung 1948: if ((rt = rt->rt_gwroute) == NULL)
1.2 itojun 1949: senderr(EHOSTUNREACH);
1.50 itojun 1950: /* the "G" test below also prevents rt == rt0 */
1951: if ((rt->rt_flags & RTF_GATEWAY) ||
1952: (rt->rt_ifp != ifp)) {
1953: rt->rt_refcnt--;
1.127 dyoung 1954: rt0->rt_gwroute = NULL;
1.50 itojun 1955: senderr(EHOSTUNREACH);
1956: }
1.2 itojun 1957: }
1958: }
1959: }
1960:
1961: /*
1962: * Address resolution or Neighbor Unreachability Detection
1963: * for the next hop.
1964: * At this point, the destination of the packet must be a unicast
1965: * or an anycast address(i.e. not a multicast).
1966: */
1967:
1968: /* Look up the neighbor cache for the nexthop */
1.127 dyoung 1969: if (rt != NULL && (rt->rt_flags & RTF_LLINFO) != 0)
1.2 itojun 1970: ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1971: else {
1.29 itojun 1972: /*
1973: * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
1.52 itojun 1974: * the condition below is not very efficient. But we believe
1.29 itojun 1975: * it is tolerable, because this should be a rare case.
1976: */
1977: if (nd6_is_addr_neighbor(dst, ifp) &&
1978: (rt = nd6_lookup(&dst->sin6_addr, 1, ifp)) != NULL)
1.2 itojun 1979: ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1980: }
1.99 rpaulo 1981: if (ln == NULL || rt == NULL) {
1.29 itojun 1982: if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
1.58 itojun 1983: !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
1.29 itojun 1984: log(LOG_DEBUG,
1985: "nd6_output: can't allocate llinfo for %s "
1986: "(ln=%p, rt=%p)\n",
1987: ip6_sprintf(&dst->sin6_addr), ln, rt);
1988: senderr(EIO); /* XXX: good error? */
1989: }
1990:
1991: goto sendpkt; /* send anyway */
1.2 itojun 1992: }
1993:
1.26 itojun 1994: /* We don't have to do link-layer address resolution on a p2p link. */
1995: if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
1.42 itojun 1996: ln->ln_state < ND6_LLINFO_REACHABLE) {
1.26 itojun 1997: ln->ln_state = ND6_LLINFO_STALE;
1.86 itojun 1998: nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1.42 itojun 1999: }
1.2 itojun 2000:
2001: /*
2002: * The first time we send a packet to a neighbor whose entry is
2003: * STALE, we have to change the state to DELAY and a sets a timer to
2004: * expire in DELAY_FIRST_PROBE_TIME seconds to ensure do
2005: * neighbor unreachability detection on expiration.
2006: * (RFC 2461 7.3.3)
2007: */
2008: if (ln->ln_state == ND6_LLINFO_STALE) {
2009: ln->ln_asked = 0;
2010: ln->ln_state = ND6_LLINFO_DELAY;
1.99 rpaulo 2011: nd6_llinfo_settimer(ln, (long)nd6_delay * hz);
1.2 itojun 2012: }
2013:
2014: /*
2015: * If the neighbor cache entry has a state other than INCOMPLETE
1.52 itojun 2016: * (i.e. its link-layer address is already resolved), just
1.2 itojun 2017: * send the packet.
2018: */
2019: if (ln->ln_state > ND6_LLINFO_INCOMPLETE)
2020: goto sendpkt;
2021:
2022: /*
2023: * There is a neighbor cache entry, but no ethernet address
1.99 rpaulo 2024: * response yet. Append this latest packet to the end of the
2025: * packet queue in the mbuf, unless the number of the packet
2026: * does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen,
2027: * the oldest packet in the queue will be removed.
1.2 itojun 2028: */
1.41 itojun 2029: if (ln->ln_state == ND6_LLINFO_NOSTATE)
1.2 itojun 2030: ln->ln_state = ND6_LLINFO_INCOMPLETE;
1.99 rpaulo 2031: if (ln->ln_hold) {
2032: struct mbuf *m_hold;
2033: int i;
2034:
2035: i = 0;
2036: for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) {
2037: i++;
2038: if (m_hold->m_nextpkt == NULL) {
2039: m_hold->m_nextpkt = m;
2040: break;
2041: }
2042: }
2043: while (i >= nd6_maxqueuelen) {
2044: m_hold = ln->ln_hold;
2045: ln->ln_hold = ln->ln_hold->m_nextpkt;
1.100 rpaulo 2046: m_freem(m_hold);
1.99 rpaulo 2047: i--;
2048: }
2049: } else {
2050: ln->ln_hold = m;
2051: }
2052:
1.64 itojun 2053: /*
2054: * If there has been no NS for the neighbor after entering the
2055: * INCOMPLETE state, send the first solicitation.
2056: */
1.86 itojun 2057: if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
1.64 itojun 2058: ln->ln_asked++;
1.86 itojun 2059: nd6_llinfo_settimer(ln,
2060: (long)ND_IFINFO(ifp)->retrans * hz / 1000);
1.64 itojun 2061: nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
1.2 itojun 2062: }
1.112 dyoung 2063: return 0;
1.63 itojun 2064:
1.2 itojun 2065: sendpkt:
1.99 rpaulo 2066: /* discard the packet if IPv6 operation is disabled on the interface */
2067: if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {
2068: error = ENETDOWN; /* better error? */
2069: goto bad;
2070: }
1.30 itojun 2071:
1.78 itojun 2072: #ifdef IPSEC
2073: /* clean ipsec history once it goes out of the node */
2074: ipsec_delaux(m);
2075: #endif
1.127 dyoung 2076: if ((ifp->if_flags & IFF_LOOPBACK) != 0)
1.114 dyoung 2077: return (*ifp->if_output)(origifp, m, sin6tocsa(dst), rt);
2078: return (*ifp->if_output)(ifp, m, sin6tocsa(dst), rt);
1.25 itojun 2079:
1.2 itojun 2080: bad:
1.114 dyoung 2081: if (m != NULL)
1.2 itojun 2082: m_freem(m);
1.112 dyoung 2083: return error;
1.63 itojun 2084: }
1.2 itojun 2085: #undef senderr
1.54 itojun 2086:
2087: int
1.112 dyoung 2088: nd6_need_cache(struct ifnet *ifp)
1.54 itojun 2089: {
2090: /*
2091: * XXX: we currently do not make neighbor cache on any interface
2092: * other than ARCnet, Ethernet, FDDI and GIF.
2093: *
2094: * RFC2893 says:
2095: * - unidirectional tunnels needs no ND
2096: */
2097: switch (ifp->if_type) {
2098: case IFT_ARCNET:
2099: case IFT_ETHER:
2100: case IFT_FDDI:
2101: case IFT_IEEE1394:
1.102 liamjfoy 2102: case IFT_CARP:
1.54 itojun 2103: case IFT_GIF: /* XXX need more cases? */
1.99 rpaulo 2104: case IFT_PPP:
2105: case IFT_TUNNEL:
1.112 dyoung 2106: return 1;
1.54 itojun 2107: default:
1.112 dyoung 2108: return 0;
1.54 itojun 2109: }
2110: }
1.2 itojun 2111:
2112: int
1.110 dyoung 2113: nd6_storelladdr(const struct ifnet *ifp, const struct rtentry *rt,
1.127 dyoung 2114: struct mbuf *m, const struct sockaddr *dst, uint8_t *lldst,
1.110 dyoung 2115: size_t dstsize)
1.2 itojun 2116: {
1.110 dyoung 2117: const struct sockaddr_dl *sdl;
1.2 itojun 2118:
2119: if (m->m_flags & M_MCAST) {
2120: switch (ifp->if_type) {
2121: case IFT_ETHER:
1.63 itojun 2122: case IFT_FDDI:
1.118 dyoung 2123: ETHER_MAP_IPV6_MULTICAST(&satocsin6(dst)->sin6_addr,
2124: lldst);
1.110 dyoung 2125: return 1;
1.33 onoe 2126: case IFT_IEEE1394:
1.118 dyoung 2127: memcpy(lldst, ifp->if_broadcastaddr,
2128: MIN(dstsize, ifp->if_addrlen));
1.110 dyoung 2129: return 1;
1.9 is 2130: case IFT_ARCNET:
1.110 dyoung 2131: *lldst = 0;
2132: return 1;
1.2 itojun 2133: default:
1.43 itojun 2134: m_freem(m);
1.110 dyoung 2135: return 0;
1.2 itojun 2136: }
2137: }
2138:
1.32 itojun 2139: if (rt == NULL) {
2140: /* this could happen, if we could not allocate memory */
1.43 itojun 2141: m_freem(m);
1.110 dyoung 2142: return 0;
1.32 itojun 2143: }
2144: if (rt->rt_gateway->sa_family != AF_LINK) {
1.110 dyoung 2145: printf("%s: something odd happens\n", __func__);
1.43 itojun 2146: m_freem(m);
1.110 dyoung 2147: return 0;
1.2 itojun 2148: }
1.118 dyoung 2149: sdl = satocsdl(rt->rt_gateway);
1.110 dyoung 2150: if (sdl->sdl_alen == 0 || sdl->sdl_alen > dstsize) {
1.24 itojun 2151: /* this should be impossible, but we bark here for debugging */
1.110 dyoung 2152: printf("%s: sdl_alen == 0, dst=%s, if=%s\n", __func__,
1.118 dyoung 2153: ip6_sprintf(&satocsin6(dst)->sin6_addr), if_name(ifp));
1.43 itojun 2154: m_freem(m);
1.110 dyoung 2155: return 0;
1.23 itojun 2156: }
1.2 itojun 2157:
1.110 dyoung 2158: memcpy(lldst, CLLADDR(sdl), MIN(dstsize, sdl->sdl_alen));
2159: return 1;
1.65 itojun 2160: }
2161:
1.100 rpaulo 2162: static void
1.112 dyoung 2163: clear_llinfo_pqueue(struct llinfo_nd6 *ln)
1.100 rpaulo 2164: {
2165: struct mbuf *m_hold, *m_hold_next;
2166:
2167: for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
2168: m_hold_next = m_hold->m_nextpkt;
2169: m_hold->m_nextpkt = NULL;
2170: m_freem(m_hold);
2171: }
2172:
2173: ln->ln_hold = NULL;
2174: return;
2175: }
2176:
1.65 itojun 2177: int
1.105 christos 2178: nd6_sysctl(
2179: int name,
2180: void *oldp, /* syscall arg, need copyout */
2181: size_t *oldlenp,
2182: void *newp, /* syscall arg, need copyin */
1.107 christos 2183: size_t newlen
1.105 christos 2184: )
1.65 itojun 2185: {
1.69 itojun 2186: void *p;
1.88 simonb 2187: size_t ol;
1.65 itojun 2188: int error;
2189:
2190: error = 0;
2191:
2192: if (newp)
2193: return EPERM;
2194: if (oldp && !oldlenp)
2195: return EINVAL;
2196: ol = oldlenp ? *oldlenp : 0;
2197:
1.69 itojun 2198: if (oldp) {
2199: p = malloc(*oldlenp, M_TEMP, M_WAITOK);
1.99 rpaulo 2200: if (p == NULL)
1.69 itojun 2201: return ENOMEM;
2202: } else
2203: p = NULL;
1.65 itojun 2204: switch (name) {
2205: case ICMPV6CTL_ND6_DRLIST:
1.69 itojun 2206: error = fill_drlist(p, oldlenp, ol);
1.99 rpaulo 2207: if (!error && p != NULL && oldp != NULL)
1.71 itojun 2208: error = copyout(p, oldp, *oldlenp);
1.65 itojun 2209: break;
2210:
2211: case ICMPV6CTL_ND6_PRLIST:
1.69 itojun 2212: error = fill_prlist(p, oldlenp, ol);
1.99 rpaulo 2213: if (!error && p != NULL && oldp != NULL)
1.71 itojun 2214: error = copyout(p, oldp, *oldlenp);
1.65 itojun 2215: break;
2216:
1.99 rpaulo 2217: case ICMPV6CTL_ND6_MAXQLEN:
2218: break;
2219:
1.65 itojun 2220: default:
2221: error = ENOPROTOOPT;
2222: break;
2223: }
1.69 itojun 2224: if (p)
2225: free(p, M_TEMP);
1.65 itojun 2226:
1.112 dyoung 2227: return error;
1.65 itojun 2228: }
2229:
2230: static int
1.112 dyoung 2231: fill_drlist(void *oldp, size_t *oldlenp, size_t ol)
1.65 itojun 2232: {
2233: int error = 0, s;
2234: struct in6_defrouter *d = NULL, *de = NULL;
2235: struct nd_defrouter *dr;
2236: size_t l;
2237:
2238: s = splsoftnet();
1.66 itojun 2239:
1.65 itojun 2240: if (oldp) {
2241: d = (struct in6_defrouter *)oldp;
1.111 christos 2242: de = (struct in6_defrouter *)((char *)oldp + *oldlenp);
1.65 itojun 2243: }
2244: l = 0;
2245:
1.108 dyoung 2246: TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
1.65 itojun 2247:
2248: if (oldp && d + 1 <= de) {
1.122 dyoung 2249: memset(d, 0, sizeof(*d));
2250: sockaddr_in6_init(&d->rtaddr, &dr->rtaddr, 0, 0, 0);
1.96 rpaulo 2251: if (sa6_recoverscope(&d->rtaddr)) {
2252: log(LOG_ERR,
2253: "scope error in router list (%s)\n",
2254: ip6_sprintf(&d->rtaddr.sin6_addr));
2255: /* XXX: press on... */
2256: }
1.65 itojun 2257: d->flags = dr->flags;
2258: d->rtlifetime = dr->rtlifetime;
2259: d->expire = dr->expire;
2260: d->if_index = dr->ifp->if_index;
2261: }
2262:
2263: l += sizeof(*d);
2264: if (d)
2265: d++;
2266: }
2267:
2268: if (oldp) {
2269: if (l > ol)
2270: error = ENOMEM;
1.101 christos 2271: }
2272: if (oldlenp)
1.111 christos 2273: *oldlenp = l; /* (void *)d - (void *)oldp */
1.65 itojun 2274:
2275: splx(s);
2276:
1.112 dyoung 2277: return error;
1.65 itojun 2278: }
2279:
2280: static int
1.112 dyoung 2281: fill_prlist(void *oldp, size_t *oldlenp, size_t ol)
1.65 itojun 2282: {
2283: int error = 0, s;
2284: struct nd_prefix *pr;
2285: struct in6_prefix *p = NULL;
2286: struct in6_prefix *pe = NULL;
2287: size_t l;
2288:
2289: s = splsoftnet();
2290:
2291: if (oldp) {
2292: p = (struct in6_prefix *)oldp;
1.111 christos 2293: pe = (struct in6_prefix *)((char *)oldp + *oldlenp);
1.65 itojun 2294: }
2295: l = 0;
2296:
1.108 dyoung 2297: LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
1.65 itojun 2298: u_short advrtrs;
2299: size_t advance;
2300: struct sockaddr_in6 *sin6;
2301: struct sockaddr_in6 *s6;
2302: struct nd_pfxrouter *pfr;
2303:
2304: if (oldp && p + 1 <= pe)
2305: {
1.129 dyoung 2306: memset(p, 0, sizeof(*p));
1.65 itojun 2307: sin6 = (struct sockaddr_in6 *)(p + 1);
2308:
2309: p->prefix = pr->ndpr_prefix;
1.96 rpaulo 2310: if (sa6_recoverscope(&p->prefix)) {
1.65 itojun 2311: log(LOG_ERR,
2312: "scope error in prefix list (%s)\n",
2313: ip6_sprintf(&p->prefix.sin6_addr));
1.96 rpaulo 2314: /* XXX: press on... */
2315: }
1.65 itojun 2316: p->raflags = pr->ndpr_raf;
2317: p->prefixlen = pr->ndpr_plen;
2318: p->vltime = pr->ndpr_vltime;
2319: p->pltime = pr->ndpr_pltime;
2320: p->if_index = pr->ndpr_ifp->if_index;
2321: if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
2322: p->expire = 0;
2323: else {
2324: time_t maxexpire;
2325:
2326: /* XXX: we assume time_t is signed. */
2327: maxexpire = (-1) &
1.99 rpaulo 2328: ~((time_t)1 <<
2329: ((sizeof(maxexpire) * 8) - 1));
1.65 itojun 2330: if (pr->ndpr_vltime <
2331: maxexpire - pr->ndpr_lastupdate) {
2332: p->expire = pr->ndpr_lastupdate +
2333: pr->ndpr_vltime;
2334: } else
2335: p->expire = maxexpire;
2336: }
2337: p->refcnt = pr->ndpr_refcnt;
2338: p->flags = pr->ndpr_stateflags;
2339: p->origin = PR_ORIG_RA;
2340: advrtrs = 0;
1.108 dyoung 2341: LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
1.65 itojun 2342: if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
2343: advrtrs++;
2344: continue;
2345: }
2346: s6 = &sin6[advrtrs];
1.122 dyoung 2347: sockaddr_in6_init(s6, &pfr->router->rtaddr,
2348: 0, 0, 0);
1.96 rpaulo 2349: if (sa6_recoverscope(s6)) {
2350: log(LOG_ERR,
2351: "scope error in "
2352: "prefix list (%s)\n",
2353: ip6_sprintf(&pfr->router->rtaddr));
2354: }
1.65 itojun 2355: advrtrs++;
2356: }
2357: p->advrtrs = advrtrs;
2358: }
2359: else {
2360: advrtrs = 0;
1.108 dyoung 2361: LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
1.65 itojun 2362: advrtrs++;
2363: }
2364:
2365: advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
2366: l += advance;
2367: if (p)
1.111 christos 2368: p = (struct in6_prefix *)((char *)p + advance);
1.65 itojun 2369: }
2370:
2371: if (oldp) {
1.111 christos 2372: *oldlenp = l; /* (void *)d - (void *)oldp */
1.65 itojun 2373: if (l > ol)
2374: error = ENOMEM;
2375: } else
2376: *oldlenp = l;
2377:
2378: splx(s);
2379:
1.112 dyoung 2380: return error;
1.2 itojun 2381: }
CVSweb <webmaster@jp.NetBSD.org>