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} |
|