Annotation of src/sys/netinet6/nd6_rtr.c, Revision 1.142
1.142 ! maxv 1: /* $NetBSD: nd6_rtr.c,v 1.141 2018/05/01 07:21:39 maxv Exp $ */
1.20 itojun 2: /* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
1.3 thorpej 3:
1.2 itojun 4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
1.16 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.16 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: */
1.27 lukem 32:
33: #include <sys/cdefs.h>
1.142 ! maxv 34: __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.141 2018/05/01 07:21:39 maxv Exp $");
1.134 msaitoh 35:
36: #ifdef _KERNEL_OPT
37: #include "opt_net_mpsafe.h"
38: #endif
1.2 itojun 39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/malloc.h>
43: #include <sys/mbuf.h>
44: #include <sys/socket.h>
45: #include <sys/sockio.h>
46: #include <sys/time.h>
47: #include <sys/kernel.h>
48: #include <sys/errno.h>
49: #include <sys/ioctl.h>
50: #include <sys/syslog.h>
1.82 tls 51: #include <sys/cprng.h>
1.2 itojun 52:
53: #include <net/if.h>
54: #include <net/if_types.h>
55: #include <net/if_dl.h>
56:
57: #include <netinet/in.h>
58: #include <netinet6/in6_var.h>
1.56 rpaulo 59: #include <netinet6/in6_ifattach.h>
1.11 itojun 60: #include <netinet/ip6.h>
1.2 itojun 61: #include <netinet6/ip6_var.h>
62: #include <netinet6/nd6.h>
1.11 itojun 63: #include <netinet/icmp6.h>
1.75 thorpej 64: #include <netinet6/icmp6_private.h>
1.54 rpaulo 65: #include <netinet6/scope6_var.h>
1.2 itojun 66:
1.68 dyoung 67: static int rtpref(struct nd_defrouter *);
68: static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
69: static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
70: struct mbuf *, int);
1.118 ozaki-r 71: static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int, struct psref *);
1.68 dyoung 72: static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *,
73: struct nd_defrouter *);
74: static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
75: static void pfxrtr_del(struct nd_pfxrouter *);
1.32 itojun 76: static struct nd_pfxrouter *find_pfxlist_reachable_router
1.68 dyoung 77: (struct nd_prefix *);
1.121 ozaki-r 78:
79: static void defrouter_addreq(struct nd_defrouter *);
1.68 dyoung 80: static void defrouter_delreq(struct nd_defrouter *);
81:
82: static int in6_init_prefix_ltimes(struct nd_prefix *);
1.83 christos 83: static void in6_init_address_ltimes(struct nd_prefix *,
84: struct in6_addrlifetime *);
85: static void purge_detached(struct ifnet *);
1.2 itojun 86:
1.120 ozaki-r 87: static int rt6_deleteroute_matcher(struct rtentry *, void *);
1.2 itojun 88:
1.121 ozaki-r 89: static int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *,
90: struct nd_prefix **);
91: static int nd6_prefix_onlink(struct nd_prefix *);
92: static int nd6_prefix_offlink(struct nd_prefix *);
93: static struct nd_prefix *nd6_prefix_lookup(struct nd_prefixctl *);
94:
1.2 itojun 95: extern int nd6_recalc_reachtm_interval;
96:
1.56 rpaulo 97: int ip6_use_tempaddr = 0;
98:
99: int ip6_desync_factor;
100: u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
101: u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
102: int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
103:
1.81 spz 104: int nd6_numroutes = 0;
105:
1.56 rpaulo 106: /* RTPREF_MEDIUM has to be 0! */
107: #define RTPREF_HIGH 1
108: #define RTPREF_MEDIUM 0
109: #define RTPREF_LOW (-1)
110: #define RTPREF_RESERVED (-2)
111: #define RTPREF_INVALID (-3) /* internal */
112:
1.101 ozaki-r 113: static inline bool
114: nd6_is_llinfo_probreach(struct nd_defrouter *dr)
115: {
1.105 ozaki-r 116: struct llentry *ln = NULL;
1.101 ozaki-r 117:
1.108 ozaki-r 118: ln = nd6_lookup(&dr->rtaddr, dr->ifp, false);
119: if (ln == NULL)
1.101 ozaki-r 120: return false;
1.108 ozaki-r 121:
122: if (!ND6_IS_LLINFO_PROBREACH(ln)) {
123: LLE_RUNLOCK(ln);
1.101 ozaki-r 124: return false;
1.108 ozaki-r 125: }
1.101 ozaki-r 126:
1.108 ozaki-r 127: LLE_RUNLOCK(ln);
1.101 ozaki-r 128: return true;
129: }
130:
1.2 itojun 131: /*
132: * Receive Router Solicitation Message - just for routers.
1.81 spz 133: * Router solicitation/advertisement is mostly managed by a userland program
1.2 itojun 134: * (rtadvd) so here we have no function like nd6_ra_output().
135: *
136: * Based on RFC 2461
137: */
138: void
1.64 christos 139: nd6_rs_input(struct mbuf *m, int off, int icmp6len)
1.2 itojun 140: {
1.111 ozaki-r 141: struct ifnet *ifp;
142: struct nd_ifinfo *ndi;
1.2 itojun 143: struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.12 itojun 144: struct nd_router_solicit *nd_rs;
1.2 itojun 145: struct in6_addr saddr6 = ip6->ip6_src;
146: char *lladdr = NULL;
147: int lladdrlen = 0;
148: union nd_opts ndopts;
1.111 ozaki-r 149: struct psref psref;
1.130 ryo 150: char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1.111 ozaki-r 151:
152: ifp = m_get_rcvif_psref(m, &psref);
153: if (ifp == NULL)
154: goto freeit;
155:
156: ndi = ND_IFINFO(ifp);
1.2 itojun 157:
158: /* If I'm not a router, ignore it. */
1.80 dyoung 159: if (nd6_accepts_rtadv(ndi) || !ip6_forwarding)
1.12 itojun 160: goto freeit;
1.2 itojun 161:
162: /* Sanity checks */
163: if (ip6->ip6_hlim != 255) {
1.107 ozaki-r 164: nd6log(LOG_ERR, "invalid hlim (%d) from %s to %s on %s\n",
1.131 christos 165: ip6->ip6_hlim, IN6_PRINT(ip6bufs, &ip6->ip6_src),
166: IN6_PRINT(ip6bufd, &ip6->ip6_dst), if_name(ifp));
1.20 itojun 167: goto bad;
1.2 itojun 168: }
169:
170: /*
171: * Don't update the neighbor cache, if src = ::.
172: * This indicates that the src has no IP address assigned yet.
173: */
174: if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
1.12 itojun 175: goto freeit;
176:
177: IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
178: if (nd_rs == NULL) {
1.75 thorpej 179: ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
1.142 ! maxv 180: m_put_rcvif_psref(ifp, &psref);
1.2 itojun 181: return;
1.12 itojun 182: }
1.2 itojun 183:
184: icmp6len -= sizeof(*nd_rs);
185: nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
186: if (nd6_options(&ndopts) < 0) {
1.107 ozaki-r 187: nd6log(LOG_INFO, "invalid ND option, ignored\n");
1.20 itojun 188: /* nd6_options have incremented stats */
1.12 itojun 189: goto freeit;
1.2 itojun 190: }
191:
192: if (ndopts.nd_opts_src_lladdr) {
193: lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
194: lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
195: }
196:
197: if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1.107 ozaki-r 198: nd6log(LOG_INFO, "lladdrlen mismatch for %s "
1.2 itojun 199: "(if %d, RS packet %d)\n",
1.131 christos 200: IN6_PRINT(ip6bufs, &saddr6),
1.130 ryo 201: ifp->if_addrlen, lladdrlen - 2);
1.20 itojun 202: goto bad;
1.2 itojun 203: }
204:
1.6 itojun 205: nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
1.12 itojun 206:
207: freeit:
1.111 ozaki-r 208: m_put_rcvif_psref(ifp, &psref);
1.12 itojun 209: m_freem(m);
1.20 itojun 210: return;
211:
212: bad:
1.75 thorpej 213: ICMP6_STATINC(ICMP6_STAT_BADRS);
1.111 ozaki-r 214: m_put_rcvif_psref(ifp, &psref);
1.20 itojun 215: m_freem(m);
1.2 itojun 216: }
217:
218: /*
219: * Receive Router Advertisement Message.
220: *
221: * Based on RFC 2461
222: * TODO: on-link bit on prefix information
223: * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
224: */
225: void
1.64 christos 226: nd6_ra_input(struct mbuf *m, int off, int icmp6len)
1.2 itojun 227: {
1.111 ozaki-r 228: struct ifnet *ifp;
229: struct nd_ifinfo *ndi;
1.2 itojun 230: struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.12 itojun 231: struct nd_router_advert *nd_ra;
1.2 itojun 232: struct in6_addr saddr6 = ip6->ip6_src;
233: #if 0
234: struct in6_addr daddr6 = ip6->ip6_dst;
1.12 itojun 235: int flags; /* = nd_ra->nd_ra_flags_reserved; */
1.2 itojun 236: int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
237: int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
238: #endif
1.56 rpaulo 239: int mcast = 0;
1.2 itojun 240: union nd_opts ndopts;
241: struct nd_defrouter *dr;
1.111 ozaki-r 242: struct psref psref;
1.130 ryo 243: char ip6buf[INET6_ADDRSTRLEN], ip6buf2[INET6_ADDRSTRLEN];
1.111 ozaki-r 244:
245: ifp = m_get_rcvif_psref(m, &psref);
246: if (ifp == NULL)
247: goto freeit;
1.2 itojun 248:
1.111 ozaki-r 249: ndi = ND_IFINFO(ifp);
1.32 itojun 250: /*
1.81 spz 251: * We only accept RAs when
252: * the system-wide variable allows the acceptance, and the
1.33 itojun 253: * per-interface variable allows RAs on the receiving interface.
1.32 itojun 254: */
1.80 dyoung 255: if (!nd6_accepts_rtadv(ndi))
1.32 itojun 256: goto freeit;
1.2 itojun 257:
258: if (ip6->ip6_hlim != 255) {
1.107 ozaki-r 259: nd6log(LOG_ERR, "invalid hlim (%d) from %s to %s on %s\n",
1.131 christos 260: ip6->ip6_hlim, IN6_PRINT(ip6buf, &ip6->ip6_src),
261: IN6_PRINT(ip6buf2, &ip6->ip6_dst), if_name(ifp));
1.20 itojun 262: goto bad;
1.2 itojun 263: }
264:
265: if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
1.107 ozaki-r 266: nd6log(LOG_ERR, "src %s is not link-local\n",
1.131 christos 267: IN6_PRINT(ip6buf, &saddr6));
1.20 itojun 268: goto bad;
1.12 itojun 269: }
270:
271: IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
272: if (nd_ra == NULL) {
1.75 thorpej 273: ICMP6_STATINC(ICMP6_STAT_TOOSHORT);
1.111 ozaki-r 274: m_put_rcvif_psref(ifp, &psref);
1.2 itojun 275: return;
276: }
277:
278: icmp6len -= sizeof(*nd_ra);
279: nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
280: if (nd6_options(&ndopts) < 0) {
1.107 ozaki-r 281: nd6log(LOG_INFO, "invalid ND option, ignored\n");
1.20 itojun 282: /* nd6_options have incremented stats */
1.12 itojun 283: goto freeit;
1.2 itojun 284: }
285:
286: {
1.52 christos 287: struct nd_defrouter drtr;
1.2 itojun 288: u_int32_t advreachable = nd_ra->nd_ra_reachable;
289:
1.56 rpaulo 290: /* remember if this is a multicasted advertisement */
291: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
292: mcast = 1;
293:
294: memset(&drtr, 0, sizeof(drtr));
1.52 christos 295: drtr.rtaddr = saddr6;
296: drtr.flags = nd_ra->nd_ra_flags_reserved;
1.58 rpaulo 297: drtr.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
1.102 ozaki-r 298: drtr.expire = time_uptime + drtr.rtlifetime;
1.52 christos 299: drtr.ifp = ifp;
1.2 itojun 300: /* unspecified or not? (RFC 2461 6.3.4) */
301: if (advreachable) {
302: NTOHL(advreachable);
303: if (advreachable <= MAX_REACHABLE_TIME &&
304: ndi->basereachable != advreachable) {
305: ndi->basereachable = advreachable;
306: ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
307: ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
308: }
309: }
310: if (nd_ra->nd_ra_retransmit)
311: ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
1.99 roy 312: if (nd_ra->nd_ra_curhoplimit) {
313: if (ndi->chlim < nd_ra->nd_ra_curhoplimit)
314: ndi->chlim = nd_ra->nd_ra_curhoplimit;
315: else if (ndi->chlim != nd_ra->nd_ra_curhoplimit)
316: log(LOG_ERR, "nd_ra_input: lower CurHopLimit sent from "
317: "%s on %s (current=%d, received=%d), ignored\n",
1.131 christos 318: IN6_PRINT(ip6buf, &ip6->ip6_src),
1.99 roy 319: if_name(ifp), ndi->chlim, nd_ra->nd_ra_curhoplimit);
320: }
1.136 ozaki-r 321: IFNET_LOCK(ifp);
1.128 ozaki-r 322: ND6_WLOCK();
1.52 christos 323: dr = defrtrlist_update(&drtr);
1.2 itojun 324: }
325:
326: /*
327: * prefix
328: */
329: if (ndopts.nd_opts_pi) {
330: struct nd_opt_hdr *pt;
1.32 itojun 331: struct nd_opt_prefix_info *pi = NULL;
1.94 matt 332: struct nd_prefixctl prc;
1.2 itojun 333:
334: for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
335: pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
1.63 christos 336: pt = (struct nd_opt_hdr *)((char *)pt +
1.2 itojun 337: (pt->nd_opt_len << 3))) {
338: if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
339: continue;
340: pi = (struct nd_opt_prefix_info *)pt;
341:
342: if (pi->nd_opt_pi_len != 4) {
1.107 ozaki-r 343: nd6log(LOG_INFO, "invalid option "
1.22 itojun 344: "len %d for prefix information option, "
1.107 ozaki-r 345: "ignored\n", pi->nd_opt_pi_len);
1.2 itojun 346: continue;
347: }
348:
349: if (128 < pi->nd_opt_pi_prefix_len) {
1.107 ozaki-r 350: nd6log(LOG_INFO, "invalid prefix "
1.22 itojun 351: "len %d for prefix information option, "
1.107 ozaki-r 352: "ignored\n", pi->nd_opt_pi_prefix_len);
1.2 itojun 353: continue;
354: }
355:
356: if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
357: || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
1.107 ozaki-r 358: nd6log(LOG_INFO,
359: "invalid prefix %s, ignored\n",
1.131 christos 360: IN6_PRINT(ip6buf, &pi->nd_opt_pi_prefix));
1.2 itojun 361: continue;
362: }
363:
1.94 matt 364: memset(&prc, 0, sizeof(prc));
365: sockaddr_in6_init(&prc.ndprc_prefix,
1.69 dyoung 366: &pi->nd_opt_pi_prefix, 0, 0, 0);
1.111 ozaki-r 367: prc.ndprc_ifp = ifp;
1.2 itojun 368:
1.94 matt 369: prc.ndprc_raf_onlink = (pi->nd_opt_pi_flags_reserved &
1.56 rpaulo 370: ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
1.94 matt 371: prc.ndprc_raf_auto = (pi->nd_opt_pi_flags_reserved &
1.56 rpaulo 372: ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
1.94 matt 373: prc.ndprc_plen = pi->nd_opt_pi_prefix_len;
374: prc.ndprc_vltime = ntohl(pi->nd_opt_pi_valid_time);
375: prc.ndprc_pltime = ntohl(pi->nd_opt_pi_preferred_time);
1.2 itojun 376:
1.94 matt 377: (void)prelist_update(&prc, dr, m, mcast);
1.2 itojun 378: }
379: }
1.128 ozaki-r 380: ND6_UNLOCK();
1.136 ozaki-r 381: IFNET_UNLOCK(ifp);
1.2 itojun 382:
383: /*
384: * MTU
385: */
386: if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
1.32 itojun 387: u_long mtu;
1.30 itojun 388: u_long maxmtu;
1.2 itojun 389:
1.32 itojun 390: mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
391:
1.2 itojun 392: /* lower bound */
393: if (mtu < IPV6_MMTU) {
1.107 ozaki-r 394: nd6log(LOG_INFO, "bogus mtu option "
1.32 itojun 395: "mtu=%lu sent from %s, ignoring\n",
1.131 christos 396: mtu, IN6_PRINT(ip6buf, &ip6->ip6_src));
1.2 itojun 397: goto skip;
398: }
399:
400: /* upper bound */
1.30 itojun 401: maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
402: ? ndi->maxmtu : ifp->if_mtu;
403: if (mtu <= maxmtu) {
404: int change = (ndi->linkmtu != mtu);
405:
406: ndi->linkmtu = mtu;
407: if (change) /* in6_maxmtu may change */
408: in6_setmaxmtu();
1.2 itojun 409: } else {
1.107 ozaki-r 410: nd6log(LOG_INFO,
411: "bogus mtu mtu=%lu sent from %s; "
1.30 itojun 412: "exceeds maxmtu %lu, ignoring\n",
1.131 christos 413: mtu, IN6_PRINT(ip6buf, &ip6->ip6_src), maxmtu);
1.2 itojun 414: }
415: }
416:
417: skip:
1.33 itojun 418:
1.2 itojun 419: /*
1.26 itojun 420: * Source link layer address
1.2 itojun 421: */
422: {
423: char *lladdr = NULL;
424: int lladdrlen = 0;
1.33 itojun 425:
1.2 itojun 426: if (ndopts.nd_opts_src_lladdr) {
427: lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
428: lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
429: }
430:
431: if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
1.107 ozaki-r 432: nd6log(LOG_INFO, "lladdrlen mismatch for %s "
1.131 christos 433: "(if %d, RA packet %d)\n", IN6_PRINT(ip6buf, &saddr6),
1.107 ozaki-r 434: ifp->if_addrlen, lladdrlen - 2);
1.20 itojun 435: goto bad;
1.2 itojun 436: }
437:
1.6 itojun 438: nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
1.7 itojun 439:
440: /*
441: * Installing a link-layer address might change the state of the
442: * router's neighbor cache, which might also affect our on-link
443: * detection of adveritsed prefixes.
444: */
1.128 ozaki-r 445: ND6_WLOCK();
1.123 ozaki-r 446: nd6_pfxlist_onlink_check();
1.128 ozaki-r 447: ND6_UNLOCK();
1.2 itojun 448: }
1.12 itojun 449:
1.20 itojun 450: freeit:
1.111 ozaki-r 451: m_put_rcvif_psref(ifp, &psref);
1.20 itojun 452: m_freem(m);
453: return;
454:
455: bad:
1.75 thorpej 456: ICMP6_STATINC(ICMP6_STAT_BADRA);
1.111 ozaki-r 457: m_put_rcvif_psref(ifp, &psref);
1.12 itojun 458: m_freem(m);
1.2 itojun 459: }
460:
461: /*
1.45 wiz 462: * default router list processing sub routines
1.2 itojun 463: */
1.121 ozaki-r 464: static void
1.94 matt 465: defrouter_addreq(struct nd_defrouter *newdr)
1.2 itojun 466: {
1.76 dyoung 467: union {
468: struct sockaddr_in6 sin6;
469: struct sockaddr sa;
470: } def, mask, gate;
1.138 ozaki-r 471: #ifndef NET_MPSAFE
1.137 ozaki-r 472: int s;
1.138 ozaki-r 473: #endif
1.32 itojun 474: int error;
1.2 itojun 475:
1.56 rpaulo 476: memset(&def, 0, sizeof(def));
477: memset(&mask, 0, sizeof(mask));
478: memset(&gate, 0,sizeof(gate)); /* for safety */
1.2 itojun 479:
1.76 dyoung 480: def.sin6.sin6_len = mask.sin6.sin6_len = gate.sin6.sin6_len =
1.32 itojun 481: sizeof(struct sockaddr_in6);
1.76 dyoung 482: def.sin6.sin6_family = mask.sin6.sin6_family = gate.sin6.sin6_family = AF_INET6;
1.94 matt 483: gate.sin6.sin6_addr = newdr->rtaddr;
1.32 itojun 484: #ifndef SCOPEDROUTING
1.76 dyoung 485: gate.sin6.sin6_scope_id = 0; /* XXX */
1.32 itojun 486: #endif
1.2 itojun 487:
1.138 ozaki-r 488: #ifndef NET_MPSAFE
1.137 ozaki-r 489: s = splsoftnet();
1.138 ozaki-r 490: #endif
1.101 ozaki-r 491: error = rtrequest_newmsg(RTM_ADD, &def.sa, &gate.sa, &mask.sa,
492: RTF_GATEWAY);
493: if (error == 0) {
1.81 spz 494: nd6_numroutes++;
1.101 ozaki-r 495: newdr->installed = 1;
1.32 itojun 496: }
1.138 ozaki-r 497: #ifndef NET_MPSAFE
1.137 ozaki-r 498: splx(s);
1.138 ozaki-r 499: #endif
1.2 itojun 500: return;
501: }
502:
503: struct nd_defrouter *
1.123 ozaki-r 504: nd6_defrouter_lookup(const struct in6_addr *addr, struct ifnet *ifp)
1.2 itojun 505: {
506: struct nd_defrouter *dr;
507:
1.128 ozaki-r 508: ND6_ASSERT_LOCK();
509:
1.124 ozaki-r 510: ND_DEFROUTER_LIST_FOREACH(dr) {
1.66 dyoung 511: if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
512: break;
1.7 itojun 513: }
1.2 itojun 514:
1.66 dyoung 515: return dr; /* search failed */
1.2 itojun 516: }
517:
518: void
1.123 ozaki-r 519: nd6_defrtrlist_del(struct nd_defrouter *dr, struct in6_ifextra *ext)
1.2 itojun 520: {
521: struct nd_defrouter *deldr = NULL;
522: struct nd_prefix *pr;
1.96 martin 523: struct nd_ifinfo *ndi;
524:
1.128 ozaki-r 525: ND6_ASSERT_WLOCK();
526:
1.96 martin 527: if (ext == NULL)
528: ext = dr->ifp->if_afdata[AF_INET6];
529:
530: /* detach already in progress, can not do anything */
531: if (ext == NULL)
532: return;
533:
534: ndi = ext->nd_ifinfo;
1.2 itojun 535:
536: /*
537: * Flush all the routing table entries that use the router
538: * as a next hop.
539: */
1.79 tonnerre 540: /* XXX: better condition? */
1.80 dyoung 541: if (!ip6_forwarding && nd6_accepts_rtadv(ndi))
1.123 ozaki-r 542: nd6_rt_flush(&dr->rtaddr, dr->ifp);
1.32 itojun 543:
544: if (dr->installed) {
545: deldr = dr;
546: defrouter_delreq(dr);
1.2 itojun 547: }
1.124 ozaki-r 548: ND_DEFROUTER_LIST_REMOVE(dr);
1.2 itojun 549:
550: /*
551: * Also delete all the pointers to the router in each prefix lists.
552: */
1.125 ozaki-r 553: ND_PREFIX_LIST_FOREACH(pr) {
1.2 itojun 554: struct nd_pfxrouter *pfxrtr;
555: if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
556: pfxrtr_del(pfxrtr);
557: }
1.123 ozaki-r 558: nd6_pfxlist_onlink_check();
1.2 itojun 559:
560: /*
1.7 itojun 561: * If the router is the primary one, choose a new one.
1.123 ozaki-r 562: * Note that nd6_defrouter_select() will remove the current gateway
1.7 itojun 563: * from the routing table.
1.2 itojun 564: */
565: if (deldr)
1.123 ozaki-r 566: nd6_defrouter_select();
1.7 itojun 567:
1.83 christos 568: ext->ndefrouters--;
569: if (ext->ndefrouters < 0) {
1.123 ozaki-r 570: log(LOG_WARNING, "nd6_defrtrlist_del: negative count on %s\n",
1.83 christos 571: dr->ifp->if_xname);
572: }
573:
1.2 itojun 574: free(dr, M_IP6NDP);
575: }
576:
1.7 itojun 577: /*
1.32 itojun 578: * Remove the default route for a given router.
1.123 ozaki-r 579: * This is just a subroutine function for nd6_defrouter_select(), and should
1.32 itojun 580: * not be called from anywhere else.
581: */
582: static void
1.64 christos 583: defrouter_delreq(struct nd_defrouter *dr)
1.32 itojun 584: {
1.76 dyoung 585: union {
586: struct sockaddr_in6 sin6;
587: struct sockaddr sa;
588: } def, mask, gw;
1.101 ozaki-r 589: int error;
1.32 itojun 590:
1.76 dyoung 591: memset(&def, 0, sizeof(def));
592: memset(&mask, 0, sizeof(mask));
593: memset(&gw, 0, sizeof(gw)); /* for safety */
1.32 itojun 594:
1.76 dyoung 595: def.sin6.sin6_len = mask.sin6.sin6_len = gw.sin6.sin6_len =
1.32 itojun 596: sizeof(struct sockaddr_in6);
1.76 dyoung 597: def.sin6.sin6_family = mask.sin6.sin6_family = gw.sin6.sin6_family = AF_INET6;
598: gw.sin6.sin6_addr = dr->rtaddr;
1.32 itojun 599: #ifndef SCOPEDROUTING
1.76 dyoung 600: gw.sin6.sin6_scope_id = 0; /* XXX */
1.32 itojun 601: #endif
602:
1.101 ozaki-r 603: error = rtrequest_newmsg(RTM_DELETE, &def.sa, &gw.sa, &mask.sa,
604: RTF_GATEWAY);
605: if (error == 0)
1.100 ozaki-r 606: nd6_numroutes--;
1.32 itojun 607:
1.35 itojun 608: dr->installed = 0;
1.32 itojun 609: }
610:
611: /*
612: * remove all default routes from default router list
613: */
614: void
1.123 ozaki-r 615: nd6_defrouter_reset(void)
1.32 itojun 616: {
617: struct nd_defrouter *dr;
618:
1.128 ozaki-r 619: ND6_ASSERT_WLOCK();
620:
1.124 ozaki-r 621: ND_DEFROUTER_LIST_FOREACH(dr)
1.32 itojun 622: defrouter_delreq(dr);
623:
624: /*
625: * XXX should we also nuke any default routers in the kernel, by
626: * going through them by rtalloc1()?
627: */
628: }
629:
630: /*
631: * Default Router Selection according to Section 6.3.6 of RFC 2461 and
632: * draft-ietf-ipngwg-router-selection:
633: * 1) Routers that are reachable or probably reachable should be preferred.
634: * If we have more than one (probably) reachable router, prefer ones
635: * with the highest router preference.
1.7 itojun 636: * 2) When no routers on the list are known to be reachable or
637: * probably reachable, routers SHOULD be selected in a round-robin
1.32 itojun 638: * fashion, regardless of router preference values.
1.7 itojun 639: * 3) If the Default Router List is empty, assume that all
640: * destinations are on-link.
1.32 itojun 641: *
642: * We assume nd_defrouter is sorted by router preference value.
643: * Since the code below covers both with and without router preference cases,
644: * we do not need to classify the cases by ifdef.
645: *
646: * At this moment, we do not try to install more than one default router,
647: * even when the multipath routing is available, because we're not sure about
648: * the benefits for stub hosts comparing to the risk of making the code
649: * complicated and the possibility of introducing bugs.
1.7 itojun 650: */
651: void
1.123 ozaki-r 652: nd6_defrouter_select(void)
1.7 itojun 653: {
1.79 tonnerre 654: struct nd_ifinfo *ndi;
1.32 itojun 655: struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
1.7 itojun 656:
1.128 ozaki-r 657: ND6_ASSERT_WLOCK();
658:
1.7 itojun 659: /*
1.32 itojun 660: * This function should be called only when acting as an autoconfigured
661: * host. Although the remaining part of this function is not effective
662: * if the node is not an autoconfigured host, we explicitly exclude
663: * such cases here for safety.
1.7 itojun 664: */
1.79 tonnerre 665: if (ip6_forwarding) {
1.107 ozaki-r 666: nd6log(LOG_WARNING, "called unexpectedly (forwarding=%d, "
667: "accept_rtadv=%d)\n", ip6_forwarding, ip6_accept_rtadv);
1.32 itojun 668: return;
1.7 itojun 669: }
670:
1.32 itojun 671: /*
672: * Let's handle easy case (3) first:
1.49 itojun 673: * If default router list is empty, there's nothing to be done.
1.32 itojun 674: */
1.128 ozaki-r 675: if (ND_DEFROUTER_LIST_EMPTY())
1.32 itojun 676: return;
677:
678: /*
679: * Search for a (probably) reachable router from the list.
680: * We just pick up the first reachable one (if any), assuming that
681: * the ordering rule of the list described in defrtrlist_update().
682: */
1.124 ozaki-r 683: ND_DEFROUTER_LIST_FOREACH(dr) {
1.79 tonnerre 684: ndi = ND_IFINFO(dr->ifp);
1.80 dyoung 685: if (nd6_accepts_rtadv(ndi))
1.79 tonnerre 686: continue;
687:
1.56 rpaulo 688: if (selected_dr == NULL &&
1.101 ozaki-r 689: nd6_is_llinfo_probreach(dr))
1.32 itojun 690: selected_dr = dr;
691:
692: if (dr->installed && !installed_dr)
693: installed_dr = dr;
694: else if (dr->installed && installed_dr) {
695: /* this should not happen. warn for diagnosis. */
1.123 ozaki-r 696: log(LOG_ERR, "nd6_defrouter_select: more than one router"
1.32 itojun 697: " is installed\n");
698: }
699: }
700: /*
701: * If none of the default routers was found to be reachable,
702: * round-robin the list regardless of preference.
703: * Otherwise, if we have an installed router, check if the selected
704: * (reachable) router should really be preferred to the installed one.
705: * We only prefer the new router when the old one is not reachable
706: * or when the new one has a really higher preference value.
707: */
1.56 rpaulo 708: if (selected_dr == NULL) {
1.124 ozaki-r 709: if (installed_dr == NULL ||
710: ND_DEFROUTER_LIST_NEXT(installed_dr) == NULL)
711: selected_dr = ND_DEFROUTER_LIST_FIRST();
1.32 itojun 712: else
1.124 ozaki-r 713: selected_dr = ND_DEFROUTER_LIST_NEXT(installed_dr);
1.32 itojun 714: } else if (installed_dr &&
1.101 ozaki-r 715: nd6_is_llinfo_probreach(installed_dr) &&
1.32 itojun 716: rtpref(selected_dr) <= rtpref(installed_dr)) {
717: selected_dr = installed_dr;
718: }
719:
720: /*
721: * If the selected router is different than the installed one,
722: * remove the installed router and install the selected one.
723: * Note that the selected router is never NULL here.
724: */
725: if (installed_dr != selected_dr) {
726: if (installed_dr)
727: defrouter_delreq(installed_dr);
728: defrouter_addreq(selected_dr);
1.7 itojun 729: }
730:
731: return;
732: }
733:
1.32 itojun 734: /*
735: * for default router selection
736: * regards router-preference field as a 2-bit signed integer
737: */
738: static int
739: rtpref(struct nd_defrouter *dr)
740: {
741: switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
742: case ND_RA_FLAG_RTPREF_HIGH:
1.56 rpaulo 743: return (RTPREF_HIGH);
1.32 itojun 744: case ND_RA_FLAG_RTPREF_MEDIUM:
1.58 rpaulo 745: case ND_RA_FLAG_RTPREF_RSV:
1.56 rpaulo 746: return (RTPREF_MEDIUM);
1.32 itojun 747: case ND_RA_FLAG_RTPREF_LOW:
1.56 rpaulo 748: return (RTPREF_LOW);
1.32 itojun 749: default:
750: /*
751: * This case should never happen. If it did, it would mean a
752: * serious bug of kernel internal. We thus always bark here.
753: * Or, can we even panic?
754: */
1.56 rpaulo 755: log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
756: return (RTPREF_INVALID);
1.32 itojun 757: }
758: /* NOTREACHED */
759: }
760:
1.2 itojun 761: static struct nd_defrouter *
1.94 matt 762: defrtrlist_update(struct nd_defrouter *newdr)
1.2 itojun 763: {
1.127 ozaki-r 764: struct nd_defrouter *dr, *n, *ret = NULL;
1.94 matt 765: struct in6_ifextra *ext = newdr->ifp->if_afdata[AF_INET6];
1.128 ozaki-r 766:
767: ND6_ASSERT_WLOCK();
1.2 itojun 768:
1.123 ozaki-r 769: if ((dr = nd6_defrouter_lookup(&newdr->rtaddr, newdr->ifp)) != NULL) {
1.2 itojun 770: /* entry exists */
1.94 matt 771: if (newdr->rtlifetime == 0) {
1.123 ozaki-r 772: nd6_defrtrlist_del(dr, ext);
1.2 itojun 773: dr = NULL;
774: } else {
1.32 itojun 775: int oldpref = rtpref(dr);
776:
1.2 itojun 777: /* override */
1.94 matt 778: dr->flags = newdr->flags; /* xxx flag check */
779: dr->rtlifetime = newdr->rtlifetime;
780: dr->expire = newdr->expire;
1.32 itojun 781:
782: /*
783: * If the preference does not change, there's no need
784: * to sort the entries.
785: */
1.94 matt 786: if (rtpref(newdr) == oldpref) {
1.127 ozaki-r 787: ret = dr;
788: goto out;
1.32 itojun 789: }
790:
791: /*
792: * preferred router may be changed, so relocate
793: * this router.
794: * XXX: calling TAILQ_REMOVE directly is a bad manner.
1.123 ozaki-r 795: * However, since nd6_defrtrlist_del() has many side
1.32 itojun 796: * effects, we intentionally do so here.
1.123 ozaki-r 797: * nd6_defrouter_select() below will handle routing
1.32 itojun 798: * changes later.
799: */
1.124 ozaki-r 800: ND_DEFROUTER_LIST_REMOVE(dr);
1.32 itojun 801: n = dr;
802: goto insert;
1.2 itojun 803: }
1.127 ozaki-r 804: ret = dr;
805: goto out;
1.2 itojun 806: }
807:
1.127 ozaki-r 808: if (ip6_maxifdefrouters >= 0 && ext->ndefrouters >= ip6_maxifdefrouters)
809: goto out;
1.83 christos 810:
1.2 itojun 811: /* entry does not exist */
1.127 ozaki-r 812: if (newdr->rtlifetime == 0)
813: goto out;
1.2 itojun 814:
1.81 spz 815: if (ip6_rtadv_maxroutes <= nd6_numroutes) {
816: ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
1.127 ozaki-r 817: goto out;
1.81 spz 818: }
819:
1.2 itojun 820: n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
1.127 ozaki-r 821: if (n == NULL)
822: goto out;
1.78 cegger 823: memset(n, 0, sizeof(*n));
1.94 matt 824: *n = *newdr;
1.7 itojun 825:
1.32 itojun 826: insert:
1.7 itojun 827: /*
1.32 itojun 828: * Insert the new router in the Default Router List;
829: * The Default Router List should be in the descending order
830: * of router-preferece. Routers with the same preference are
831: * sorted in the arriving time order.
1.7 itojun 832: */
1.32 itojun 833:
834: /* insert at the end of the group */
1.124 ozaki-r 835: ND_DEFROUTER_LIST_FOREACH(dr) {
1.32 itojun 836: if (rtpref(n) > rtpref(dr))
837: break;
838: }
839: if (dr)
1.124 ozaki-r 840: ND_DEFROUTER_LIST_INSERT_BEFORE(dr, n);
1.32 itojun 841: else
1.124 ozaki-r 842: ND_DEFROUTER_LIST_INSERT_TAIL(n);
1.32 itojun 843:
1.123 ozaki-r 844: nd6_defrouter_select();
1.32 itojun 845:
1.83 christos 846: ext->ndefrouters++;
847:
1.127 ozaki-r 848: ret = n;
849: out:
850: return ret;
1.2 itojun 851: }
852:
853: static struct nd_pfxrouter *
1.64 christos 854: pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
1.2 itojun 855: {
856: struct nd_pfxrouter *search;
1.33 itojun 857:
1.128 ozaki-r 858: ND6_ASSERT_LOCK();
859:
1.62 dyoung 860: LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
1.2 itojun 861: if (search->router == dr)
862: break;
863: }
864:
1.36 itojun 865: return (search);
1.2 itojun 866: }
867:
868: static void
1.64 christos 869: pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
1.2 itojun 870: {
1.94 matt 871: struct nd_pfxrouter *newpfr;
1.2 itojun 872:
1.128 ozaki-r 873: ND6_ASSERT_WLOCK();
874:
1.94 matt 875: newpfr = malloc(sizeof(*newpfr), M_IP6NDP, M_NOWAIT|M_ZERO);
876: if (newpfr == NULL)
1.2 itojun 877: return;
1.94 matt 878: newpfr->router = dr;
1.2 itojun 879:
1.94 matt 880: LIST_INSERT_HEAD(&pr->ndpr_advrtrs, newpfr, pfr_entry);
1.2 itojun 881:
1.123 ozaki-r 882: nd6_pfxlist_onlink_check();
1.2 itojun 883: }
884:
885: static void
1.64 christos 886: pfxrtr_del(struct nd_pfxrouter *pfr)
1.2 itojun 887: {
888: LIST_REMOVE(pfr, pfr_entry);
889: free(pfr, M_IP6NDP);
890: }
891:
1.121 ozaki-r 892: static struct nd_prefix *
1.64 christos 893: nd6_prefix_lookup(struct nd_prefixctl *key)
1.2 itojun 894: {
895: struct nd_prefix *search;
896:
1.125 ozaki-r 897: ND_PREFIX_LIST_FOREACH(search) {
1.94 matt 898: if (key->ndprc_ifp == search->ndpr_ifp &&
899: key->ndprc_plen == search->ndpr_plen &&
900: in6_are_prefix_equal(&key->ndprc_prefix.sin6_addr,
901: &search->ndpr_prefix.sin6_addr, key->ndprc_plen)) {
1.2 itojun 902: break;
903: }
904: }
905:
1.36 itojun 906: return (search);
1.2 itojun 907: }
908:
1.83 christos 909: static void
910: purge_detached(struct ifnet *ifp)
911: {
912: struct nd_prefix *pr, *pr_next;
913: struct in6_ifaddr *ia;
1.93 ozaki-r 914: struct ifaddr *ifa, *ifa_next;
1.83 christos 915:
1.128 ozaki-r 916: restart:
917: ND6_ASSERT_WLOCK();
918:
1.126 ozaki-r 919: ND_PREFIX_LIST_FOREACH_SAFE(pr, pr_next) {
1.118 ozaki-r 920: int s;
1.83 christos 921:
922: /*
923: * This function is called when we need to make more room for
924: * new prefixes rather than keeping old, possibly stale ones.
925: * Detached prefixes would be a good candidate; if all routers
926: * that advertised the prefix expired, the prefix is also
927: * probably stale.
928: */
929: if (pr->ndpr_ifp != ifp ||
930: IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
931: ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
932: !LIST_EMPTY(&pr->ndpr_advrtrs)))
933: continue;
934:
1.118 ozaki-r 935: s = pserialize_read_enter();
1.115 ozaki-r 936: for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = ifa_next) {
937: ifa_next = IFADDR_READER_NEXT(ifa);
1.83 christos 938: if (ifa->ifa_addr->sa_family != AF_INET6)
939: continue;
940: ia = (struct in6_ifaddr *)ifa;
941: if ((ia->ia6_flags & IN6_IFF_AUTOCONF) ==
942: IN6_IFF_AUTOCONF && ia->ia6_ndpr == pr) {
1.118 ozaki-r 943: pserialize_read_exit(s);
1.128 ozaki-r 944: ND6_UNLOCK();
945:
946: /* in6_purgeaddr may destroy pr. */
1.83 christos 947: in6_purgeaddr(ifa);
1.128 ozaki-r 948:
949: ND6_WLOCK();
1.118 ozaki-r 950: goto restart;
1.83 christos 951: }
952: }
1.118 ozaki-r 953: pserialize_read_exit(s);
954:
1.128 ozaki-r 955: KASSERT(pr->ndpr_refcnt == 0);
956: nd6_prelist_remove(pr);
1.83 christos 957: }
958: }
1.121 ozaki-r 959:
960: static int
1.94 matt 961: nd6_prelist_add(struct nd_prefixctl *prc, struct nd_defrouter *dr,
1.64 christos 962: struct nd_prefix **newp)
1.2 itojun 963: {
1.94 matt 964: struct nd_prefix *newpr = NULL;
1.138 ozaki-r 965: int i;
1.56 rpaulo 966: int error;
1.94 matt 967: struct in6_ifextra *ext = prc->ndprc_ifp->if_afdata[AF_INET6];
1.83 christos 968:
1.128 ozaki-r 969: ND6_ASSERT_WLOCK();
970:
1.83 christos 971: if (ip6_maxifprefixes >= 0) {
972: if (ext->nprefixes >= ip6_maxifprefixes / 2)
1.94 matt 973: purge_detached(prc->ndprc_ifp);
1.83 christos 974: if (ext->nprefixes >= ip6_maxifprefixes)
975: return ENOMEM;
976: }
1.2 itojun 977:
1.56 rpaulo 978: error = 0;
1.94 matt 979: newpr = malloc(sizeof(*newpr), M_IP6NDP, M_NOWAIT|M_ZERO);
980: if (newpr == NULL)
1.2 itojun 981: return ENOMEM;
1.94 matt 982: newpr->ndpr_ifp = prc->ndprc_ifp;
983: newpr->ndpr_prefix = prc->ndprc_prefix;
984: newpr->ndpr_plen = prc->ndprc_plen;
985: newpr->ndpr_vltime = prc->ndprc_vltime;
986: newpr->ndpr_pltime = prc->ndprc_pltime;
987: newpr->ndpr_flags = prc->ndprc_flags;
988: if ((error = in6_init_prefix_ltimes(newpr)) != 0) {
989: free(newpr, M_IP6NDP);
1.56 rpaulo 990: return(error);
991: }
1.102 ozaki-r 992: newpr->ndpr_lastupdate = time_uptime;
1.32 itojun 993: if (newp != NULL)
1.94 matt 994: *newp = newpr;
1.2 itojun 995:
1.55 rpaulo 996: /* initialization */
1.94 matt 997: LIST_INIT(&newpr->ndpr_advrtrs);
998: in6_prefixlen2mask(&newpr->ndpr_mask, newpr->ndpr_plen);
1.2 itojun 999: /* make prefix in the canonical form */
1.94 matt 1000: for (i = 0; i < 4; i++) {
1001: newpr->ndpr_prefix.sin6_addr.s6_addr32[i] &=
1002: newpr->ndpr_mask.s6_addr32[i];
1003: }
1.2 itojun 1004:
1005: /* link ndpr_entry to nd_prefix list */
1.125 ozaki-r 1006: ND_PREFIX_LIST_INSERT_HEAD(newpr);
1.2 itojun 1007:
1.32 itojun 1008: /* ND_OPT_PI_FLAG_ONLINK processing */
1.94 matt 1009: if (newpr->ndpr_raf_onlink) {
1.32 itojun 1010: int e;
1011:
1.94 matt 1012: if ((e = nd6_prefix_onlink(newpr)) != 0) {
1.130 ryo 1013: char ip6buf[INET6_ADDRSTRLEN];
1.107 ozaki-r 1014: nd6log(LOG_ERR, "failed to make "
1.32 itojun 1015: "the prefix %s/%d on-link on %s (errno=%d)\n",
1.131 christos 1016: IN6_PRINT(ip6buf, &prc->ndprc_prefix.sin6_addr),
1.107 ozaki-r 1017: prc->ndprc_plen, if_name(prc->ndprc_ifp), e);
1.32 itojun 1018: /* proceed anyway. XXX: is it correct? */
1019: }
1020: }
1021:
1.2 itojun 1022: if (dr)
1.94 matt 1023: pfxrtr_add(newpr, dr);
1.2 itojun 1024:
1.83 christos 1025: ext->nprefixes++;
1026:
1.2 itojun 1027: return 0;
1028: }
1029:
1030: void
1.128 ozaki-r 1031: nd6_prefix_unref(struct nd_prefix *pr)
1032: {
1033:
1034: ND6_WLOCK();
1035: pr->ndpr_refcnt--;
1036: if (pr->ndpr_refcnt == 0)
1037: nd6_prelist_remove(pr);
1038: ND6_UNLOCK();
1039: }
1040:
1041: void
1.132 ozaki-r 1042: nd6_invalidate_prefix(struct nd_prefix *pr)
1.2 itojun 1043: {
1.132 ozaki-r 1044: int e;
1.32 itojun 1045:
1.128 ozaki-r 1046: ND6_ASSERT_WLOCK();
1047:
1.32 itojun 1048: /* make sure to invalidate the prefix until it is really freed. */
1049: pr->ndpr_vltime = 0;
1050: pr->ndpr_pltime = 0;
1051: #if 0
1052: /*
1053: * Though these flags are now meaningless, we'd rather keep the value
1054: * not to confuse users when executing "ndp -p".
1055: */
1056: pr->ndpr_raf_onlink = 0;
1057: pr->ndpr_raf_auto = 0;
1058: #endif
1059: if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
1060: (e = nd6_prefix_offlink(pr)) != 0) {
1.130 ryo 1061: char ip6buf[INET6_ADDRSTRLEN];
1.107 ozaki-r 1062: nd6log(LOG_ERR,
1063: "failed to make %s/%d offlink on %s, errno=%d\n",
1.131 christos 1064: IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.107 ozaki-r 1065: pr->ndpr_plen, if_name(pr->ndpr_ifp), e);
1.32 itojun 1066: /* what should we do? */
1067: }
1.132 ozaki-r 1068: }
1069:
1070: void
1071: nd6_prelist_remove(struct nd_prefix *pr)
1072: {
1073: struct nd_pfxrouter *pfr, *next;
1074: struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
1075:
1076: ND6_ASSERT_WLOCK();
1077: KASSERT(pr->ndpr_refcnt == 0);
1078:
1079: nd6_invalidate_prefix(pr);
1.32 itojun 1080:
1.2 itojun 1081: /* unlink ndpr_entry from nd_prefix list */
1.125 ozaki-r 1082: ND_PREFIX_LIST_REMOVE(pr);
1.2 itojun 1083:
1084: /* free list of routers that adversed the prefix */
1.62 dyoung 1085: for (pfr = LIST_FIRST(&pr->ndpr_advrtrs); pfr != NULL; pfr = next) {
1086: next = LIST_NEXT(pfr, pfr_entry);
1.2 itojun 1087:
1088: free(pfr, M_IP6NDP);
1089: }
1.83 christos 1090:
1.86 christos 1091: if (ext) {
1092: ext->nprefixes--;
1093: if (ext->nprefixes < 0) {
1.123 ozaki-r 1094: log(LOG_WARNING, "nd6_prelist_remove: negative count on "
1.86 christos 1095: "%s\n", pr->ndpr_ifp->if_xname);
1096: }
1.83 christos 1097: }
1.21 itojun 1098:
1.2 itojun 1099: free(pr, M_IP6NDP);
1100:
1.123 ozaki-r 1101: nd6_pfxlist_onlink_check();
1.2 itojun 1102: }
1103:
1.56 rpaulo 1104: static int
1.94 matt 1105: prelist_update(struct nd_prefixctl *newprc,
1.64 christos 1106: struct nd_defrouter *dr, /* may be NULL */
1107: struct mbuf *m,
1108: int mcast)
1.2 itojun 1109: {
1.114 ozaki-r 1110: struct in6_ifaddr *ia6_match = NULL;
1.32 itojun 1111: struct ifaddr *ifa;
1.94 matt 1112: struct ifnet *ifp = newprc->ndprc_ifp;
1.2 itojun 1113: struct nd_prefix *pr;
1114: int error = 0;
1115: int auth;
1.32 itojun 1116: struct in6_addrlifetime lt6_tmp;
1.118 ozaki-r 1117: int ss;
1.130 ryo 1118: char ip6buf[INET6_ADDRSTRLEN];
1.2 itojun 1119:
1.140 maxv 1120: KASSERT(m != NULL);
1.128 ozaki-r 1121: ND6_ASSERT_WLOCK();
1122:
1.140 maxv 1123: auth = (m->m_flags & M_AUTHIPHDR) ? 1 : 0;
1.2 itojun 1124:
1.94 matt 1125: if ((pr = nd6_prefix_lookup(newprc)) != NULL) {
1.32 itojun 1126: /*
1.94 matt 1127: * nd6_prefix_lookup() ensures that pr and newprc have the same
1.32 itojun 1128: * prefix on a same interface.
1129: */
1130:
1131: /*
1132: * Update prefix information. Note that the on-link (L) bit
1133: * and the autonomous (A) bit should NOT be changed from 1
1134: * to 0.
1135: */
1.94 matt 1136: if (newprc->ndprc_raf_onlink == 1)
1.32 itojun 1137: pr->ndpr_raf_onlink = 1;
1.94 matt 1138: if (newprc->ndprc_raf_auto == 1)
1.32 itojun 1139: pr->ndpr_raf_auto = 1;
1.94 matt 1140: if (newprc->ndprc_raf_onlink) {
1141: pr->ndpr_vltime = newprc->ndprc_vltime;
1142: pr->ndpr_pltime = newprc->ndprc_pltime;
1.56 rpaulo 1143: (void)in6_init_prefix_ltimes(pr); /* XXX error case? */
1.102 ozaki-r 1144: pr->ndpr_lastupdate = time_uptime;
1.32 itojun 1145: }
1146:
1.94 matt 1147: if (newprc->ndprc_raf_onlink &&
1.32 itojun 1148: (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1149: int e;
1150:
1151: if ((e = nd6_prefix_onlink(pr)) != 0) {
1.107 ozaki-r 1152: nd6log(LOG_ERR,
1153: "failed to make "
1.32 itojun 1154: "the prefix %s/%d on-link on %s "
1.107 ozaki-r 1155: "(errno=%d)\n",
1.131 christos 1156: IN6_PRINT(ip6buf,
1.130 ryo 1157: &pr->ndpr_prefix.sin6_addr),
1.107 ozaki-r 1158: pr->ndpr_plen, if_name(pr->ndpr_ifp), e);
1.32 itojun 1159: /* proceed anyway. XXX: is it correct? */
1160: }
1161: }
1162:
1163: if (dr && pfxrtr_lookup(pr, dr) == NULL)
1164: pfxrtr_add(pr, dr);
1165: } else {
1166: struct nd_prefix *newpr = NULL;
1167:
1.94 matt 1168: if (newprc->ndprc_vltime == 0)
1.2 itojun 1169: goto end;
1.94 matt 1170: if (newprc->ndprc_raf_onlink == 0 && newprc->ndprc_raf_auto == 0)
1.32 itojun 1171: goto end;
1172:
1.81 spz 1173: if (ip6_rtadv_maxroutes <= nd6_numroutes) {
1174: ICMP6_STATINC(ICMP6_STAT_DROPPED_RAROUTE);
1175: goto end;
1176: }
1177:
1.94 matt 1178: error = nd6_prelist_add(newprc, dr, &newpr);
1.32 itojun 1179: if (error != 0 || newpr == NULL) {
1.107 ozaki-r 1180: nd6log(LOG_NOTICE,
1181: "nd6_prelist_add failed for %s/%d on %s "
1182: "errno=%d, returnpr=%p\n",
1.131 christos 1183: IN6_PRINT(ip6buf, &newprc->ndprc_prefix.sin6_addr),
1.94 matt 1184: newprc->ndprc_plen, if_name(newprc->ndprc_ifp),
1.107 ozaki-r 1185: error, newpr);
1.32 itojun 1186: goto end; /* we should just give up in this case. */
1.2 itojun 1187: }
1188:
1189: /*
1.32 itojun 1190: * XXX: from the ND point of view, we can ignore a prefix
1191: * with the on-link bit being zero. However, we need a
1192: * prefix structure for references from autoconfigured
1193: * addresses. Thus, we explicitly make sure that the prefix
1194: * itself expires now.
1.2 itojun 1195: */
1.32 itojun 1196: if (newpr->ndpr_raf_onlink == 0) {
1197: newpr->ndpr_vltime = 0;
1198: newpr->ndpr_pltime = 0;
1199: in6_init_prefix_ltimes(newpr);
1200: }
1.2 itojun 1201:
1.32 itojun 1202: pr = newpr;
1203: }
1204:
1205: /*
1206: * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
1207: * Note that pr must be non NULL at this point.
1208: */
1209:
1210: /* 5.5.3 (a). Ignore the prefix without the A bit set. */
1.94 matt 1211: if (!newprc->ndprc_raf_auto)
1.32 itojun 1212: goto end;
1.2 itojun 1213:
1.32 itojun 1214: /*
1215: * 5.5.3 (b). the link-local prefix should have been ignored in
1216: * nd6_ra_input.
1217: */
1.2 itojun 1218:
1.56 rpaulo 1219: /* 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime. */
1.94 matt 1220: if (newprc->ndprc_pltime > newprc->ndprc_vltime) {
1.56 rpaulo 1221: error = EINVAL; /* XXX: won't be used */
1222: goto end;
1223: }
1.2 itojun 1224:
1.32 itojun 1225: /*
1.56 rpaulo 1226: * 5.5.3 (d). If the prefix advertised is not equal to the prefix of
1227: * an address configured by stateless autoconfiguration already in the
1228: * list of addresses associated with the interface, and the Valid
1229: * Lifetime is not 0, form an address. We first check if we have
1230: * a matching prefix.
1231: * Note: we apply a clarification in rfc2462bis-02 here. We only
1232: * consider autoconfigured addresses while RFC2462 simply said
1233: * "address".
1.32 itojun 1234: */
1.118 ozaki-r 1235: ss = pserialize_read_enter();
1.115 ozaki-r 1236: IFADDR_READER_FOREACH(ifa, ifp) {
1.114 ozaki-r 1237: struct in6_ifaddr *ia6;
1.56 rpaulo 1238: u_int32_t remaininglifetime;
1.2 itojun 1239:
1.32 itojun 1240: if (ifa->ifa_addr->sa_family != AF_INET6)
1241: continue;
1.2 itojun 1242:
1.114 ozaki-r 1243: ia6 = (struct in6_ifaddr *)ifa;
1.2 itojun 1244:
1.32 itojun 1245: /*
1.56 rpaulo 1246: * We only consider autoconfigured addresses as per rfc2462bis.
1247: */
1.114 ozaki-r 1248: if (!(ia6->ia6_flags & IN6_IFF_AUTOCONF))
1.56 rpaulo 1249: continue;
1250:
1251: /*
1.32 itojun 1252: * Spec is not clear here, but I believe we should concentrate
1253: * on unicast (i.e. not anycast) addresses.
1254: * XXX: other ia6_flags? detached or duplicated?
1255: */
1.114 ozaki-r 1256: if ((ia6->ia6_flags & IN6_IFF_ANYCAST) != 0)
1.32 itojun 1257: continue;
1.33 itojun 1258:
1.56 rpaulo 1259: /*
1260: * Ignore the address if it is not associated with a prefix
1261: * or is associated with a prefix that is different from this
1262: * one. (pr is never NULL here)
1263: */
1.114 ozaki-r 1264: if (ia6->ia6_ndpr != pr)
1.32 itojun 1265: continue;
1.7 itojun 1266:
1.32 itojun 1267: if (ia6_match == NULL) /* remember the first one */
1.114 ozaki-r 1268: ia6_match = ia6;
1.2 itojun 1269:
1.32 itojun 1270: /*
1271: * An already autoconfigured address matched. Now that we
1272: * are sure there is at least one matched address, we can
1273: * proceed to 5.5.3. (e): update the lifetimes according to the
1274: * "two hours" rule and the privacy extension.
1.56 rpaulo 1275: * We apply some clarifications in rfc2462bis:
1276: * - use remaininglifetime instead of storedlifetime as a
1277: * variable name
1278: * - remove the dead code in the "two-hour" rule
1.32 itojun 1279: */
1280: #define TWOHOUR (120*60)
1.114 ozaki-r 1281: lt6_tmp = ia6->ia6_lifetime;
1.32 itojun 1282: if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
1.56 rpaulo 1283: remaininglifetime = ND6_INFINITE_LIFETIME;
1.114 ozaki-r 1284: else if (time_uptime - ia6->ia6_updatetime >
1.32 itojun 1285: lt6_tmp.ia6t_vltime) {
1286: /*
1287: * The case of "invalid" address. We should usually
1288: * not see this case.
1289: */
1.56 rpaulo 1290: remaininglifetime = 0;
1.32 itojun 1291: } else
1.56 rpaulo 1292: remaininglifetime = lt6_tmp.ia6t_vltime -
1.114 ozaki-r 1293: (time_uptime - ia6->ia6_updatetime);
1.56 rpaulo 1294:
1295: /* when not updating, keep the current stored lifetime. */
1296: lt6_tmp.ia6t_vltime = remaininglifetime;
1297:
1.94 matt 1298: if (TWOHOUR < newprc->ndprc_vltime ||
1299: remaininglifetime < newprc->ndprc_vltime) {
1300: lt6_tmp.ia6t_vltime = newprc->ndprc_vltime;
1.56 rpaulo 1301: } else if (remaininglifetime <= TWOHOUR) {
1302: if (auth)
1.94 matt 1303: lt6_tmp.ia6t_vltime = newprc->ndprc_vltime;
1.32 itojun 1304: } else {
1305: /*
1.94 matt 1306: * newprc->ndprc_vltime <= TWOHOUR &&
1.56 rpaulo 1307: * TWOHOUR < remaininglifetime
1.32 itojun 1308: */
1309: lt6_tmp.ia6t_vltime = TWOHOUR;
1.2 itojun 1310: }
1311:
1.32 itojun 1312: /* The 2 hour rule is not imposed for preferred lifetime. */
1.94 matt 1313: lt6_tmp.ia6t_pltime = newprc->ndprc_pltime;
1.2 itojun 1314:
1.32 itojun 1315: in6_init_address_ltimes(pr, <6_tmp);
1.2 itojun 1316:
1.56 rpaulo 1317: /*
1318: * We need to treat lifetimes for temporary addresses
1319: * differently, according to
1320: * draft-ietf-ipv6-privacy-addrs-v2-01.txt 3.3 (1);
1321: * we only update the lifetimes when they are in the maximum
1322: * intervals.
1323: */
1.114 ozaki-r 1324: if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
1.56 rpaulo 1325: u_int32_t maxvltime, maxpltime;
1326:
1327: if (ip6_temp_valid_lifetime >
1.114 ozaki-r 1328: (u_int32_t)((time_uptime - ia6->ia6_createtime) +
1.56 rpaulo 1329: ip6_desync_factor)) {
1330: maxvltime = ip6_temp_valid_lifetime -
1.114 ozaki-r 1331: (time_uptime - ia6->ia6_createtime) -
1.56 rpaulo 1332: ip6_desync_factor;
1333: } else
1334: maxvltime = 0;
1335: if (ip6_temp_preferred_lifetime >
1.114 ozaki-r 1336: (u_int32_t)((time_uptime - ia6->ia6_createtime) +
1.56 rpaulo 1337: ip6_desync_factor)) {
1338: maxpltime = ip6_temp_preferred_lifetime -
1.114 ozaki-r 1339: (time_uptime - ia6->ia6_createtime) -
1.56 rpaulo 1340: ip6_desync_factor;
1341: } else
1342: maxpltime = 0;
1343:
1344: if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
1345: lt6_tmp.ia6t_vltime > maxvltime) {
1346: lt6_tmp.ia6t_vltime = maxvltime;
1347: }
1348: if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
1349: lt6_tmp.ia6t_pltime > maxpltime) {
1350: lt6_tmp.ia6t_pltime = maxpltime;
1351: }
1352: }
1353:
1.114 ozaki-r 1354: ia6->ia6_lifetime = lt6_tmp;
1355: ia6->ia6_updatetime = time_uptime;
1.32 itojun 1356: }
1.118 ozaki-r 1357: pserialize_read_exit(ss);
1358:
1.94 matt 1359: if (ia6_match == NULL && newprc->ndprc_vltime) {
1.56 rpaulo 1360: int ifidlen;
1.114 ozaki-r 1361: struct in6_ifaddr *ia6;
1.118 ozaki-r 1362: struct psref psref;
1.56 rpaulo 1363:
1.2 itojun 1364: /*
1.56 rpaulo 1365: * 5.5.3 (d) (continued)
1.32 itojun 1366: * No address matched and the valid lifetime is non-zero.
1367: * Create a new address.
1.2 itojun 1368: */
1.56 rpaulo 1369:
1370: /*
1371: * Prefix Length check:
1372: * If the sum of the prefix length and interface identifier
1373: * length does not equal 128 bits, the Prefix Information
1374: * option MUST be ignored. The length of the interface
1375: * identifier is defined in a separate link-type specific
1376: * document.
1377: */
1378: ifidlen = in6_if2idlen(ifp);
1379: if (ifidlen < 0) {
1380: /* this should not happen, so we always log it. */
1.106 ozaki-r 1381: log(LOG_ERR, "%s: IFID undefined (%s)\n",
1382: __func__, if_name(ifp));
1.56 rpaulo 1383: goto end;
1384: }
1385: if (ifidlen + pr->ndpr_plen != 128) {
1.107 ozaki-r 1386: nd6log(LOG_INFO,
1387: "invalid prefixlen %d for %s, ignored\n",
1388: pr->ndpr_plen, if_name(ifp));
1.56 rpaulo 1389: goto end;
1390: }
1391:
1.118 ozaki-r 1392: if ((ia6 = in6_ifadd(newprc, mcast, &psref)) != NULL) {
1.32 itojun 1393: /*
1.94 matt 1394: * note that we should use pr (not newprc) for reference.
1.32 itojun 1395: */
1396: pr->ndpr_refcnt++;
1397: ia6->ia6_ndpr = pr;
1.2 itojun 1398:
1.119 roy 1399: /* toggle onlink state if the address was assigned
1400: * a prefix route. */
1401: if (ia6->ia_flags & IFA_ROUTE)
1402: pr->ndpr_stateflags |= NDPRF_ONLINK;
1403:
1.32 itojun 1404: /*
1.56 rpaulo 1405: * draft-ietf-ipngwg-temp-addresses-v2-00 3.3 (2).
1406: * When a new public address is created as described
1407: * in RFC2462, also create a new temporary address.
1408: *
1409: * draft-ietf-ipngwg-temp-addresses-v2-00 3.5.
1410: * When an interface connects to a new link, a new
1411: * randomized interface identifier should be generated
1412: * immediately together with a new set of temporary
1413: * addresses. Thus, we specifiy 1 as the 2nd arg of
1414: * in6_tmpifadd().
1415: */
1416: if (ip6_use_tempaddr) {
1417: int e;
1418: if ((e = in6_tmpifadd(ia6, 1, 1)) != 0) {
1.107 ozaki-r 1419: nd6log(LOG_NOTICE,
1420: "failed to create a temporary "
1421: "address, errno=%d\n", e);
1.56 rpaulo 1422: }
1423: }
1.118 ozaki-r 1424: ia6_release(ia6, &psref);
1.56 rpaulo 1425:
1426: /*
1.32 itojun 1427: * A newly added address might affect the status
1428: * of other addresses, so we check and update it.
1429: * XXX: what if address duplication happens?
1430: */
1.123 ozaki-r 1431: nd6_pfxlist_onlink_check();
1.32 itojun 1432: } else {
1433: /* just set an error. do not bark here. */
1434: error = EADDRNOTAVAIL; /* XXX: might be unused. */
1435: }
1.2 itojun 1436: }
1437:
1438: end:
1439: return error;
1440: }
1441:
1442: /*
1.7 itojun 1443: * A supplement function used in the on-link detection below;
1444: * detect if a given prefix has a (probably) reachable advertising router.
1445: * XXX: lengthy function name...
1446: */
1447: static struct nd_pfxrouter *
1.64 christos 1448: find_pfxlist_reachable_router(struct nd_prefix *pr)
1.7 itojun 1449: {
1450: struct nd_pfxrouter *pfxrtr;
1451:
1452: for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1453: pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1.89 roy 1454: if (pfxrtr->router->ifp->if_flags & IFF_UP &&
1455: pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN &&
1.101 ozaki-r 1456: nd6_is_llinfo_probreach(pfxrtr->router))
1.7 itojun 1457: break; /* found */
1458: }
1459:
1.36 itojun 1460: return (pfxrtr);
1.7 itojun 1461: }
1462:
1463: /*
1.2 itojun 1464: * Check if each prefix in the prefix list has at least one available router
1.25 itojun 1465: * that advertised the prefix (a router is "available" if its neighbor cache
1466: * entry is reachable or probably reachable).
1.7 itojun 1467: * If the check fails, the prefix may be off-link, because, for example,
1.2 itojun 1468: * we have moved from the network but the lifetime of the prefix has not
1.25 itojun 1469: * expired yet. So we should not use the prefix if there is another prefix
1470: * that has an available router.
1471: * But, if there is no prefix that has an available router, we still regards
1472: * all the prefixes as on-link. This is because we can't tell if all the
1.2 itojun 1473: * routers are simply dead or if we really moved from the network and there
1474: * is no router around us.
1475: */
1.7 itojun 1476: void
1.123 ozaki-r 1477: nd6_pfxlist_onlink_check(void)
1.2 itojun 1478: {
1479: struct nd_prefix *pr;
1.114 ozaki-r 1480: struct in6_ifaddr *ia;
1.56 rpaulo 1481: struct nd_defrouter *dr;
1482: struct nd_pfxrouter *pfxrtr = NULL;
1.118 ozaki-r 1483: int s;
1.130 ryo 1484: char ip6buf[INET6_ADDRSTRLEN];
1.2 itojun 1485:
1.128 ozaki-r 1486: ND6_ASSERT_WLOCK();
1487:
1.7 itojun 1488: /*
1489: * Check if there is a prefix that has a reachable advertising
1490: * router.
1491: */
1.125 ozaki-r 1492: ND_PREFIX_LIST_FOREACH(pr) {
1.32 itojun 1493: if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
1.2 itojun 1494: break;
1.7 itojun 1495: }
1.56 rpaulo 1496: /*
1497: * If we have no such prefix, check whether we still have a router
1498: * that does not advertise any prefixes.
1499: */
1500: if (pr == NULL) {
1.124 ozaki-r 1501: ND_DEFROUTER_LIST_FOREACH(dr) {
1.56 rpaulo 1502: struct nd_prefix *pr0;
1503:
1.125 ozaki-r 1504: ND_PREFIX_LIST_FOREACH(pr0) {
1.56 rpaulo 1505: if ((pfxrtr = pfxrtr_lookup(pr0, dr)) != NULL)
1506: break;
1507: }
1508: if (pfxrtr)
1509: break;
1510: }
1511: }
1.124 ozaki-r 1512: if (pr != NULL || (!ND_DEFROUTER_LIST_EMPTY() && !pfxrtr)) {
1.2 itojun 1513: /*
1.32 itojun 1514: * There is at least one prefix that has a reachable router,
1515: * or at least a router which probably does not advertise
1516: * any prefixes. The latter would be the case when we move
1517: * to a new link where we have a router that does not provide
1518: * prefixes and we configure an address by hand.
1519: * Detach prefixes which have no reachable advertising
1520: * router, and attach other prefixes.
1.2 itojun 1521: */
1.125 ozaki-r 1522: ND_PREFIX_LIST_FOREACH(pr) {
1.32 itojun 1523: /* XXX: a link-local prefix should never be detached */
1524: if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1525: continue;
1526:
1527: /*
1528: * we aren't interested in prefixes without the L bit
1529: * set.
1530: */
1531: if (pr->ndpr_raf_onlink == 0)
1532: continue;
1533:
1534: if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1535: find_pfxlist_reachable_router(pr) == NULL)
1536: pr->ndpr_stateflags |= NDPRF_DETACHED;
1537: if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1538: find_pfxlist_reachable_router(pr) != 0)
1539: pr->ndpr_stateflags &= ~NDPRF_DETACHED;
1540: }
1541: } else {
1542: /* there is no prefix that has a reachable router */
1.125 ozaki-r 1543: ND_PREFIX_LIST_FOREACH(pr) {
1.32 itojun 1544: if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1545: continue;
1546:
1547: if (pr->ndpr_raf_onlink == 0)
1548: continue;
1549:
1550: if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
1551: pr->ndpr_stateflags &= ~NDPRF_DETACHED;
1552: }
1553: }
1554:
1555: /*
1556: * Remove each interface route associated with a (just) detached
1557: * prefix, and reinstall the interface route for a (just) attached
1558: * prefix. Note that all attempt of reinstallation does not
1559: * necessarily success, when a same prefix is shared among multiple
1560: * interfaces. Such cases will be handled in nd6_prefix_onlink,
1561: * so we don't have to care about them.
1562: */
1.125 ozaki-r 1563: ND_PREFIX_LIST_FOREACH(pr) {
1.32 itojun 1564: int e;
1565:
1566: if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1567: continue;
1568:
1569: if (pr->ndpr_raf_onlink == 0)
1570: continue;
1571:
1572: if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1573: (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1574: if ((e = nd6_prefix_offlink(pr)) != 0) {
1.107 ozaki-r 1575: nd6log(LOG_ERR,
1576: "failed to make %s/%d offlink, errno=%d\n",
1.131 christos 1577: IN6_PRINT(ip6buf,
1.130 ryo 1578: &pr->ndpr_prefix.sin6_addr),
1.107 ozaki-r 1579: pr->ndpr_plen, e);
1.2 itojun 1580: }
1581: }
1.32 itojun 1582: if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1583: (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
1584: pr->ndpr_raf_onlink) {
1585: if ((e = nd6_prefix_onlink(pr)) != 0) {
1.107 ozaki-r 1586: nd6log(LOG_ERR,
1587: "failed to make %s/%d onlink, errno=%d\n",
1.131 christos 1588: IN6_PRINT(ip6buf,
1.130 ryo 1589: &pr->ndpr_prefix.sin6_addr),
1.107 ozaki-r 1590: pr->ndpr_plen, e);
1.32 itojun 1591: }
1592: }
1593: }
1594:
1595: /*
1596: * Changes on the prefix status might affect address status as well.
1597: * Make sure that all addresses derived from an attached prefix are
1598: * attached, and that all addresses derived from a detached prefix are
1599: * detached. Note, however, that a manually configured address should
1600: * always be attached.
1601: * The precise detection logic is same as the one for prefixes.
1602: */
1.118 ozaki-r 1603: s = pserialize_read_enter();
1.114 ozaki-r 1604: IN6_ADDRLIST_READER_FOREACH(ia) {
1605: if (!(ia->ia6_flags & IN6_IFF_AUTOCONF))
1.32 itojun 1606: continue;
1607:
1.114 ozaki-r 1608: if (ia->ia6_ndpr == NULL) {
1.32 itojun 1609: /*
1610: * This can happen when we first configure the address
1611: * (i.e. the address exists, but the prefix does not).
1612: * XXX: complicated relationships...
1613: */
1614: continue;
1615: }
1616:
1.114 ozaki-r 1617: if (find_pfxlist_reachable_router(ia->ia6_ndpr))
1.32 itojun 1618: break;
1619: }
1.118 ozaki-r 1620: pserialize_read_exit(s);
1.114 ozaki-r 1621:
1622: if (ia) {
1.118 ozaki-r 1623: int bound = curlwp_bind();
1624:
1625: s = pserialize_read_enter();
1.114 ozaki-r 1626: IN6_ADDRLIST_READER_FOREACH(ia) {
1.118 ozaki-r 1627: struct ifaddr *ifa = (struct ifaddr *)ia;
1628: struct psref psref;
1629:
1.114 ozaki-r 1630: if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1.32 itojun 1631: continue;
1632:
1.114 ozaki-r 1633: if (ia->ia6_ndpr == NULL) /* XXX: see above. */
1.32 itojun 1634: continue;
1635:
1.118 ozaki-r 1636: ia6_acquire(ia, &psref);
1637: pserialize_read_exit(s);
1638:
1.114 ozaki-r 1639: if (find_pfxlist_reachable_router(ia->ia6_ndpr)) {
1640: if (ia->ia6_flags & IN6_IFF_DETACHED) {
1641: ia->ia6_flags &= ~IN6_IFF_DETACHED;
1642: ia->ia6_flags |= IN6_IFF_TENTATIVE;
1.118 ozaki-r 1643: nd6_dad_start(ifa,
1.56 rpaulo 1644: 0);
1.87 roy 1645: /* We will notify the routing socket
1646: * of the DAD result, so no need to
1647: * here */
1.56 rpaulo 1648: }
1649: } else {
1.114 ozaki-r 1650: if ((ia->ia6_flags & IN6_IFF_DETACHED) == 0) {
1651: ia->ia6_flags |= IN6_IFF_DETACHED;
1.97 roy 1652: rt_newaddrmsg(RTM_NEWADDR,
1.118 ozaki-r 1653: ifa, 0, NULL);
1.56 rpaulo 1654: }
1655: }
1.118 ozaki-r 1656:
1657: s = pserialize_read_enter();
1658: ia6_release(ia, &psref);
1.2 itojun 1659: }
1.118 ozaki-r 1660: pserialize_read_exit(s);
1661: curlwp_bindx(bound);
1.2 itojun 1662: }
1663: else {
1.118 ozaki-r 1664: int bound = curlwp_bind();
1665:
1666: s = pserialize_read_enter();
1.114 ozaki-r 1667: IN6_ADDRLIST_READER_FOREACH(ia) {
1668: if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1.32 itojun 1669: continue;
1670:
1.114 ozaki-r 1671: if (ia->ia6_flags & IN6_IFF_DETACHED) {
1.118 ozaki-r 1672: struct ifaddr *ifa = (struct ifaddr *)ia;
1673: struct psref psref;
1674:
1.114 ozaki-r 1675: ia->ia6_flags &= ~IN6_IFF_DETACHED;
1676: ia->ia6_flags |= IN6_IFF_TENTATIVE;
1.118 ozaki-r 1677:
1678: ia6_acquire(ia, &psref);
1679: pserialize_read_exit(s);
1680:
1.56 rpaulo 1681: /* Do we need a delay in this case? */
1.118 ozaki-r 1682: nd6_dad_start(ifa, 0);
1683:
1684: s = pserialize_read_enter();
1685: ia6_release(ia, &psref);
1.56 rpaulo 1686: }
1.32 itojun 1687: }
1.118 ozaki-r 1688: pserialize_read_exit(s);
1689: curlwp_bindx(bound);
1.2 itojun 1690: }
1691: }
1692:
1.121 ozaki-r 1693: static int
1.64 christos 1694: nd6_prefix_onlink(struct nd_prefix *pr)
1.2 itojun 1695: {
1.32 itojun 1696: struct ifaddr *ifa;
1697: struct ifnet *ifp = pr->ndpr_ifp;
1698: struct sockaddr_in6 mask6;
1699: struct nd_prefix *opr;
1700: u_long rtflags;
1701: int error = 0;
1.118 ozaki-r 1702: struct psref psref;
1703: int bound;
1.130 ryo 1704: char ip6buf[INET6_ADDRSTRLEN];
1705: char ip6bufp[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
1.32 itojun 1706:
1.128 ozaki-r 1707: ND6_ASSERT_WLOCK();
1708:
1.32 itojun 1709: /* sanity check */
1710: if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1.107 ozaki-r 1711: nd6log(LOG_ERR, "%s/%d is already on-link\n",
1.131 christos 1712: IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.130 ryo 1713: pr->ndpr_plen);
1.51 itojun 1714: return (EEXIST);
1.32 itojun 1715: }
1716:
1717: /*
1718: * Add the interface route associated with the prefix. Before
1719: * installing the route, check if there's the same prefix on another
1720: * interface, and the prefix has already installed the interface route.
1721: * Although such a configuration is expected to be rare, we explicitly
1722: * allow it.
1723: */
1.125 ozaki-r 1724: ND_PREFIX_LIST_FOREACH(opr) {
1.32 itojun 1725: if (opr == pr)
1726: continue;
1727:
1728: if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0)
1729: continue;
1730:
1731: if (opr->ndpr_plen == pr->ndpr_plen &&
1732: in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
1733: &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen))
1.36 itojun 1734: return (0);
1.32 itojun 1735: }
1736:
1737: /*
1738: * We prefer link-local addresses as the associated interface address.
1739: */
1740: /* search for a link-local addr */
1.118 ozaki-r 1741: bound = curlwp_bind();
1742: ifa = (struct ifaddr *)in6ifa_ifpforlinklocal_psref(ifp,
1743: IN6_IFF_NOTREADY | IN6_IFF_ANYCAST, &psref);
1.32 itojun 1744: if (ifa == NULL) {
1.118 ozaki-r 1745: int s = pserialize_read_enter();
1.115 ozaki-r 1746: IFADDR_READER_FOREACH(ifa, ifp) {
1.32 itojun 1747: if (ifa->ifa_addr->sa_family == AF_INET6)
1748: break;
1749: }
1.118 ozaki-r 1750: if (ifa != NULL)
1751: ifa_acquire(ifa, &psref);
1752: pserialize_read_exit(s);
1.32 itojun 1753: /* should we care about ia6_flags? */
1754: }
1755: if (ifa == NULL) {
1756: /*
1757: * This can still happen, when, for example, we receive an RA
1758: * containing a prefix with the L bit set and the A bit clear,
1759: * after removing all IPv6 addresses on the receiving
1760: * interface. This should, of course, be rare though.
1761: */
1.107 ozaki-r 1762: nd6log(LOG_NOTICE, "failed to find any ifaddr"
1.32 itojun 1763: " to add route for a prefix(%s/%d) on %s\n",
1.131 christos 1764: IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.107 ozaki-r 1765: pr->ndpr_plen, if_name(ifp));
1.118 ozaki-r 1766: curlwp_bindx(bound);
1.36 itojun 1767: return (0);
1.32 itojun 1768: }
1.2 itojun 1769:
1770: /*
1.32 itojun 1771: * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1772: * ifa->ifa_rtrequest = nd6_rtrequest;
1.2 itojun 1773: */
1.78 cegger 1774: memset(&mask6, 0, sizeof(mask6));
1.85 joerg 1775: mask6.sin6_family = AF_INET6;
1.32 itojun 1776: mask6.sin6_len = sizeof(mask6);
1777: mask6.sin6_addr = pr->ndpr_mask;
1778: /* rtrequest() will probably set RTF_UP, but we're not sure. */
1779: rtflags = ifa->ifa_flags | RTF_UP;
1780: if (nd6_need_cache(ifp)) {
1781: /* explicitly set in case ifa_flags does not set the flag. */
1.108 ozaki-r 1782: rtflags |= RTF_CONNECTED;
1.32 itojun 1783: } else {
1784: /*
1785: * explicitly clear the cloning bit in case ifa_flags sets it.
1786: */
1.108 ozaki-r 1787: rtflags &= ~RTF_CONNECTED;
1.32 itojun 1788: }
1.116 ozaki-r 1789: error = rtrequest_newmsg(RTM_ADD, sin6tosa(&pr->ndpr_prefix),
1790: ifa->ifa_addr, sin6tosa(&mask6), rtflags);
1.32 itojun 1791: if (error == 0) {
1.101 ozaki-r 1792: nd6_numroutes++;
1.32 itojun 1793: pr->ndpr_stateflags |= NDPRF_ONLINK;
1794: } else {
1.107 ozaki-r 1795: nd6log(LOG_ERR, "failed to add route for a"
1.32 itojun 1796: " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1797: "errno = %d\n",
1.131 christos 1798: IN6_PRINT(ip6bufp, &pr->ndpr_prefix.sin6_addr),
1.32 itojun 1799: pr->ndpr_plen, if_name(ifp),
1.131 christos 1800: IN6_PRINT(ip6buf,
1.130 ryo 1801: &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
1.131 christos 1802: IN6_PRINT(ip6bufm, &mask6.sin6_addr), rtflags, error);
1.32 itojun 1803: }
1.118 ozaki-r 1804: ifa_release(ifa, &psref);
1805: curlwp_bindx(bound);
1.32 itojun 1806:
1.36 itojun 1807: return (error);
1.32 itojun 1808: }
1809:
1.121 ozaki-r 1810: static int
1.64 christos 1811: nd6_prefix_offlink(struct nd_prefix *pr)
1.32 itojun 1812: {
1813: int error = 0;
1814: struct ifnet *ifp = pr->ndpr_ifp;
1815: struct nd_prefix *opr;
1816: struct sockaddr_in6 sa6, mask6;
1.130 ryo 1817: char ip6buf[INET6_ADDRSTRLEN];
1.32 itojun 1818:
1.128 ozaki-r 1819: ND6_ASSERT_WLOCK();
1820:
1.32 itojun 1821: /* sanity check */
1822: if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1.107 ozaki-r 1823: nd6log(LOG_ERR, "%s/%d is already off-link\n",
1.131 christos 1824: IN6_PRINT(ip6buf, &pr->ndpr_prefix.sin6_addr),
1.130 ryo 1825: pr->ndpr_plen);
1.36 itojun 1826: return (EEXIST);
1.32 itojun 1827: }
1828:
1.69 dyoung 1829: sockaddr_in6_init(&sa6, &pr->ndpr_prefix.sin6_addr, 0, 0, 0);
1830: sockaddr_in6_init(&mask6, &pr->ndpr_mask, 0, 0, 0);
1.116 ozaki-r 1831: error = rtrequest_newmsg(RTM_DELETE, sin6tosa(&sa6), NULL,
1832: sin6tosa(&mask6), 0);
1.32 itojun 1833: if (error == 0) {
1834: pr->ndpr_stateflags &= ~NDPRF_ONLINK;
1.101 ozaki-r 1835: nd6_numroutes--;
1.2 itojun 1836:
1.32 itojun 1837: /*
1838: * There might be the same prefix on another interface,
1839: * the prefix which could not be on-link just because we have
1840: * the interface route (see comments in nd6_prefix_onlink).
1841: * If there's one, try to make the prefix on-link on the
1842: * interface.
1843: */
1.125 ozaki-r 1844: ND_PREFIX_LIST_FOREACH(opr) {
1.32 itojun 1845: if (opr == pr)
1846: continue;
1.2 itojun 1847:
1.32 itojun 1848: if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
1849: continue;
1.2 itojun 1850:
1.32 itojun 1851: /*
1852: * KAME specific: detached prefixes should not be
1853: * on-link.
1854: */
1855: if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
1856: continue;
1.2 itojun 1857:
1.32 itojun 1858: if (opr->ndpr_plen == pr->ndpr_plen &&
1859: in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
1860: &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
1861: int e;
1862:
1863: if ((e = nd6_prefix_onlink(opr)) != 0) {
1.107 ozaki-r 1864: nd6log(LOG_ERR, "failed to "
1.32 itojun 1865: "recover a prefix %s/%d from %s "
1866: "to %s (errno = %d)\n",
1.131 christos 1867: IN6_PRINT(ip6buf,
1.130 ryo 1868: &opr->ndpr_prefix.sin6_addr),
1.32 itojun 1869: opr->ndpr_plen, if_name(ifp),
1.107 ozaki-r 1870: if_name(opr->ndpr_ifp), e);
1.32 itojun 1871: }
1872: }
1873: }
1874: } else {
1875: /* XXX: can we still set the NDPRF_ONLINK flag? */
1.107 ozaki-r 1876: nd6log(LOG_ERR, "failed to delete route: "
1.32 itojun 1877: "%s/%d on %s (errno = %d)\n",
1.131 christos 1878: IN6_PRINT(ip6buf, &sa6.sin6_addr), pr->ndpr_plen,
1.130 ryo 1879: if_name(ifp),
1.107 ozaki-r 1880: error);
1.2 itojun 1881: }
1882:
1.101 ozaki-r 1883: return error;
1.2 itojun 1884: }
1885:
1886: static struct in6_ifaddr *
1.118 ozaki-r 1887: in6_ifadd(struct nd_prefixctl *prc, int mcast, struct psref *psref)
1.2 itojun 1888: {
1.94 matt 1889: struct ifnet *ifp = prc->ndprc_ifp;
1.2 itojun 1890: struct ifaddr *ifa;
1.32 itojun 1891: struct in6_aliasreq ifra;
1892: struct in6_ifaddr *ia, *ib;
1893: int error, plen0;
1.2 itojun 1894: struct in6_addr mask;
1.94 matt 1895: int prefixlen = prc->ndprc_plen;
1.56 rpaulo 1896: int updateflags;
1.118 ozaki-r 1897: int s;
1.130 ryo 1898: char ip6buf[INET6_ADDRSTRLEN];
1.2 itojun 1899:
1.128 ozaki-r 1900: ND6_ASSERT_WLOCK();
1901:
1.31 itojun 1902: in6_prefixlen2mask(&mask, prefixlen);
1.2 itojun 1903:
1.32 itojun 1904: /*
1905: * find a link-local address (will be interface ID).
1906: * Is it really mandatory? Theoretically, a global or a site-local
1907: * address can be configured without a link-local address, if we
1908: * have a unique interface identifier...
1909: *
1910: * it is not mandatory to have a link-local address, we can generate
1911: * interface identifier on the fly. we do this because:
1912: * (1) it should be the easiest way to find interface identifier.
1913: * (2) RFC2462 5.4 suggesting the use of the same interface identifier
1914: * for multiple addresses on a single interface, and possible shortcut
1915: * of DAD. we omitted DAD for this reason in the past.
1916: * (3) a user can prevent autoconfiguration of global address
1917: * by removing link-local address by hand (this is partly because we
1.55 rpaulo 1918: * don't have other way to control the use of IPv6 on an interface.
1.32 itojun 1919: * this has been our design choice - cf. NRL's "ifconfig auto").
1920: * (4) it is easier to manage when an interface has addresses
1921: * with the same interface identifier, than to have multiple addresses
1922: * with different interface identifiers.
1923: */
1.118 ozaki-r 1924: s = pserialize_read_enter();
1.32 itojun 1925: ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */
1.2 itojun 1926: if (ifa)
1927: ib = (struct in6_ifaddr *)ifa;
1.118 ozaki-r 1928: else {
1929: pserialize_read_exit(s);
1.2 itojun 1930: return NULL;
1.118 ozaki-r 1931: }
1.2 itojun 1932:
1933: #if 0 /* don't care link local addr state, and always do DAD */
1934: /* if link-local address is not eligible, do not autoconfigure. */
1935: if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
1936: printf("in6_ifadd: link-local address not ready\n");
1937: return NULL;
1938: }
1939: #endif
1940:
1941: /* prefixlen + ifidlen must be equal to 128 */
1.32 itojun 1942: plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
1943: if (prefixlen != plen0) {
1.107 ozaki-r 1944: nd6log(LOG_INFO, "wrong prefixlen for %s "
1.32 itojun 1945: "(prefix=%d ifid=%d)\n",
1.107 ozaki-r 1946: if_name(ifp), prefixlen, 128 - plen0);
1.118 ozaki-r 1947: pserialize_read_exit(s);
1.2 itojun 1948: return NULL;
1949: }
1950:
1951: /* make ifaddr */
1952:
1.56 rpaulo 1953: memset(&ifra, 0, sizeof(ifra));
1.32 itojun 1954: /*
1955: * in6_update_ifa() does not use ifra_name, but we accurately set it
1956: * for safety.
1957: */
1958: strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
1.94 matt 1959: sockaddr_in6_init(&ifra.ifra_addr, &prc->ndprc_prefix.sin6_addr, 0, 0, 0);
1.32 itojun 1960: /* prefix */
1961: ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1962: ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1963: ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1964: ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1.2 itojun 1965:
1966: /* interface ID */
1.32 itojun 1967: ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
1968: (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
1969: ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
1970: (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
1971: ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
1972: (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
1973: ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
1974: (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
1.118 ozaki-r 1975: pserialize_read_exit(s);
1.33 itojun 1976:
1.32 itojun 1977: /* new prefix mask. */
1.69 dyoung 1978: sockaddr_in6_init(&ifra.ifra_prefixmask, &mask, 0, 0, 0);
1.2 itojun 1979:
1.56 rpaulo 1980: /* lifetimes */
1.94 matt 1981: ifra.ifra_lifetime.ia6t_vltime = prc->ndprc_vltime;
1982: ifra.ifra_lifetime.ia6t_pltime = prc->ndprc_pltime;
1.2 itojun 1983:
1.32 itojun 1984: /* XXX: scope zone ID? */
1.2 itojun 1985:
1.32 itojun 1986: ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
1.2 itojun 1987:
1.56 rpaulo 1988: /*
1989: * Make sure that we do not have this address already. This should
1990: * usually not happen, but we can still see this case, e.g., if we
1991: * have manually configured the exact address to be configured.
1992: */
1.118 ozaki-r 1993: s = pserialize_read_enter();
1.56 rpaulo 1994: if (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr) != NULL) {
1995: /* this should be rare enough to make an explicit log */
1996: log(LOG_INFO, "in6_ifadd: %s is already configured\n",
1.131 christos 1997: IN6_PRINT(ip6buf, &ifra.ifra_addr.sin6_addr));
1.118 ozaki-r 1998: pserialize_read_exit(s);
1.56 rpaulo 1999: return (NULL);
2000: }
1.118 ozaki-r 2001: pserialize_read_exit(s);
1.56 rpaulo 2002:
2003: /*
2004: * Allocate ifaddr structure, link into chain, etc.
2005: * If we are going to create a new address upon receiving a multicasted
2006: * RA, we need to impose a random delay before starting DAD.
2007: * [draft-ietf-ipv6-rfc2462bis-02.txt, Section 5.4.2]
2008: */
2009: updateflags = 0;
2010: if (mcast)
2011: updateflags |= IN6_IFAUPDATE_DADDELAY;
1.129 christos 2012: if ((error = in6_update_ifa(ifp, &ifra, updateflags)) != 0) {
1.107 ozaki-r 2013: nd6log(LOG_ERR, "failed to make ifaddr %s on %s (errno=%d)\n",
1.131 christos 2014: IN6_PRINT(ip6buf, &ifra.ifra_addr.sin6_addr), if_name(ifp),
1.107 ozaki-r 2015: error);
1.36 itojun 2016: return (NULL); /* ifaddr must not have been allocated. */
1.32 itojun 2017: }
1.2 itojun 2018:
1.118 ozaki-r 2019: ia = in6ifa_ifpwithaddr_psref(ifp, &ifra.ifra_addr.sin6_addr, psref);
1.2 itojun 2020:
1.36 itojun 2021: return (ia); /* this is always non-NULL */
1.2 itojun 2022: }
2023:
2024: int
1.64 christos 2025: in6_tmpifadd(
2026: const struct in6_ifaddr *ia0, /* corresponding public address */
2027: int forcegen,
2028: int dad_delay)
1.56 rpaulo 2029: {
2030: struct ifnet *ifp = ia0->ia_ifa.ifa_ifp;
2031: struct in6_ifaddr *newia, *ia;
2032: struct in6_aliasreq ifra;
2033: int i, error;
2034: int trylimit = 3; /* XXX: adhoc value */
2035: int updateflags;
2036: u_int32_t randid[2];
2037: u_int32_t vltime0, pltime0;
1.117 ozaki-r 2038: int s;
1.56 rpaulo 2039:
1.128 ozaki-r 2040: ND6_ASSERT_WLOCK();
2041:
1.56 rpaulo 2042: memset(&ifra, 0, sizeof(ifra));
2043: strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
2044: ifra.ifra_addr = ia0->ia_addr;
2045: /* copy prefix mask */
2046: ifra.ifra_prefixmask = ia0->ia_prefixmask;
2047: /* clear the old IFID */
2048: for (i = 0; i < 4; i++) {
2049: ifra.ifra_addr.sin6_addr.s6_addr32[i] &=
2050: ifra.ifra_prefixmask.sin6_addr.s6_addr32[i];
2051: }
2052:
2053: again:
2054: if (in6_get_tmpifid(ifp, (u_int8_t *)randid,
2055: (const u_int8_t *)&ia0->ia_addr.sin6_addr.s6_addr[8], forcegen)) {
1.107 ozaki-r 2056: nd6log(LOG_NOTICE, "failed to find a good random IFID\n");
1.56 rpaulo 2057: return (EINVAL);
2058: }
2059: ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
2060: (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
2061: ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
2062: (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
2063:
2064: /*
2065: * in6_get_tmpifid() quite likely provided a unique interface ID.
2066: * However, we may still have a chance to see collision, because
2067: * there may be a time lag between generation of the ID and generation
2068: * of the address. So, we'll do one more sanity check.
2069: */
1.117 ozaki-r 2070: s = pserialize_read_enter();
1.113 ozaki-r 2071: IN6_ADDRLIST_READER_FOREACH(ia) {
1.56 rpaulo 2072: if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
2073: &ifra.ifra_addr.sin6_addr)) {
1.117 ozaki-r 2074: pserialize_read_exit(s);
1.56 rpaulo 2075: if (trylimit-- == 0) {
2076: /*
2077: * Give up. Something strange should have
2078: * happened.
2079: */
1.107 ozaki-r 2080: nd6log(LOG_NOTICE,
2081: "failed to find a unique random IFID\n");
1.56 rpaulo 2082: return (EEXIST);
2083: }
2084: forcegen = 1;
2085: goto again;
2086: }
2087: }
1.117 ozaki-r 2088: pserialize_read_exit(s);
1.56 rpaulo 2089:
2090: /*
2091: * The Valid Lifetime is the lower of the Valid Lifetime of the
2092: * public address or TEMP_VALID_LIFETIME.
2093: * The Preferred Lifetime is the lower of the Preferred Lifetime
2094: * of the public address or TEMP_PREFERRED_LIFETIME -
2095: * DESYNC_FACTOR.
2096: */
2097: if (ia0->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
2098: vltime0 = IFA6_IS_INVALID(ia0) ? 0 :
2099: (ia0->ia6_lifetime.ia6t_vltime -
1.102 ozaki-r 2100: (time_uptime - ia0->ia6_updatetime));
1.56 rpaulo 2101: if (vltime0 > ip6_temp_valid_lifetime)
2102: vltime0 = ip6_temp_valid_lifetime;
2103: } else
2104: vltime0 = ip6_temp_valid_lifetime;
2105: if (ia0->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
2106: pltime0 = IFA6_IS_DEPRECATED(ia0) ? 0 :
2107: (ia0->ia6_lifetime.ia6t_pltime -
1.102 ozaki-r 2108: (time_uptime - ia0->ia6_updatetime));
1.56 rpaulo 2109: if (pltime0 > ip6_temp_preferred_lifetime - ip6_desync_factor){
2110: pltime0 = ip6_temp_preferred_lifetime -
2111: ip6_desync_factor;
2112: }
2113: } else
2114: pltime0 = ip6_temp_preferred_lifetime - ip6_desync_factor;
2115: ifra.ifra_lifetime.ia6t_vltime = vltime0;
2116: ifra.ifra_lifetime.ia6t_pltime = pltime0;
2117:
2118: /*
2119: * A temporary address is created only if this calculated Preferred
2120: * Lifetime is greater than REGEN_ADVANCE time units.
2121: */
2122: if (ifra.ifra_lifetime.ia6t_pltime <= ip6_temp_regen_advance)
2123: return (0);
2124:
2125: /* XXX: scope zone ID? */
2126:
2127: ifra.ifra_flags |= (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY);
2128:
2129: /* allocate ifaddr structure, link into chain, etc. */
2130: updateflags = 0;
1.57 rpaulo 2131: if (dad_delay)
1.56 rpaulo 2132: updateflags |= IN6_IFAUPDATE_DADDELAY;
1.129 christos 2133: if ((error = in6_update_ifa(ifp, &ifra, updateflags)) != 0)
1.56 rpaulo 2134: return (error);
2135:
1.118 ozaki-r 2136: s = pserialize_read_enter();
1.56 rpaulo 2137: newia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
2138: if (newia == NULL) { /* XXX: can it happen? */
1.118 ozaki-r 2139: pserialize_read_exit(s);
1.107 ozaki-r 2140: nd6log(LOG_ERR,
2141: "ifa update succeeded, but we got no ifaddr\n");
1.56 rpaulo 2142: return (EINVAL); /* XXX */
2143: }
2144: newia->ia6_ndpr = ia0->ia6_ndpr;
2145: newia->ia6_ndpr->ndpr_refcnt++;
1.118 ozaki-r 2146: pserialize_read_exit(s);
1.56 rpaulo 2147:
2148: /*
2149: * A newly added address might affect the status of other addresses.
2150: * XXX: when the temporary address is generated with a new public
2151: * address, the onlink check is redundant. However, it would be safe
2152: * to do the check explicitly everywhere a new address is generated,
2153: * and, in fact, we surely need the check when we create a new
2154: * temporary address due to deprecation of an old temporary address.
2155: */
1.123 ozaki-r 2156: nd6_pfxlist_onlink_check();
1.56 rpaulo 2157:
2158: return (0);
2159: }
2160:
2161: static int
1.2 itojun 2162: in6_init_prefix_ltimes(struct nd_prefix *ndpr)
2163: {
1.7 itojun 2164:
1.128 ozaki-r 2165: ND6_ASSERT_WLOCK();
2166:
1.26 itojun 2167: /* check if preferred lifetime > valid lifetime. RFC2462 5.5.3 (c) */
1.2 itojun 2168: if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
1.107 ozaki-r 2169: nd6log(LOG_INFO, "preferred lifetime"
1.2 itojun 2170: "(%d) is greater than valid lifetime(%d)\n",
1.107 ozaki-r 2171: (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime);
1.2 itojun 2172: return (EINVAL);
2173: }
1.7 itojun 2174: if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
1.2 itojun 2175: ndpr->ndpr_preferred = 0;
2176: else
1.102 ozaki-r 2177: ndpr->ndpr_preferred = time_uptime + ndpr->ndpr_pltime;
1.7 itojun 2178: if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
1.2 itojun 2179: ndpr->ndpr_expire = 0;
2180: else
1.102 ozaki-r 2181: ndpr->ndpr_expire = time_uptime + ndpr->ndpr_vltime;
1.2 itojun 2182:
2183: return 0;
2184: }
2185:
2186: static void
1.94 matt 2187: in6_init_address_ltimes(struct nd_prefix *newpr,
1.60 christos 2188: struct in6_addrlifetime *lt6)
1.2 itojun 2189: {
1.7 itojun 2190:
2191: /* Valid lifetime must not be updated unless explicitly specified. */
1.32 itojun 2192: /* init ia6t_expire */
2193: if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
2194: lt6->ia6t_expire = 0;
2195: else {
1.102 ozaki-r 2196: lt6->ia6t_expire = time_uptime;
1.32 itojun 2197: lt6->ia6t_expire += lt6->ia6t_vltime;
1.2 itojun 2198: }
1.7 itojun 2199:
1.2 itojun 2200: /* init ia6t_preferred */
1.7 itojun 2201: if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1.2 itojun 2202: lt6->ia6t_preferred = 0;
2203: else {
1.102 ozaki-r 2204: lt6->ia6t_preferred = time_uptime;
1.2 itojun 2205: lt6->ia6t_preferred += lt6->ia6t_pltime;
2206: }
2207: }
2208:
2209: /*
2210: * Delete all the routing table entries that use the specified gateway.
2211: * XXX: this function causes search through all entries of routing table, so
1.16 itojun 2212: * it shouldn't be called when acting as a router.
1.2 itojun 2213: */
2214: void
1.123 ozaki-r 2215: nd6_rt_flush(struct in6_addr *gateway, struct ifnet *ifp)
1.2 itojun 2216: {
1.138 ozaki-r 2217: #ifndef NET_MPSAFE
1.137 ozaki-r 2218: int s = splsoftnet();
1.138 ozaki-r 2219: #endif
1.2 itojun 2220:
2221: /* We'll care only link-local addresses */
1.138 ozaki-r 2222: if (!IN6_IS_ADDR_LINKLOCAL(gateway))
2223: goto out;
1.2 itojun 2224:
1.120 ozaki-r 2225: rt_delete_matched_entries(AF_INET6, rt6_deleteroute_matcher, gateway);
1.138 ozaki-r 2226:
2227: out:
2228: #ifndef NET_MPSAFE
1.137 ozaki-r 2229: splx(s);
1.138 ozaki-r 2230: #endif
2231: return; /* XXX gcc */
1.2 itojun 2232: }
2233:
2234: static int
1.120 ozaki-r 2235: rt6_deleteroute_matcher(struct rtentry *rt, void *arg)
1.2 itojun 2236: {
2237: struct in6_addr *gate = (struct in6_addr *)arg;
2238:
2239: if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
1.36 itojun 2240: return (0);
1.2 itojun 2241:
1.104 ozaki-r 2242: if (!IN6_ARE_ADDR_EQUAL(gate, &satosin6(rt->rt_gateway)->sin6_addr))
1.36 itojun 2243: return (0);
1.26 itojun 2244:
2245: /*
1.32 itojun 2246: * Do not delete a static route.
2247: * XXX: this seems to be a bit ad-hoc. Should we consider the
2248: * 'cloned' bit instead?
2249: */
2250: if ((rt->rt_flags & RTF_STATIC) != 0)
1.36 itojun 2251: return (0);
1.32 itojun 2252:
2253: /*
1.2 itojun 2254: * We delete only host route. This means, in particular, we don't
2255: * delete default route.
2256: */
2257: if ((rt->rt_flags & RTF_HOST) == 0)
1.36 itojun 2258: return (0);
1.2 itojun 2259:
1.120 ozaki-r 2260: return 1;
1.2 itojun 2261: }
CVSweb <webmaster@jp.NetBSD.org>