Deleted Added
full compact
nd6_rtr.c (59760) nd6_rtr.c (62587)
1/* $FreeBSD: head/sys/netinet6/nd6_rtr.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: nd6_rtr.c,v 1.43 2000/07/02 23:19:59 itojun Exp $ */
3
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

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.
28 *
29 * $FreeBSD: head/sys/netinet6/nd6_rtr.c 59760 2000-04-29 15:36:14Z phk $
30 */
31
31 */
32
33#include "opt_inet.h"
34#include "opt_inet6.h"
35
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/mbuf.h>
36#include <sys/socket.h>
37#include <sys/sockio.h>
38#include <sys/time.h>
39#include <sys/errno.h>
40#include <sys/syslog.h>
41
42#include <net/if.h>
43#include <net/if_types.h>
44#include <net/if_dl.h>
45#include <net/route.h>
46#include <net/radix.h>
47
48#include <netinet/in.h>
49#include <netinet6/in6_var.h>
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/malloc.h>
39#include <sys/mbuf.h>
40#include <sys/socket.h>
41#include <sys/sockio.h>
42#include <sys/time.h>
43#include <sys/errno.h>
44#include <sys/syslog.h>
45
46#include <net/if.h>
47#include <net/if_types.h>
48#include <net/if_dl.h>
49#include <net/route.h>
50#include <net/radix.h>
51
52#include <netinet/in.h>
53#include <netinet6/in6_var.h>
50#include <netinet6/ip6.h>
54#include
51#include <netinet6/ip6_var.h>
52#include <netinet6/nd6.h>
55#include <netinet6/ip6_var.h>
56#include <netinet6/nd6.h>
53#include <netinet6/icmp6.h>
57#include
58#include <netinet6/scope6_var.h>
54
55#include <net/net_osdep.h>
56
59
60#include <net/net_osdep.h>
61
57#define SDL(s) ((struct sockaddr_dl *)s)
62#define SDL(s) ((struct sockaddr_dl *)s)
58
63
59static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
60static int prelist_add __P((struct nd_prefix *, struct nd_defrouter *));
61static struct nd_prefix *prefix_lookup __P((struct nd_prefix *));
62static struct in6_ifaddr *in6_ifadd __P((struct ifnet *, struct in6_addr *,
63 struct in6_addr *, int));
64static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
65 struct nd_defrouter *));
66static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
67static void pfxrtr_del __P((struct nd_pfxrouter *));
68static void pfxlist_onlink_check __P((void));
69static void nd6_detach_prefix __P((struct nd_prefix *));
70static void nd6_attach_prefix __P((struct nd_prefix *));
64static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
65static int prelist_add __P((struct nd_prefix *, struct nd_defrouter *));
66static struct nd_prefix *prefix_lookup __P((struct nd_prefix *));
67static struct in6_ifaddr *in6_ifadd __P((struct ifnet *, struct in6_addr *,
68 struct in6_addr *, int));
69static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
70 struct nd_defrouter *));
71static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
72static void pfxrtr_del __P((struct nd_pfxrouter *));
73static struct nd_pfxrouter *find_pfxlist_reachable_router
74 __P((struct nd_prefix *));
75static void nd6_detach_prefix __P((struct nd_prefix *));
76static void nd6_attach_prefix __P((struct nd_prefix *));
77static void defrouter_addifreq __P((struct ifnet *));
78#ifdef ND6_USE_RTSOCK
79static void defrouter_msg __P((int, struct rtentry *));
80#endif
71
81
72static void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
73 struct in6_addrlifetime *lt6));
82static void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
83 struct in6_addrlifetime *lt6,
84 int update_vltime));
74
85
75static int rt6_deleteroute __P((struct radix_node *, void *));
86static int rt6_deleteroute __P((struct radix_node *, void *));
76
87
77extern int nd6_recalc_reachtm_interval;
88extern int nd6_recalc_reachtm_interval;
78
89
90struct ifnet *nd6_defifp;
91int nd6_defifindex;
92
79/*
80 * Receive Router Solicitation Message - just for routers.
81 * Router solicitation/advertisement is mostly managed by userland program
82 * (rtadvd) so here we have no function like nd6_ra_output().
83 *
84 * Based on RFC 2461
85 */
86void
87nd6_rs_input(m, off, icmp6len)
88 struct mbuf *m;
89 int off, icmp6len;
90{
91 struct ifnet *ifp = m->m_pkthdr.rcvif;
92 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
93/*
94 * Receive Router Solicitation Message - just for routers.
95 * Router solicitation/advertisement is mostly managed by userland program
96 * (rtadvd) so here we have no function like nd6_ra_output().
97 *
98 * Based on RFC 2461
99 */
100void
101nd6_rs_input(m, off, icmp6len)
102 struct mbuf *m;
103 int off, icmp6len;
104{
105 struct ifnet *ifp = m->m_pkthdr.rcvif;
106 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
93 struct nd_router_solicit *nd_rs
94 = (struct nd_router_solicit *)((caddr_t)ip6 + off);
107 struct nd_router_solicit *nd_rs;
95 struct in6_addr saddr6 = ip6->ip6_src;
108 struct in6_addr saddr6 = ip6->ip6_src;
109#if 0
110 struct in6_addr daddr6 = ip6->ip6_dst;
111#endif
96 char *lladdr = NULL;
97 int lladdrlen = 0;
112 char *lladdr = NULL;
113 int lladdrlen = 0;
114#if 0
115 struct sockaddr_dl *sdl = (struct sockaddr_dl *)NULL;
116 struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL;
117 struct rtentry *rt = NULL;
118 int is_newentry;
119#endif
98 union nd_opts ndopts;
99
100 /* If I'm not a router, ignore it. */
101 if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
120 union nd_opts ndopts;
121
122 /* If I'm not a router, ignore it. */
123 if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
102 return;
124 goto freeit;
103
104 /* Sanity checks */
105 if (ip6->ip6_hlim != 255) {
106 log(LOG_ERR,
107 "nd6_rs_input: invalid hlim %d\n", ip6->ip6_hlim);
125
126 /* Sanity checks */
127 if (ip6->ip6_hlim != 255) {
128 log(LOG_ERR,
129 "nd6_rs_input: invalid hlim %d\n", ip6->ip6_hlim);
108 return;
130 goto freeit;
109 }
110
111 /*
112 * Don't update the neighbor cache, if src = ::.
113 * This indicates that the src has no IP address assigned yet.
114 */
115 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
131 }
132
133 /*
134 * Don't update the neighbor cache, if src = ::.
135 * This indicates that the src has no IP address assigned yet.
136 */
137 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
138 goto freeit;
139
140#ifndef PULLDOWN_TEST
141 IP6_EXTHDR_CHECK(m, off, icmp6len,);
142 nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
143#else
144 IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
145 if (nd_rs == NULL) {
146 icmp6stat.icp6s_tooshort++;
116 return;
147 return;
148 }
149#endif
117
118 icmp6len -= sizeof(*nd_rs);
119 nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
120 if (nd6_options(&ndopts) < 0) {
121 log(LOG_INFO, "nd6_rs_input: invalid ND option, ignored\n");
150
151 icmp6len -= sizeof(*nd_rs);
152 nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
153 if (nd6_options(&ndopts) < 0) {
154 log(LOG_INFO, "nd6_rs_input: invalid ND option, ignored\n");
122 return;
155 goto freeit;
123 }
124
125 if (ndopts.nd_opts_src_lladdr) {
126 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
127 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
128 }
129
130 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
131 log(LOG_INFO,
132 "nd6_rs_input: lladdrlen mismatch for %s "
133 "(if %d, RS packet %d)\n",
134 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
135 }
136
137 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
156 }
157
158 if (ndopts.nd_opts_src_lladdr) {
159 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
160 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
161 }
162
163 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
164 log(LOG_INFO,
165 "nd6_rs_input: lladdrlen mismatch for %s "
166 "(if %d, RS packet %d)\n",
167 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
168 }
169
170 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
171
172 freeit:
173 m_freem(m);
138}
139
140/*
141 * Receive Router Advertisement Message.
142 *
143 * Based on RFC 2461
144 * TODO: on-link bit on prefix information
145 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
146 */
147void
148nd6_ra_input(m, off, icmp6len)
149 struct mbuf *m;
150 int off, icmp6len;
151{
152 struct ifnet *ifp = m->m_pkthdr.rcvif;
153 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
154 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
174}
175
176/*
177 * Receive Router Advertisement Message.
178 *
179 * Based on RFC 2461
180 * TODO: on-link bit on prefix information
181 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
182 */
183void
184nd6_ra_input(m, off, icmp6len)
185 struct mbuf *m;
186 int off, icmp6len;
187{
188 struct ifnet *ifp = m->m_pkthdr.rcvif;
189 struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
190 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
155 struct nd_router_advert *nd_ra =
156 (struct nd_router_advert *)((caddr_t)ip6 + off);
191 struct nd_router_advert *nd_ra;
157 struct in6_addr saddr6 = ip6->ip6_src;
192 struct in6_addr saddr6 = ip6->ip6_src;
193#if 0
194 struct in6_addr daddr6 = ip6->ip6_dst;
195 int flags; /* = nd_ra->nd_ra_flags_reserved; */
196 int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
197 int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
198#endif
158 union nd_opts ndopts;
159 struct nd_defrouter *dr;
160
161 if (ip6_accept_rtadv == 0)
199 union nd_opts ndopts;
200 struct nd_defrouter *dr;
201
202 if (ip6_accept_rtadv == 0)
162 return;
203 goto freeit;
163
164 if (ip6->ip6_hlim != 255) {
165 log(LOG_ERR,
166 "nd6_ra_input: invalid hlim %d\n", ip6->ip6_hlim);
204
205 if (ip6->ip6_hlim != 255) {
206 log(LOG_ERR,
207 "nd6_ra_input: invalid hlim %d\n", ip6->ip6_hlim);
167 return;
208 goto freeit;
168 }
169
170 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
171 log(LOG_ERR,
172 "nd6_ra_input: src %s is not link-local\n",
173 ip6_sprintf(&saddr6));
209 }
210
211 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
212 log(LOG_ERR,
213 "nd6_ra_input: src %s is not link-local\n",
214 ip6_sprintf(&saddr6));
215 goto freeit;
216 }
217
218#ifndef PULLDOWN_TEST
219 IP6_EXTHDR_CHECK(m, off, icmp6len,);
220 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
221#else
222 IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
223 if (nd_ra == NULL) {
224 icmp6stat.icp6s_tooshort++;
174 return;
175 }
225 return;
226 }
227#endif
176
177 icmp6len -= sizeof(*nd_ra);
178 nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
179 if (nd6_options(&ndopts) < 0) {
180 log(LOG_INFO, "nd6_ra_input: invalid ND option, ignored\n");
228
229 icmp6len -= sizeof(*nd_ra);
230 nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
231 if (nd6_options(&ndopts) < 0) {
232 log(LOG_INFO, "nd6_ra_input: invalid ND option, ignored\n");
181 return;
233 goto freeit;
182 }
183
184 {
185 struct nd_defrouter dr0;
186 u_int32_t advreachable = nd_ra->nd_ra_reachable;
187
188 dr0.rtaddr = saddr6;
189 dr0.flags = nd_ra->nd_ra_flags_reserved;
190 dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
191 dr0.expire = time_second + dr0.rtlifetime;
192 dr0.ifp = ifp;
234 }
235
236 {
237 struct nd_defrouter dr0;
238 u_int32_t advreachable = nd_ra->nd_ra_reachable;
239
240 dr0.rtaddr = saddr6;
241 dr0.flags = nd_ra->nd_ra_flags_reserved;
242 dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
243 dr0.expire = time_second + dr0.rtlifetime;
244 dr0.ifp = ifp;
245 dr0.advint = 0; /* Mobile IPv6 */
246 dr0.advint_expire = 0; /* Mobile IPv6 */
247 dr0.advints_lost = 0; /* Mobile IPv6 */
193 /* unspecified or not? (RFC 2461 6.3.4) */
194 if (advreachable) {
195 NTOHL(advreachable);
196 if (advreachable <= MAX_REACHABLE_TIME &&
197 ndi->basereachable != advreachable) {
198 ndi->basereachable = advreachable;
199 ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
200 ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */

--- 130 unchanged lines hidden (view full) ---

331 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
332 log(LOG_INFO,
333 "nd6_ra_input: lladdrlen mismatch for %s "
334 "(if %d, RA packet %d)\n",
335 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
336 }
337
338 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
248 /* unspecified or not? (RFC 2461 6.3.4) */
249 if (advreachable) {
250 NTOHL(advreachable);
251 if (advreachable <= MAX_REACHABLE_TIME &&
252 ndi->basereachable != advreachable) {
253 ndi->basereachable = advreachable;
254 ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
255 ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */

--- 130 unchanged lines hidden (view full) ---

386 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
387 log(LOG_INFO,
388 "nd6_ra_input: lladdrlen mismatch for %s "
389 "(if %d, RA packet %d)\n",
390 ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2);
391 }
392
393 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
394
395 /*
396 * Installing a link-layer address might change the state of the
397 * router's neighbor cache, which might also affect our on-link
398 * detection of adveritsed prefixes.
399 */
400 pfxlist_onlink_check();
339 }
401 }
402
403freeit:
404 m_freem(m);
340}
341
342/*
343 * default router list proccessing sub routines
344 */
405}
406
407/*
408 * default router list proccessing sub routines
409 */
410
411#ifdef ND6_USE_RTSOCK
412/* tell the change to user processes watching the routing socket. */
413static void
414defrouter_msg(cmd, rt)
415 int cmd;
416 struct rtentry *rt;
417{
418 struct rt_addrinfo info;
419
420 bzero((caddr_t)&info, sizeof(info));
421 info.rti_info[RTAX_DST] = rt_key(rt);
422 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
423 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
424
425 rt_missmsg(cmd, &info, rt->rt_flags, 0);
426}
427#endif
428
345void
346defrouter_addreq(new)
347 struct nd_defrouter *new;
348{
349 struct sockaddr_in6 def, mask, gate;
429void
430defrouter_addreq(new)
431 struct nd_defrouter *new;
432{
433 struct sockaddr_in6 def, mask, gate;
434 struct rtentry *newrt = NULL;
350 int s;
351
352 Bzero(&def, sizeof(def));
353 Bzero(&mask, sizeof(mask));
354 Bzero(&gate, sizeof(gate));
355
356 def.sin6_len = mask.sin6_len = gate.sin6_len
357 = sizeof(struct sockaddr_in6);
358 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
359 gate.sin6_addr = new->rtaddr;
360
361 s = splnet();
362 (void)rtrequest(RTM_ADD, (struct sockaddr *)&def,
363 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
435 int s;
436
437 Bzero(&def, sizeof(def));
438 Bzero(&mask, sizeof(mask));
439 Bzero(&gate, sizeof(gate));
440
441 def.sin6_len = mask.sin6_len = gate.sin6_len
442 = sizeof(struct sockaddr_in6);
443 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
444 gate.sin6_addr = new->rtaddr;
445
446 s = splnet();
447 (void)rtrequest(RTM_ADD, (struct sockaddr *)&def,
448 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
364 RTF_GATEWAY, NULL);
449 RTF_GATEWAY, &newrt);
450 if (newrt) {
451#ifdef ND6_USE_RTSOCK
452 defrouter_msg(RTM_ADD, newrt); /* tell user process */
453#endif
454 newrt->rt_refcnt--;
455 }
365 splx(s);
366 return;
367}
368
456 splx(s);
457 return;
458}
459
460/* Add a route to a given interface as default */
461void
462defrouter_addifreq(ifp)
463 struct ifnet *ifp;
464{
465 struct sockaddr_in6 def, mask;
466 struct ifaddr *ifa;
467 struct rtentry *newrt = NULL;
468 int error, flags;
469
470 bzero(&def, sizeof(def));
471 bzero(&mask, sizeof(mask));
472
473 def.sin6_len = mask.sin6_len = sizeof(struct sockaddr_in6);
474 def.sin6_family = mask.sin6_family = AF_INET6;
475
476 /*
477 * Search for an ifaddr beloging to the specified interface.
478 * XXX: An IPv6 address are required to be assigned on the interface.
479 */
480 if ((ifa = ifaof_ifpforaddr((struct sockaddr *)&def, ifp)) == NULL) {
481 log(LOG_ERR, /* better error? */
482 "defrouter_addifreq: failed to find an ifaddr "
483 "to install a route to interface %s\n",
484 if_name(ifp));
485 return;
486 }
487
488 flags = ifa->ifa_flags;
489 if ((ifp->if_flags & IFF_POINTOPOINT) != 0)
490 flags &= ~RTF_CLONING;
491 if ((error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
492 ifa->ifa_addr, (struct sockaddr *)&mask,
493 flags, &newrt)) != 0) {
494 log(LOG_ERR,
495 "defrouter_addifreq: failed to install a route to "
496 "interface %s (errno = %d)\n",
497 if_name(ifp), error);
498
499 if (newrt) /* maybe unnecessary, but do it for safety */
500 newrt->rt_refcnt--;
501 } else {
502 if (newrt) {
503#ifdef ND6_USE_RTSOCK
504 defrouter_msg(RTM_ADD, newrt);
505#endif
506 newrt->rt_refcnt--;
507 }
508 }
509}
510
369struct nd_defrouter *
370defrouter_lookup(addr, ifp)
371 struct in6_addr *addr;
372 struct ifnet *ifp;
373{
374 struct nd_defrouter *dr;
375
511struct nd_defrouter *
512defrouter_lookup(addr, ifp)
513 struct in6_addr *addr;
514 struct ifnet *ifp;
515{
516 struct nd_defrouter *dr;
517
376 LIST_FOREACH(dr, &nd_defrouter, dr_entry)
518 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
519 dr = TAILQ_NEXT(dr, dr_entry)) {
377 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
378 return(dr);
520 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
521 return(dr);
522 }
379
380 return(NULL); /* search failed */
381}
382
383void
384defrouter_delreq(dr, dofree)
385 struct nd_defrouter *dr;
386 int dofree;
387{
388 struct sockaddr_in6 def, mask, gate;
523
524 return(NULL); /* search failed */
525}
526
527void
528defrouter_delreq(dr, dofree)
529 struct nd_defrouter *dr;
530 int dofree;
531{
532 struct sockaddr_in6 def, mask, gate;
533 struct rtentry *oldrt = NULL;
389
390 Bzero(&def, sizeof(def));
391 Bzero(&mask, sizeof(mask));
392 Bzero(&gate, sizeof(gate));
393
394 def.sin6_len = mask.sin6_len = gate.sin6_len
395 = sizeof(struct sockaddr_in6);
396 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
397 gate.sin6_addr = dr->rtaddr;
398
399 rtrequest(RTM_DELETE, (struct sockaddr *)&def,
400 (struct sockaddr *)&gate,
401 (struct sockaddr *)&mask,
534
535 Bzero(&def, sizeof(def));
536 Bzero(&mask, sizeof(mask));
537 Bzero(&gate, sizeof(gate));
538
539 def.sin6_len = mask.sin6_len = gate.sin6_len
540 = sizeof(struct sockaddr_in6);
541 def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
542 gate.sin6_addr = dr->rtaddr;
543
544 rtrequest(RTM_DELETE, (struct sockaddr *)&def,
545 (struct sockaddr *)&gate,
546 (struct sockaddr *)&mask,
402 RTF_GATEWAY, (struct rtentry **)0);
547 RTF_GATEWAY, &oldrt);
548 if (oldrt) {
549#ifdef ND6_USE_RTSOCK
550 defrouter_msg(RTM_DELETE, oldrt);
551#endif
552 if (oldrt->rt_refcnt <= 0)
553 oldrt->rt_refcnt++; /* XXX */
554 rtfree(oldrt);
555 }
403
556
404 if (dofree)
557 if (dofree) /* XXX: necessary? */
405 free(dr, M_IP6NDP);
558 free(dr, M_IP6NDP);
406
407 if (!LIST_EMPTY(&nd_defrouter))
408 defrouter_addreq(LIST_FIRST(&nd_defrouter));
409
410 /*
411 * xxx update the Destination Cache entries for all
412 * destinations using that neighbor as a router (7.2.5)
413 */
414}
415
416void
417defrtrlist_del(dr)
418 struct nd_defrouter *dr;
419{
420 struct nd_defrouter *deldr = NULL;
421 struct nd_prefix *pr;
422
423 /*
424 * Flush all the routing table entries that use the router
425 * as a next hop.
426 */
427 if (!ip6_forwarding && ip6_accept_rtadv) {
428 /* above is a good condition? */
429 rt6_flush(&dr->rtaddr, dr->ifp);
430 }
431
559}
560
561void
562defrtrlist_del(dr)
563 struct nd_defrouter *dr;
564{
565 struct nd_defrouter *deldr = NULL;
566 struct nd_prefix *pr;
567
568 /*
569 * Flush all the routing table entries that use the router
570 * as a next hop.
571 */
572 if (!ip6_forwarding && ip6_accept_rtadv) {
573 /* above is a good condition? */
574 rt6_flush(&dr->rtaddr, dr->ifp);
575 }
576
432 if (dr == LIST_FIRST(&nd_defrouter))
577 if (dr == TAILQ_FIRST(&nd_defrouter))
433 deldr = dr; /* The router is primary. */
434
578 deldr = dr; /* The router is primary. */
579
435 LIST_REMOVE(dr, dr_entry);
580 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
436
437 /*
438 * Also delete all the pointers to the router in each prefix lists.
439 */
581
582 /*
583 * Also delete all the pointers to the router in each prefix lists.
584 */
440 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
585 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
441 struct nd_pfxrouter *pfxrtr;
442 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
443 pfxrtr_del(pfxrtr);
444 }
445 pfxlist_onlink_check();
446
447 /*
586 struct nd_pfxrouter *pfxrtr;
587 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
588 pfxrtr_del(pfxrtr);
589 }
590 pfxlist_onlink_check();
591
592 /*
448 * If the router is the primary one, delete the default route
449 * entry in the routing table.
593 * If the router is the primary one, choose a new one.
594 * Note that defrouter_select() will remove the current gateway
595 * from the routing table.
450 */
451 if (deldr)
596 */
597 if (deldr)
452 defrouter_delreq(deldr, 0);
598 defrouter_select();
599
453 free(dr, M_IP6NDP);
454}
455
600 free(dr, M_IP6NDP);
601}
602
603/*
604 * Default Router Selection according to Section 6.3.6 of RFC 2461:
605 * 1) Routers that are reachable or probably reachable should be
606 * preferred.
607 * 2) When no routers on the list are known to be reachable or
608 * probably reachable, routers SHOULD be selected in a round-robin
609 * fashion.
610 * 3) If the Default Router List is empty, assume that all
611 * destinations are on-link.
612 */
613void
614defrouter_select()
615{
616 int s = splnet();
617 struct nd_defrouter *dr, anydr;
618 struct rtentry *rt = NULL;
619 struct llinfo_nd6 *ln = NULL;
620
621 /*
622 * Search for a (probably) reachable router from the list.
623 */
624 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
625 dr = TAILQ_NEXT(dr, dr_entry)) {
626 if ((rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
627 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
628 ND6_IS_LLINFO_PROBREACH(ln)) {
629 /* Got it, and move it to the head */
630 TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
631 TAILQ_INSERT_HEAD(&nd_defrouter, dr, dr_entry);
632 break;
633 }
634 }
635
636 if ((dr = TAILQ_FIRST(&nd_defrouter))) {
637 /*
638 * De-install the previous default gateway and install
639 * a new one.
640 * Note that if there is no reachable router in the list,
641 * the head entry will be used anyway.
642 * XXX: do we have to check the current routing table entry?
643 */
644 bzero(&anydr, sizeof(anydr));
645 defrouter_delreq(&anydr, 0);
646 defrouter_addreq(dr);
647 }
648 else {
649 /*
650 * The Default Router List is empty, so install the default
651 * route to an inteface.
652 * XXX: The specification does not say this mechanism should
653 * be restricted to hosts, but this would be not useful
654 * (even harmful) for routers.
655 */
656 if (!ip6_forwarding) {
657 /*
658 * De-install the current default route
659 * in advance.
660 */
661 bzero(&anydr, sizeof(anydr));
662 defrouter_delreq(&anydr, 0);
663 if (nd6_defifp) {
664 /*
665 * Install a route to the default interface
666 * as default route.
667 */
668 defrouter_addifreq(nd6_defifp);
669 }
670#ifdef ND6_DEBUG
671 else /* noisy log? */
672 log(LOG_INFO, "defrouter_select: "
673 "there's no default router and no default"
674 " interface\n");
675#endif
676 }
677 }
678
679 splx(s);
680 return;
681}
682
456static struct nd_defrouter *
457defrtrlist_update(new)
458 struct nd_defrouter *new;
459{
460 struct nd_defrouter *dr, *n;
461 int s = splnet();
462
463 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {

--- 19 unchanged lines hidden (view full) ---

483
484 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
485 if (n == NULL) {
486 splx(s);
487 return(NULL);
488 }
489 bzero(n, sizeof(*n));
490 *n = *new;
683static struct nd_defrouter *
684defrtrlist_update(new)
685 struct nd_defrouter *new;
686{
687 struct nd_defrouter *dr, *n;
688 int s = splnet();
689
690 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {

--- 19 unchanged lines hidden (view full) ---

710
711 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
712 if (n == NULL) {
713 splx(s);
714 return(NULL);
715 }
716 bzero(n, sizeof(*n));
717 *n = *new;
491 if (LIST_EMPTY(&nd_defrouter)) {
492 LIST_INSERT_HEAD(&nd_defrouter, n, dr_entry);
493 defrouter_addreq(n);
494 } else {
495 LIST_INSERT_AFTER(LIST_FIRST(&nd_defrouter), n, dr_entry);
496 defrouter_addreq(n);
497 }
718
719 /*
720 * Insert the new router at the end of the Default Router List.
721 * If there is no other router, install it anyway. Otherwise,
722 * just continue to use the current default router.
723 */
724 TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
725 if (TAILQ_FIRST(&nd_defrouter) == n)
726 defrouter_select();
498 splx(s);
499
500 return(n);
501}
502
503static struct nd_pfxrouter *
504pfxrtr_lookup(pr, dr)
505 struct nd_prefix *pr;
506 struct nd_defrouter *dr;
507{
508 struct nd_pfxrouter *search;
727 splx(s);
728
729 return(n);
730}
731
732static struct nd_pfxrouter *
733pfxrtr_lookup(pr, dr)
734 struct nd_prefix *pr;
735 struct nd_defrouter *dr;
736{
737 struct nd_pfxrouter *search;
509
510 LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
738
739 for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
511 if (search->router == dr)
512 break;
513 }
514
515 return(search);
516}
517
518static void

--- 23 unchanged lines hidden (view full) ---

542}
543
544static struct nd_prefix *
545prefix_lookup(pr)
546 struct nd_prefix *pr;
547{
548 struct nd_prefix *search;
549
740 if (search->router == dr)
741 break;
742 }
743
744 return(search);
745}
746
747static void

--- 23 unchanged lines hidden (view full) ---

771}
772
773static struct nd_prefix *
774prefix_lookup(pr)
775 struct nd_prefix *pr;
776{
777 struct nd_prefix *search;
778
550 LIST_FOREACH(search, &nd_prefix, ndpr_entry) {
779 for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
551 if (pr->ndpr_ifp == search->ndpr_ifp &&
552 pr->ndpr_plen == search->ndpr_plen &&
553 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
554 &search->ndpr_prefix.sin6_addr,
555 pr->ndpr_plen)
556 ) {
557 break;
558 }

--- 27 unchanged lines hidden (view full) ---

586
587 /* xxx ND_OPT_PI_FLAG_ONLINK processing */
588
589 s = splnet();
590 /* link ndpr_entry to nd_prefix list */
591 LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
592 splx(s);
593
780 if (pr->ndpr_ifp == search->ndpr_ifp &&
781 pr->ndpr_plen == search->ndpr_plen &&
782 in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
783 &search->ndpr_prefix.sin6_addr,
784 pr->ndpr_plen)
785 ) {
786 break;
787 }

--- 27 unchanged lines hidden (view full) ---

815
816 /* xxx ND_OPT_PI_FLAG_ONLINK processing */
817
818 s = splnet();
819 /* link ndpr_entry to nd_prefix list */
820 LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
821 splx(s);
822
594 if (dr)
823 if (dr) {
595 pfxrtr_add(new, dr);
824 pfxrtr_add(new, dr);
825 }
596
597 return 0;
598}
599
600void
601prelist_remove(pr)
602 struct nd_prefix *pr;
603{
604 struct nd_pfxrouter *pfr, *next;
605 int s;
606
607 s = splnet();
608 /* unlink ndpr_entry from nd_prefix list */
609 LIST_REMOVE(pr, ndpr_entry);
610 splx(s);
611
612 /* free list of routers that adversed the prefix */
826
827 return 0;
828}
829
830void
831prelist_remove(pr)
832 struct nd_prefix *pr;
833{
834 struct nd_pfxrouter *pfr, *next;
835 int s;
836
837 s = splnet();
838 /* unlink ndpr_entry from nd_prefix list */
839 LIST_REMOVE(pr, ndpr_entry);
840 splx(s);
841
842 /* free list of routers that adversed the prefix */
613 for (pfr = LIST_FIRST(&pr->ndpr_advrtrs); pfr; pfr = next) {
614 next = LIST_NEXT(pfr, pfr_entry);
843 for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
844 next = pfr->pfr_next;
615
616 free(pfr, M_IP6NDP);
617 }
618 free(pr, M_IP6NDP);
619
620 pfxlist_onlink_check();
621}
622

--- 10 unchanged lines hidden (view full) ---

633 struct mbuf *m;
634{
635 struct in6_ifaddr *ia6 = NULL;
636 struct nd_prefix *pr;
637 int s = splnet();
638 int error = 0;
639 int auth;
640 struct in6_addrlifetime *lt6;
845
846 free(pfr, M_IP6NDP);
847 }
848 free(pr, M_IP6NDP);
849
850 pfxlist_onlink_check();
851}
852

--- 10 unchanged lines hidden (view full) ---

863 struct mbuf *m;
864{
865 struct in6_ifaddr *ia6 = NULL;
866 struct nd_prefix *pr;
867 int s = splnet();
868 int error = 0;
869 int auth;
870 struct in6_addrlifetime *lt6;
871 u_char onlink; /* Mobile IPv6 */
641
642 auth = 0;
643 if (m) {
644 /*
645 * Authenticity for NA consists authentication for
646 * both IP header and IP datagrams, doesn't it ?
647 */
648#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
649 auth = (m->m_flags & M_AUTHIPHDR
650 && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
651#endif
652 }
653
654 if ((pr = prefix_lookup(new)) != NULL) {
655 if (pr->ndpr_ifp != new->ndpr_ifp) {
656 error = EADDRNOTAVAIL;
657 goto end;
658 }
872
873 auth = 0;
874 if (m) {
875 /*
876 * Authenticity for NA consists authentication for
877 * both IP header and IP datagrams, doesn't it ?
878 */
879#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
880 auth = (m->m_flags & M_AUTHIPHDR
881 && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
882#endif
883 }
884
885 if ((pr = prefix_lookup(new)) != NULL) {
886 if (pr->ndpr_ifp != new->ndpr_ifp) {
887 error = EADDRNOTAVAIL;
888 goto end;
889 }
890
659 /* update prefix information */
660 pr->ndpr_flags = new->ndpr_flags;
661 pr->ndpr_vltime = new->ndpr_vltime;
662 pr->ndpr_pltime = new->ndpr_pltime;
663 pr->ndpr_preferred = new->ndpr_preferred;
664 pr->ndpr_expire = new->ndpr_expire;
665
666 /*

--- 35 unchanged lines hidden (view full) ---

702 goto noautoconf1;
703 }
704
705 lt6 = &ia6->ia6_lifetime;
706
707 /* address lifetime <= prefix lifetime */
708 lt6->ia6t_vltime = new->ndpr_vltime;
709 lt6->ia6t_pltime = new->ndpr_pltime;
891 /* update prefix information */
892 pr->ndpr_flags = new->ndpr_flags;
893 pr->ndpr_vltime = new->ndpr_vltime;
894 pr->ndpr_pltime = new->ndpr_pltime;
895 pr->ndpr_preferred = new->ndpr_preferred;
896 pr->ndpr_expire = new->ndpr_expire;
897
898 /*

--- 35 unchanged lines hidden (view full) ---

934 goto noautoconf1;
935 }
936
937 lt6 = &ia6->ia6_lifetime;
938
939 /* address lifetime <= prefix lifetime */
940 lt6->ia6t_vltime = new->ndpr_vltime;
941 lt6->ia6t_pltime = new->ndpr_pltime;
710 in6_init_address_ltimes(new, lt6);
942 in6_init_address_ltimes(new, lt6, 1);
711 } else {
943 } else {
712#define TWOHOUR (120*60)
944#define TWOHOUR (120*60)
713 /*
714 * We have seen the prefix before, and we have added
715 * interface address in the past. We still have
716 * the interface address assigned.
717 *
718 * update address lifetime based on RFC 2462
719 * 5.5.3 (e).
720 */
721 int update = 0;
722
723 lt6 = &ia6->ia6_lifetime;
724
945 /*
946 * We have seen the prefix before, and we have added
947 * interface address in the past. We still have
948 * the interface address assigned.
949 *
950 * update address lifetime based on RFC 2462
951 * 5.5.3 (e).
952 */
953 int update = 0;
954
955 lt6 = &ia6->ia6_lifetime;
956
725 /*
726 * update to RFC 2462 5.5.3 (e) from Jim Bound,
727 * (ipng 6712)
728 */
957#if 0 /* RFC 2462 5.5.3 (e) */
958 lt6->ia6t_pltime = new->ndpr_pltime;
729 if (TWOHOUR < new->ndpr_vltime
959 if (TWOHOUR < new->ndpr_vltime
960 || lt6pr->nd < new->ndpr_vltime) {
961 lt6->ia6t_vltime = new->ndpr_vltime;
962 update++;
963 } else if (auth
964 && lt6->ia6t_vltime <= TWOHOUR0
965 && new->ndpr_vltime <= lt6->ia6t_vltime) {
966 lt6->ia6t_vltime = new->ndpr_vltime;
967 update++;
968 } else {
969 lt6->ia6t_vltime = TWOHOUR;
970 update++;
971 }
972
973 /* 2 hour rule is not imposed for pref lifetime */
974 new->ndpr_apltime = new->ndpr_pltime;
975 lt6->ia6t_pltime = new->ndpr_pltime;
976#else /* update from Jim Bound, (ipng 6712) */
977 if (TWOHOUR < new->ndpr_vltime
730 || lt6->ia6t_vltime < new->ndpr_vltime) {
731 lt6->ia6t_vltime = new->ndpr_vltime;
732 update++;
733 } else if (auth) {
734 lt6->ia6t_vltime = new->ndpr_vltime;
735 update++;
736 }
737
738 /* jim bound rule is not imposed for pref lifetime */
739 lt6->ia6t_pltime = new->ndpr_pltime;
978 || lt6->ia6t_vltime < new->ndpr_vltime) {
979 lt6->ia6t_vltime = new->ndpr_vltime;
980 update++;
981 } else if (auth) {
982 lt6->ia6t_vltime = new->ndpr_vltime;
983 update++;
984 }
985
986 /* jim bound rule is not imposed for pref lifetime */
987 lt6->ia6t_pltime = new->ndpr_pltime;
740
741 update++;
742 if (update)
743 in6_init_address_ltimes(new, lt6);
988#endif
989 in6_init_address_ltimes(new, lt6, update);
744 }
745
746 noautoconf1:
747
990 }
991
992 noautoconf1:
993
994#if 0
995 /* address lifetime expire processing, RFC 2462 5.5.4. */
996 if (pr->ndpr_preferred && pr->ndpr_preferred < time_second) {
997 struct in6_ifaddr *ia6;
998
999 ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
1000 if (ia6)
1001 ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
1002 }
1003#endif
1004
1005 onlink = pr->ndpr_statef_onlink; /* Mobile IPv6 */
1006
748 if (dr && pfxrtr_lookup(pr, dr) == NULL)
749 pfxrtr_add(pr, dr);
1007 if (dr && pfxrtr_lookup(pr, dr) == NULL)
1008 pfxrtr_add(pr, dr);
1009
750 } else {
751 int error_tmp;
752
753 if (new->ndpr_vltime == 0) goto end;
754
755 bzero(&new->ndpr_addr, sizeof(struct in6_addr));
756
757 /*

--- 16 unchanged lines hidden (view full) ---

774 /* set onlink bit if an interface route is configured */
775 new->ndpr_statef_onlink = (ia6->ia_flags & IFA_ROUTE) ? 1 : 0;
776
777 lt6 = &ia6->ia6_lifetime;
778
779 /* address lifetime <= prefix lifetime */
780 lt6->ia6t_vltime = new->ndpr_vltime;
781 lt6->ia6t_pltime = new->ndpr_pltime;
1010 } else {
1011 int error_tmp;
1012
1013 if (new->ndpr_vltime == 0) goto end;
1014
1015 bzero(&new->ndpr_addr, sizeof(struct in6_addr));
1016
1017 /*

--- 16 unchanged lines hidden (view full) ---

1034 /* set onlink bit if an interface route is configured */
1035 new->ndpr_statef_onlink = (ia6->ia_flags & IFA_ROUTE) ? 1 : 0;
1036
1037 lt6 = &ia6->ia6_lifetime;
1038
1039 /* address lifetime <= prefix lifetime */
1040 lt6->ia6t_vltime = new->ndpr_vltime;
1041 lt6->ia6t_pltime = new->ndpr_pltime;
782 in6_init_address_ltimes(new, lt6);
1042 in6_init_address_ltimes(new, lt6, 1);
783
784 noautoconf2:
785 error_tmp = prelist_add(new, dr);
786 error = error_tmp ? error_tmp : error;
787 }
788
789 end:
790 splx(s);
791 return error;
792}
793
794/*
1043
1044 noautoconf2:
1045 error_tmp = prelist_add(new, dr);
1046 error = error_tmp ? error_tmp : error;
1047 }
1048
1049 end:
1050 splx(s);
1051 return error;
1052}
1053
1054/*
1055 * A supplement function used in the on-link detection below;
1056 * detect if a given prefix has a (probably) reachable advertising router.
1057 * XXX: lengthy function name...
1058 */
1059struct nd_pfxrouter *
1060find_pfxlist_reachable_router(pr)
1061 struct nd_prefix *pr;
1062{
1063 struct nd_pfxrouter *pfxrtr;
1064 struct rtentry *rt;
1065 struct llinfo_nd6 *ln;
1066
1067 for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1068 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1069 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1070 pfxrtr->router->ifp)) &&
1071 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1072 ND6_IS_LLINFO_PROBREACH(ln))
1073 break; /* found */
1074 }
1075
1076 return(pfxrtr);
1077
1078}
1079
1080/*
795 * Check if each prefix in the prefix list has at least one available router
1081 * Check if each prefix in the prefix list has at least one available router
796 * that advertised the prefix.
797 * If the check fails, the prefix may be off-link because, for example,
1082 * that advertised the prefix (A router is "available" if its neighbor cache
1083 * entry has reachable or probably reachable).
1084 * If the check fails, the prefix may be off-link, because, for example,
798 * we have moved from the network but the lifetime of the prefix has not
799 * been expired yet. So we should not use the prefix if there is another
800 * prefix that has an available router.
1085 * we have moved from the network but the lifetime of the prefix has not
1086 * been expired yet. So we should not use the prefix if there is another
1087 * prefix that has an available router.
801 * But if there is no prefix that has an availble router, we still regards
1088 * But if there is no prefix that has an available router, we still regards
802 * all the prefixes as on-link. This is because we can't tell if all the
803 * routers are simply dead or if we really moved from the network and there
804 * is no router around us.
805 */
1089 * all the prefixes as on-link. This is because we can't tell if all the
1090 * routers are simply dead or if we really moved from the network and there
1091 * is no router around us.
1092 */
806static void
1093void
807pfxlist_onlink_check()
808{
809 struct nd_prefix *pr;
810
1094pfxlist_onlink_check()
1095{
1096 struct nd_prefix *pr;
1097
811 LIST_FOREACH(pr, &nd_prefix, ndpr_entry)
812 if (!LIST_EMPTY(&pr->ndpr_advrtrs)) /* pr has an available router */
1098 /*
1099 * Check if there is a prefix that has a reachable advertising
1100 * router.
1101 */
1102 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1103 if (find_pfxlist_reachable_router(pr))
813 break;
1104 break;
1105 }
814
815 if (pr) {
816 /*
1106
1107 if (pr) {
1108 /*
817 * There is at least one prefix that has a router. First,
818 * detach prefixes which has no advertising router and then
819 * attach other prefixes. The order is important since an
820 * attached prefix and a detached prefix may have a same
821 * interface route.
1109 * There is at least one prefix that has a reachable router.
1110 * First, detach prefixes which has no reachable advertising
1111 * router and then attach other prefixes.
1112 * The order is important since an attached prefix and a
1113 * detached prefix may have a same interface route.
822 */
1114 */
823 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
824 if (LIST_EMPTY(&pr->ndpr_advrtrs) &&
1115 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1116 if (find_pfxlist_reachable_router(pr) == NULL &&
825 pr->ndpr_statef_onlink) {
826 pr->ndpr_statef_onlink = 0;
827 nd6_detach_prefix(pr);
828 }
829 }
1117 pr->ndpr_statef_onlink) {
1118 pr->ndpr_statef_onlink = 0;
1119 nd6_detach_prefix(pr);
1120 }
1121 }
830 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
831 if (!LIST_EMPTY(&pr->ndpr_advrtrs) &&
832 pr->ndpr_statef_onlink == 0)
1122 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1123 if (find_pfxlist_reachable_router(pr) &&
1124 pr->ndpr_statef_onlink == 0)
833 nd6_attach_prefix(pr);
834 }
1125 nd6_attach_prefix(pr);
1126 }
835 } else {
836 /* there is no prefix that has a router */
837 LIST_FOREACH(pr, &nd_prefix, ndpr_entry)
1127 }
1128 else {
1129 /* there is no prefix that has a reachable router */
1130 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next)
838 if (pr->ndpr_statef_onlink == 0)
839 nd6_attach_prefix(pr);
840 }
841}
842
843static void
844nd6_detach_prefix(pr)
845 struct nd_prefix *pr;

--- 53 unchanged lines hidden (view full) ---

899 */
900 ifa = ifaof_ifpforaddr((struct sockaddr *)&pr->ndpr_prefix,
901 pr->ndpr_ifp);
902 if (ifa == NULL) {
903 log(LOG_ERR,
904 "nd6_attach_prefix: failed to find any ifaddr"
905 " to add route for a prefix(%s/%d)\n",
906 ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen);
1131 if (pr->ndpr_statef_onlink == 0)
1132 nd6_attach_prefix(pr);
1133 }
1134}
1135
1136static void
1137nd6_detach_prefix(pr)
1138 struct nd_prefix *pr;

--- 53 unchanged lines hidden (view full) ---

1192 */
1193 ifa = ifaof_ifpforaddr((struct sockaddr *)&pr->ndpr_prefix,
1194 pr->ndpr_ifp);
1195 if (ifa == NULL) {
1196 log(LOG_ERR,
1197 "nd6_attach_prefix: failed to find any ifaddr"
1198 " to add route for a prefix(%s/%d)\n",
1199 ip6_sprintf(&pr->ndpr_addr), pr->ndpr_plen);
907 } else {
1200 }
1201 else {
908 int e;
909 struct sockaddr_in6 mask6;
910
911 bzero(&mask6, sizeof(mask6));
912 mask6.sin6_family = AF_INET6;
913 mask6.sin6_len = sizeof(mask6);
914 mask6.sin6_addr = pr->ndpr_mask;
915 e = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,

--- 34 unchanged lines hidden (view full) ---

950 struct ifaddr *ifa;
951 struct in6_ifaddr *ia, *ib, *oia;
952 int s, error;
953 struct in6_addr mask;
954
955 in6_len2mask(&mask, prefixlen);
956
957 /* find link-local address (will be interface ID) */
1202 int e;
1203 struct sockaddr_in6 mask6;
1204
1205 bzero(&mask6, sizeof(mask6));
1206 mask6.sin6_family = AF_INET6;
1207 mask6.sin6_len = sizeof(mask6);
1208 mask6.sin6_addr = pr->ndpr_mask;
1209 e = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,

--- 34 unchanged lines hidden (view full) ---

1244 struct ifaddr *ifa;
1245 struct in6_ifaddr *ia, *ib, *oia;
1246 int s, error;
1247 struct in6_addr mask;
1248
1249 in6_len2mask(&mask, prefixlen);
1250
1251 /* find link-local address (will be interface ID) */
958 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp);
1252 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);/* 0 is OK? */
959 if (ifa)
960 ib = (struct in6_ifaddr *)ifa;
961 else
962 return NULL;
963
1253 if (ifa)
1254 ib = (struct in6_ifaddr *)ifa;
1255 else
1256 return NULL;
1257
1258#if 0 /* don't care link local addr state, and always do DAD */
1259 /* if link-local address is not eligible, do not autoconfigure. */
1260 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
1261 printf("in6_ifadd: link-local address not ready\n");
1262 return NULL;
1263 }
1264#endif
1265
964 /* prefixlen + ifidlen must be equal to 128 */
965 if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) {
966 log(LOG_ERR, "in6_ifadd: wrong prefixlen for %s"
967 "(prefix=%d ifid=%d)\n", if_name(ifp),
968 prefixlen,
969 128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr));
970 return NULL;
971 }
972
973 /* make ifaddr */
974 ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT);
975 if (ia == NULL) {
976 printf("ENOBUFS in in6_ifadd %d\n", __LINE__);
977 return NULL;
978 }
979
980 bzero((caddr_t)ia, sizeof(*ia));
981 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1266 /* prefixlen + ifidlen must be equal to 128 */
1267 if (prefixlen != in6_mask2len(&ib->ia_prefixmask.sin6_addr)) {
1268 log(LOG_ERR, "in6_ifadd: wrong prefixlen for %s"
1269 "(prefix=%d ifid=%d)\n", if_name(ifp),
1270 prefixlen,
1271 128 - in6_mask2len(&ib->ia_prefixmask.sin6_addr));
1272 return NULL;
1273 }
1274
1275 /* make ifaddr */
1276 ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_DONTWAIT);
1277 if (ia == NULL) {
1278 printf("ENOBUFS in in6_ifadd %d\n", __LINE__);
1279 return NULL;
1280 }
1281
1282 bzero((caddr_t)ia, sizeof(*ia));
1283 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
982 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1284 if (ifp->if_flags & IFF_POINTOPOINT)
1285 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1286 else
1287 ia->ia_ifa.ifa_dstaddr = NULL;
983 ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
984 ia->ia_ifp = ifp;
985
986 /* link to in6_ifaddr */
987 if ((oia = in6_ifaddr) != NULL) {
988 for( ; oia->ia_next; oia = oia->ia_next)
989 continue;
990 oia->ia_next = ia;
1288 ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
1289 ia->ia_ifp = ifp;
1290
1291 /* link to in6_ifaddr */
1292 if ((oia = in6_ifaddr) != NULL) {
1293 for( ; oia->ia_next; oia = oia->ia_next)
1294 continue;
1295 oia->ia_next = ia;
991 } else
1296 } else {
1297 /*
1298 * This should be impossible, since we have at least one
1299 * link-local address (see the beginning of this function).
1300 * XXX: should we rather panic here?
1301 */
1302 printf("in6_ifadd: in6_ifaddr is NULL (impossible!)\n");
992 in6_ifaddr = ia;
1303 in6_ifaddr = ia;
1304 }
1305 /* gain a refcnt for the link from in6_ifaddr */
1306 ia->ia_ifa.ifa_refcnt++;
993
994 /* link to if_addrlist */
1307
1308 /* link to if_addrlist */
995 if (!TAILQ_EMPTY(&ifp->if_addrlist)) {
996 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
997 ifa_list);
998 }
1309 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1310 /* gain another refcnt for the link from if_addrlist */
1311 ia->ia_ifa.ifa_refcnt++;
999
1000 /* new address */
1001 ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
1002 ia->ia_addr.sin6_family = AF_INET6;
1003 /* prefix */
1004 bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr));
1005 ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1006 ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];

--- 101 unchanged lines hidden (view full) ---

1108 }
1109
1110 if (ia->ia_flags & IFA_ROUTE) {
1111 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1112 ia->ia_flags &= ~IFA_ROUTE;
1113 }
1114
1115 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1312
1313 /* new address */
1314 ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
1315 ia->ia_addr.sin6_family = AF_INET6;
1316 /* prefix */
1317 bcopy(in6, &ia->ia_addr.sin6_addr, sizeof(ia->ia_addr.sin6_addr));
1318 ia->ia_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1319 ia->ia_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];

--- 101 unchanged lines hidden (view full) ---

1421 }
1422
1423 if (ia->ia_flags & IFA_ROUTE) {
1424 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1425 ia->ia_flags &= ~IFA_ROUTE;
1426 }
1427
1428 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
1429 IFAFREE(&ia->ia_ifa);
1116
1117 /* lladdr is never deleted */
1118 oia = ia;
1119 if (oia == (ia = in6_ifaddr))
1120 in6_ifaddr = ia->ia_next;
1121 else {
1122 while (ia->ia_next && (ia->ia_next != oia))
1123 ia = ia->ia_next;

--- 34 unchanged lines hidden (view full) ---

1158 ndpr->ndpr_expire = 0;
1159 else
1160 ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
1161
1162 return 0;
1163}
1164
1165static void
1430
1431 /* lladdr is never deleted */
1432 oia = ia;
1433 if (oia == (ia = in6_ifaddr))
1434 in6_ifaddr = ia->ia_next;
1435 else {
1436 while (ia->ia_next && (ia->ia_next != oia))
1437 ia = ia->ia_next;

--- 34 unchanged lines hidden (view full) ---

1472 ndpr->ndpr_expire = 0;
1473 else
1474 ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
1475
1476 return 0;
1477}
1478
1479static void
1166in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
1480in6_init_address_ltimes(struct nd_prefix *new,
1481 struct in6_addrlifetime *lt6,
1482 int update_vltime)
1167{
1168
1483{
1484
1169 /* init ia6t_expire */
1170 if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
1171 lt6->ia6t_expire = 0;
1172 else {
1173 lt6->ia6t_expire = time_second;
1174 lt6->ia6t_expire += lt6->ia6t_vltime;
1485 /* Valid lifetime must not be updated unless explicitly specified. */
1486 if (update_vltime) {
1487 /* init ia6t_expire */
1488 if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
1489 lt6->ia6t_expire = 0;
1490 else {
1491 lt6->ia6t_expire = time_second;
1492 lt6->ia6t_expire += lt6->ia6t_vltime;
1493 }
1494 /* Ensure addr lifetime <= prefix lifetime. */
1495 if (new->ndpr_expire && lt6->ia6t_expire &&
1496 new->ndpr_expire < lt6->ia6t_expire)
1497 lt6->ia6t_expire = new->ndpr_expire;
1175 }
1498 }
1499
1176 /* init ia6t_preferred */
1177 if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1178 lt6->ia6t_preferred = 0;
1179 else {
1180 lt6->ia6t_preferred = time_second;
1181 lt6->ia6t_preferred += lt6->ia6t_pltime;
1182 }
1500 /* init ia6t_preferred */
1501 if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
1502 lt6->ia6t_preferred = 0;
1503 else {
1504 lt6->ia6t_preferred = time_second;
1505 lt6->ia6t_preferred += lt6->ia6t_pltime;
1506 }
1183 /* ensure addr lifetime <= prefix lifetime */
1184 if (new->ndpr_expire && lt6->ia6t_expire &&
1185 new->ndpr_expire < lt6->ia6t_expire)
1186 lt6->ia6t_expire = new->ndpr_expire;
1507 /* Ensure addr lifetime <= prefix lifetime. */
1187 if (new->ndpr_preferred && lt6->ia6t_preferred
1188 && new->ndpr_preferred < lt6->ia6t_preferred)
1189 lt6->ia6t_preferred = new->ndpr_preferred;
1190}
1191
1192/*
1193 * Delete all the routing table entries that use the specified gateway.
1194 * XXX: this function causes search through all entries of routing table, so

--- 40 unchanged lines hidden (view full) ---

1235 */
1236 if ((rt->rt_flags & RTF_HOST) == 0)
1237 return(0);
1238
1239 return(rtrequest(RTM_DELETE, rt_key(rt),
1240 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0));
1241#undef SIN6
1242}
1508 if (new->ndpr_preferred && lt6->ia6t_preferred
1509 && new->ndpr_preferred < lt6->ia6t_preferred)
1510 lt6->ia6t_preferred = new->ndpr_preferred;
1511}
1512
1513/*
1514 * Delete all the routing table entries that use the specified gateway.
1515 * XXX: this function causes search through all entries of routing table, so

--- 40 unchanged lines hidden (view full) ---

1556 */
1557 if ((rt->rt_flags & RTF_HOST) == 0)
1558 return(0);
1559
1560 return(rtrequest(RTM_DELETE, rt_key(rt),
1561 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0));
1562#undef SIN6
1563}
1564
1565int
1566nd6_setdefaultiface(ifindex)
1567 int ifindex;
1568{
1569 int error = 0;
1570
1571 if (ifindex < 0 || if_index < ifindex)
1572 return(EINVAL);
1573
1574 if (nd6_defifindex != ifindex) {
1575 nd6_defifindex = ifindex;
1576 if (nd6_defifindex > 0)
1577 nd6_defifp = ifindex2ifnet[nd6_defifindex];
1578 else
1579 nd6_defifp = NULL;
1580
1581 /*
1582 * If the Default Router List is empty, install a route
1583 * to the specified interface as default or remove the default
1584 * route when the default interface becomes canceled.
1585 * The check for the queue is actually redundant, but
1586 * we do this here to avoid re-install the default route
1587 * if the list is NOT empty.
1588 */
1589 if (TAILQ_FIRST(&nd_defrouter) == NULL)
1590 defrouter_select();
1591
1592 /*
1593 * Our current implementation assumes one-to-one maping between
1594 * interfaces and links, so it would be natural to use the
1595 * default interface as the default link.
1596 */
1597 scope6_setdefault(nd6_defifp);
1598 }
1599
1600 return(error);
1601}