1 /* $KAME: nd6_rtr.c,v 1.30 2000/03/21 11:37:31 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/malloc.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
39 #include <sys/kernel.h>
40 #include <sys/errno.h>
41 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
42 #include <sys/ioctl.h>
44 #include <sys/syslog.h>
47 #include <net/if_types.h>
48 #include <net/if_dl.h>
49 #include <net/route.h>
50 #include <net/radix.h>
52 #include <netinet/in.h>
53 #include <netinet6/in6_var.h>
54 #include <netinet/ip6.h>
55 #include <netinet6/ip6_var.h>
56 #include <netinet6/nd6.h>
57 #include <netinet/icmp6.h>
60 #include <netinet6/mip6.h>
63 #include <net/net_osdep.h>
65 #define SDL(s) ((struct sockaddr_dl *)s)
67 static struct nd_defrouter
*defrtrlist_update
__P((struct nd_defrouter
*));
68 static int prelist_add
__P((struct nd_prefix
*, struct nd_defrouter
*));
69 /* static struct nd_prefix *prefix_lookup __P((struct nd_prefix *)); XXXYYY */
70 static struct in6_ifaddr
*in6_ifadd
__P((struct ifnet
*, struct in6_addr
*,
71 struct in6_addr
*, int));
72 /*static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
73 struct nd_defrouter *)); XXXYYYY */
74 static void pfxrtr_add
__P((struct nd_prefix
*, struct nd_defrouter
*));
75 static void pfxrtr_del
__P((struct nd_pfxrouter
*));
76 /*static struct nd_pfxrouter *find_pfxlist_reachable_router __P((struct nd_prefix *)); XXXYYY */
77 static void nd6_detach_prefix
__P((struct nd_prefix
*));
78 static void nd6_attach_prefix
__P((struct nd_prefix
*));
79 /* static void defrouter_addifreq __P((struct ifnet *)); XXXYYY */
81 static void in6_init_address_ltimes
__P((struct nd_prefix
*ndpr
,
82 struct in6_addrlifetime
*lt6
,
85 static int rt6_deleteroute
__P((struct radix_node
*, void *));
87 extern int nd6_recalc_reachtm_interval
;
89 struct ifnet
*nd6_defifp
;
94 void (*mip6_select_defrtr_hook
)(void) = NULL
;
95 struct nd_prefix
* (*mip6_get_home_prefix_hook
)(void) = NULL
;
96 void (*mip6_prelist_update_hook
)(struct nd_prefix
*pr
,
97 struct nd_defrouter
*dr
) = NULL
;
98 void (*mip6_probe_pfxrtrs_hook
)(void) = NULL
;
99 void (*mip6_store_advint_hook
)(struct nd_opt_advint
*ai
,
100 struct nd_defrouter
*dr
) = NULL
;
101 int (*mip6_get_md_state_hook
)(void) = 0;
102 void (*mip6_minus_a_case_hook
)(struct nd_prefix
*) = NULL
;
106 * Receive Router Solicitation Message - just for routers.
107 * Router solicitation/advertisement is mostly managed by userland program
108 * (rtadvd) so here we have no function like nd6_ra_output().
113 nd6_rs_input(m
, off
, icmp6len
)
117 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
118 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
119 struct nd_router_solicit
*nd_rs
;
120 struct in6_addr saddr6
= ip6
->ip6_src
;
122 struct in6_addr daddr6
= ip6
->ip6_dst
;
127 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)NULL
;
128 struct llinfo_nd6
*ln
= (struct llinfo_nd6
*)NULL
;
129 struct rtentry
*rt
= NULL
;
132 union nd_opts ndopts
;
134 /* If I'm not a router, ignore it. */
135 if (ip6_accept_rtadv
!= 0 || ip6_forwarding
!= 1)
139 if (ip6
->ip6_hlim
!= 255) {
141 "nd6_rs_input: invalid hlim %d\n", ip6
->ip6_hlim
);
146 * Don't update the neighbor cache, if src = ::.
147 * This indicates that the src has no IP address assigned yet.
149 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6
))
152 #ifndef PULLDOWN_TEST
153 IP6_EXTHDR_CHECK(m
, off
, icmp6len
,);
154 nd_rs
= (struct nd_router_solicit
*)((caddr_t
)ip6
+ off
);
156 IP6_EXTHDR_GET(nd_rs
, struct nd_router_solicit
*, m
, off
, icmp6len
);
158 icmp6stat
.icp6s_tooshort
++;
163 icmp6len
-= sizeof(*nd_rs
);
164 nd6_option_init(nd_rs
+ 1, icmp6len
, &ndopts
);
165 if (nd6_options(&ndopts
) < 0) {
166 log(LOG_INFO
, "nd6_rs_input: invalid ND option, ignored\n");
170 if (ndopts
.nd_opts_src_lladdr
) {
171 lladdr
= (char *)(ndopts
.nd_opts_src_lladdr
+ 1);
172 lladdrlen
= ndopts
.nd_opts_src_lladdr
->nd_opt_len
<< 3;
175 if (lladdr
&& ((ifp
->if_addrlen
+ 2 + 7) & ~7) != lladdrlen
) {
177 "nd6_rs_input: lladdrlen mismatch for %s "
178 "(if %d, RS packet %d)\n",
179 ip6_sprintf(&saddr6
), ifp
->if_addrlen
, lladdrlen
- 2);
182 nd6_cache_lladdr(ifp
, &saddr6
, lladdr
, lladdrlen
, ND_ROUTER_SOLICIT
, 0);
189 * Receive Router Advertisement Message.
192 * TODO: on-link bit on prefix information
193 * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
196 nd6_ra_input(m
, off
, icmp6len
)
200 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
201 struct nd_ifinfo
*ndi
= &nd_ifinfo
[ifp
->if_index
];
202 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
203 struct nd_router_advert
*nd_ra
;
204 struct in6_addr saddr6
= ip6
->ip6_src
;
206 struct in6_addr daddr6
= ip6
->ip6_dst
;
207 int flags
; /* = nd_ra->nd_ra_flags_reserved; */
208 int is_managed
= ((flags
& ND_RA_FLAG_MANAGED
) != 0);
209 int is_other
= ((flags
& ND_RA_FLAG_OTHER
) != 0);
211 union nd_opts ndopts
;
212 struct nd_defrouter
*dr
;
214 if (ip6_accept_rtadv
== 0)
217 if (ip6
->ip6_hlim
!= 255) {
219 "nd6_ra_input: invalid hlim %d\n", ip6
->ip6_hlim
);
223 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6
)) {
225 "nd6_ra_input: src %s is not link-local\n",
226 ip6_sprintf(&saddr6
));
230 #ifndef PULLDOWN_TEST
231 IP6_EXTHDR_CHECK(m
, off
, icmp6len
,);
232 nd_ra
= (struct nd_router_advert
*)((caddr_t
)ip6
+ off
);
234 IP6_EXTHDR_GET(nd_ra
, struct nd_router_advert
*, m
, off
, icmp6len
);
236 icmp6stat
.icp6s_tooshort
++;
241 icmp6len
-= sizeof(*nd_ra
);
242 nd6_option_init(nd_ra
+ 1, icmp6len
, &ndopts
);
243 if (nd6_options(&ndopts
) < 0) {
244 log(LOG_INFO
, "nd6_ra_input: invalid ND option, ignored\n");
249 struct nd_defrouter dr0
;
250 u_int32_t advreachable
= nd_ra
->nd_ra_reachable
;
251 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
252 long time_second
= time
.tv_sec
;
256 dr0
.flags
= nd_ra
->nd_ra_flags_reserved
;
257 dr0
.rtlifetime
= ntohs(nd_ra
->nd_ra_router_lifetime
);
258 dr0
.expire
= time_second
+ dr0
.rtlifetime
;
260 dr0
.advint
= 0; /* Mobile IPv6 */
261 dr0
.advint_expire
= 0; /* Mobile IPv6 */
262 dr0
.advints_lost
= 0; /* Mobile IPv6 */
263 /* unspecified or not? (RFC 2461 6.3.4) */
266 if (advreachable
<= MAX_REACHABLE_TIME
&&
267 ndi
->basereachable
!= advreachable
) {
268 ndi
->basereachable
= advreachable
;
269 ndi
->reachable
= ND_COMPUTE_RTIME(ndi
->basereachable
);
270 ndi
->recalctm
= nd6_recalc_reachtm_interval
; /* reset */
273 if (nd_ra
->nd_ra_retransmit
)
274 ndi
->retrans
= ntohl(nd_ra
->nd_ra_retransmit
);
275 if (nd_ra
->nd_ra_curhoplimit
)
276 ndi
->chlim
= nd_ra
->nd_ra_curhoplimit
;
277 dr
= defrtrlist_update(&dr0
);
283 if (ndopts
.nd_opts_pi
) {
284 struct nd_opt_hdr
*pt
;
285 struct nd_opt_prefix_info
*pi
;
288 for (pt
= (struct nd_opt_hdr
*)ndopts
.nd_opts_pi
;
289 pt
<= (struct nd_opt_hdr
*)ndopts
.nd_opts_pi_end
;
290 pt
= (struct nd_opt_hdr
*)((caddr_t
)pt
+
291 (pt
->nd_opt_len
<< 3))) {
292 if (pt
->nd_opt_type
!= ND_OPT_PREFIX_INFORMATION
)
294 pi
= (struct nd_opt_prefix_info
*)pt
;
296 if (pi
->nd_opt_pi_len
!= 4) {
297 log(LOG_INFO
, "nd6_ra_input: invalid option "
298 "len %d for prefix information option, "
299 "ignored\n", pi
->nd_opt_pi_len
);
303 if (128 < pi
->nd_opt_pi_prefix_len
) {
304 log(LOG_INFO
, "nd6_ra_input: invalid prefix "
305 "len %d for prefix information option, "
306 "ignored\n", pi
->nd_opt_pi_prefix_len
);
310 if (IN6_IS_ADDR_MULTICAST(&pi
->nd_opt_pi_prefix
)
311 || IN6_IS_ADDR_LINKLOCAL(&pi
->nd_opt_pi_prefix
)) {
312 log(LOG_INFO
, "nd6_ra_input: invalid prefix "
314 ip6_sprintf(&pi
->nd_opt_pi_prefix
));
318 /* aggregatable unicast address, rfc2374 */
319 if ((pi
->nd_opt_pi_prefix
.s6_addr8
[0] & 0xe0) == 0x20
320 && pi
->nd_opt_pi_prefix_len
!= 64) {
321 log(LOG_INFO
, "nd6_ra_input: invalid prefixlen "
322 "%d for rfc2374 prefix %s, ignored\n",
323 pi
->nd_opt_pi_prefix_len
,
324 ip6_sprintf(&pi
->nd_opt_pi_prefix
));
328 bzero(&pr
, sizeof(pr
));
329 pr
.ndpr_prefix
.sin6_family
= AF_INET6
;
330 pr
.ndpr_prefix
.sin6_len
= sizeof(pr
.ndpr_prefix
);
331 pr
.ndpr_prefix
.sin6_addr
= pi
->nd_opt_pi_prefix
;
332 pr
.ndpr_ifp
= (struct ifnet
*)m
->m_pkthdr
.rcvif
;
334 pr
.ndpr_raf_onlink
= (pi
->nd_opt_pi_flags_reserved
&
335 ND_OPT_PI_FLAG_ONLINK
) ? 1 : 0;
336 pr
.ndpr_raf_auto
= (pi
->nd_opt_pi_flags_reserved
&
337 ND_OPT_PI_FLAG_AUTO
) ? 1 : 0;
338 pr
.ndpr_plen
= pi
->nd_opt_pi_prefix_len
;
339 pr
.ndpr_vltime
= ntohl(pi
->nd_opt_pi_valid_time
);
341 ntohl(pi
->nd_opt_pi_preferred_time
);
343 if (in6_init_prefix_ltimes(&pr
))
344 continue; /* prefix lifetime init failed */
346 (void)prelist_update(&pr
, dr
, m
);
353 if (ndopts
.nd_opts_mtu
&& ndopts
.nd_opts_mtu
->nd_opt_mtu_len
== 1) {
354 u_int32_t mtu
= ntohl(ndopts
.nd_opts_mtu
->nd_opt_mtu_mtu
);
357 if (mtu
< IPV6_MMTU
) {
358 log(LOG_INFO
, "nd6_ra_input: bogus mtu option "
359 "mtu=%d sent from %s, ignoring\n",
360 mtu
, ip6_sprintf(&ip6
->ip6_src
));
366 if (mtu
<= ndi
->maxmtu
) {
367 int change
= (ndi
->linkmtu
!= mtu
);
370 if (change
) /* in6_maxmtu may change */
373 log(LOG_INFO
, "nd6_ra_input: bogus mtu "
374 "mtu=%d sent from %s; "
375 "exceeds maxmtu %d, ignoring\n",
376 mtu
, ip6_sprintf(&ip6
->ip6_src
),
380 log(LOG_INFO
, "nd6_ra_input: mtu option "
381 "mtu=%d sent from %s; maxmtu unknown, "
383 mtu
, ip6_sprintf(&ip6
->ip6_src
));
396 if (ndopts
.nd_opts_src_lladdr
) {
397 lladdr
= (char *)(ndopts
.nd_opts_src_lladdr
+ 1);
398 lladdrlen
= ndopts
.nd_opts_src_lladdr
->nd_opt_len
<< 3;
401 if (lladdr
&& ((ifp
->if_addrlen
+ 2 + 7) & ~7) != lladdrlen
) {
403 "nd6_ra_input: lladdrlen mismatch for %s "
404 "(if %d, RA packet %d)\n",
405 ip6_sprintf(&saddr6
), ifp
->if_addrlen
, lladdrlen
- 2);
408 nd6_cache_lladdr(ifp
, &saddr6
, lladdr
, lladdrlen
, ND_ROUTER_ADVERT
, 0);
411 * Installing a link-layer address might change the state of the
412 * router's neighbor cache, which might also affect our on-link
413 * detection of adveritsed prefixes.
415 pfxlist_onlink_check();
419 if (mip6_store_advint_hook
) {
420 if (ndopts
.nd_opts_adv
)
421 (*mip6_store_advint_hook
)(ndopts
.nd_opts_adv
, dr
);
430 * default router list proccessing sub routines
433 defrouter_addreq(new)
434 struct nd_defrouter
*new;
436 struct sockaddr_in6 def
, mask
, gate
;
439 Bzero(&def
, sizeof(def
));
440 Bzero(&mask
, sizeof(mask
));
441 Bzero(&gate
, sizeof(gate
));
443 def
.sin6_len
= mask
.sin6_len
= gate
.sin6_len
444 = sizeof(struct sockaddr_in6
);
445 def
.sin6_family
= mask
.sin6_family
= gate
.sin6_family
= AF_INET6
;
446 gate
.sin6_addr
= new->rtaddr
;
453 (void)rtrequest(RTM_ADD
, (struct sockaddr
*)&def
,
454 (struct sockaddr
*)&gate
, (struct sockaddr
*)&mask
,
460 /* Add a route to a given interface as default */
462 defrouter_addifreq(ifp
)
465 struct sockaddr_in6 def
, mask
;
469 bzero(&def
, sizeof(def
));
470 bzero(&mask
, sizeof(mask
));
472 def
.sin6_len
= mask
.sin6_len
= sizeof(struct sockaddr_in6
);
473 def
.sin6_family
= mask
.sin6_family
= AF_INET6
;
476 * Search for an ifaddr beloging to the specified interface.
477 * XXX: An IPv6 address are required to be assigned on the interface.
479 if ((ifa
= ifaof_ifpforaddr((struct sockaddr
*)&def
, ifp
)) == NULL
) {
480 log(LOG_ERR
, /* better error? */
481 "defrouter_addifreq: failed to find an ifaddr "
482 "to install a route to interface %s\n",
487 flags
= ifa
->ifa_flags
;
488 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0)
489 flags
&= ~RTF_CLONING
;
490 if ((error
= rtrequest(RTM_ADD
, (struct sockaddr
*)&def
,
491 ifa
->ifa_addr
, (struct sockaddr
*)&mask
,
492 flags
, NULL
)) != 0) {
494 "defrouter_addifreq: failed to install a route to "
495 "interface %s (errno = %d)\n",
496 if_name(ifp
), error
);
500 struct nd_defrouter
*
501 defrouter_lookup(addr
, ifp
)
502 struct in6_addr
*addr
;
505 struct nd_defrouter
*dr
;
507 for (dr
= TAILQ_FIRST(&nd_defrouter
); dr
;
508 dr
= TAILQ_NEXT(dr
, dr_entry
)) {
509 if (dr
->ifp
== ifp
&& IN6_ARE_ADDR_EQUAL(addr
, &dr
->rtaddr
))
513 return(NULL
); /* search failed */
517 defrouter_delreq(dr
, dofree
)
518 struct nd_defrouter
*dr
;
521 struct sockaddr_in6 def
, mask
, gate
;
523 Bzero(&def
, sizeof(def
));
524 Bzero(&mask
, sizeof(mask
));
525 Bzero(&gate
, sizeof(gate
));
527 def
.sin6_len
= mask
.sin6_len
= gate
.sin6_len
528 = sizeof(struct sockaddr_in6
);
529 def
.sin6_family
= mask
.sin6_family
= gate
.sin6_family
= AF_INET6
;
530 gate
.sin6_addr
= dr
->rtaddr
;
532 rtrequest(RTM_DELETE
, (struct sockaddr
*)&def
,
533 (struct sockaddr
*)&gate
,
534 (struct sockaddr
*)&mask
,
535 RTF_GATEWAY
, (struct rtentry
**)0);
537 if (dofree
) /* XXX: necessary? */
543 struct nd_defrouter
*dr
;
545 struct nd_defrouter
*deldr
= NULL
;
546 struct nd_prefix
*pr
;
549 * Flush all the routing table entries that use the router
552 if (!ip6_forwarding
&& ip6_accept_rtadv
) {
553 /* above is a good condition? */
554 rt6_flush(&dr
->rtaddr
, dr
->ifp
);
557 if (dr
== TAILQ_FIRST(&nd_defrouter
))
558 deldr
= dr
; /* The router is primary. */
560 TAILQ_REMOVE(&nd_defrouter
, dr
, dr_entry
);
563 * Also delete all the pointers to the router in each prefix lists.
565 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
566 struct nd_pfxrouter
*pfxrtr
;
567 if ((pfxrtr
= pfxrtr_lookup(pr
, dr
)) != NULL
)
570 pfxlist_onlink_check();
573 * If the router is the primary one, choose a new one.
574 * Note that defrouter_select() will remove the current gateway
575 * from the routing table.
584 * Default Router Selection according to Section 6.3.6 of RFC 2461:
585 * 1) Routers that are reachable or probably reachable should be
587 * 2) When no routers on the list are known to be reachable or
588 * probably reachable, routers SHOULD be selected in a round-robin
590 * 3) If the Default Router List is empty, assume that all
591 * destinations are on-link.
597 int s
= splsoftnet();
601 struct nd_defrouter
*dr
, anydr
;
602 struct rtentry
*rt
= NULL
;
603 struct llinfo_nd6
*ln
= NULL
;
606 /* Mobile IPv6 alternative routine */
607 if (mip6_select_defrtr_hook
) {
608 (*mip6_select_defrtr_hook
)(); /* XXXYYY Temporary? */
612 /* End of Mobile IPv6 */
616 * Search for a (probably) reachable router from the list.
618 for (dr
= TAILQ_FIRST(&nd_defrouter
); dr
;
619 dr
= TAILQ_NEXT(dr
, dr_entry
)) {
620 if ((rt
= nd6_lookup(&dr
->rtaddr
, 0, dr
->ifp
)) &&
621 (ln
= (struct llinfo_nd6
*)rt
->rt_llinfo
) &&
622 ND6_IS_LLINFO_PROBREACH(ln
)) {
623 /* Got it, and move it to the head */
624 TAILQ_REMOVE(&nd_defrouter
, dr
, dr_entry
);
625 TAILQ_INSERT_HEAD(&nd_defrouter
, dr
, dr_entry
);
630 if ((dr
= TAILQ_FIRST(&nd_defrouter
))) {
632 * De-install the previous default gateway and install
634 * Note that if there is no reachable router in the list,
635 * the head entry will be used anyway.
636 * XXX: do we have to check the current routing table entry?
638 bzero(&anydr
, sizeof(anydr
));
639 defrouter_delreq(&anydr
, 0);
640 defrouter_addreq(dr
);
644 * The Default Router List is empty, so install the default
645 * route to an inteface.
646 * XXX: The specification does not say this mechanism should
647 * be restricted to hosts, but this would be not useful
648 * (even harmful) for routers.
650 if (!ip6_forwarding
) {
652 * De-install the current default route
655 bzero(&anydr
, sizeof(anydr
));
656 defrouter_delreq(&anydr
, 0);
659 * Install a route to the default interface
662 defrouter_addifreq(nd6_defifp
);
665 else /* noisy log? */
666 log(LOG_INFO
, "defrouter_select: "
667 "there's no default router and no default"
677 static struct nd_defrouter
*
678 defrtrlist_update(new)
679 struct nd_defrouter
*new;
681 struct nd_defrouter
*dr
, *n
;
683 int s
= splsoftnet();
688 if ((dr
= defrouter_lookup(&new->rtaddr
, new->ifp
)) != NULL
) {
690 if (new->rtlifetime
== 0) {
695 dr
->flags
= new->flags
; /* xxx flag check */
696 dr
->rtlifetime
= new->rtlifetime
;
697 dr
->expire
= new->expire
;
703 /* entry does not exist */
704 if (new->rtlifetime
== 0) {
709 n
= (struct nd_defrouter
*)_MALLOC(sizeof(*n
), M_IP6NDP
, M_NOWAIT
);
714 bzero(n
, sizeof(*n
));
718 * Insert the new router at the end of the Default Router List.
719 * If there is no other router, install it anyway. Otherwise,
720 * just continue to use the current default router.
722 TAILQ_INSERT_TAIL(&nd_defrouter
, n
, dr_entry
);
723 if (TAILQ_FIRST(&nd_defrouter
) == n
)
730 struct nd_pfxrouter
*
731 pfxrtr_lookup(pr
, dr
)
732 struct nd_prefix
*pr
;
733 struct nd_defrouter
*dr
;
735 struct nd_pfxrouter
*search
;
737 for (search
= pr
->ndpr_advrtrs
.lh_first
; search
; search
= search
->pfr_next
) {
738 if (search
->router
== dr
)
747 struct nd_prefix
*pr
;
748 struct nd_defrouter
*dr
;
750 struct nd_pfxrouter
*new;
752 new = (struct nd_pfxrouter
*)_MALLOC(sizeof(*new), M_IP6NDP
, M_NOWAIT
);
755 bzero(new, sizeof(*new));
758 LIST_INSERT_HEAD(&pr
->ndpr_advrtrs
, new, pfr_entry
);
760 pfxlist_onlink_check();
765 struct nd_pfxrouter
*pfr
;
767 LIST_REMOVE(pfr
, pfr_entry
);
768 _FREE(pfr
, M_IP6NDP
);
773 struct nd_prefix
*pr
;
775 struct nd_prefix
*search
;
777 for (search
= nd_prefix
.lh_first
; search
; search
= search
->ndpr_next
) {
778 if (pr
->ndpr_ifp
== search
->ndpr_ifp
&&
779 pr
->ndpr_plen
== search
->ndpr_plen
&&
780 in6_are_prefix_equal(&pr
->ndpr_prefix
.sin6_addr
,
781 &search
->ndpr_prefix
.sin6_addr
,
793 struct nd_prefix
*pr
;
794 struct nd_defrouter
*dr
;
796 struct nd_prefix
*new;
799 new = (struct nd_prefix
*)_MALLOC(sizeof(*new), M_IP6NDP
, M_NOWAIT
);
802 bzero(new, sizeof(*new));
806 new->ndpr_statef_onlink
= pr
->ndpr_statef_onlink
;
807 LIST_INIT(&new->ndpr_advrtrs
);
808 in6_prefixlen2mask(&new->ndpr_mask
, new->ndpr_plen
);
809 /* make prefix in the canonical form */
810 for (i
= 0; i
< 4; i
++)
811 new->ndpr_prefix
.sin6_addr
.s6_addr32
[i
] &=
812 new->ndpr_mask
.s6_addr32
[i
];
814 /* xxx ND_OPT_PI_FLAG_ONLINK processing */
821 /* link ndpr_entry to nd_prefix list */
822 LIST_INSERT_HEAD(&nd_prefix
, new, ndpr_entry
);
828 if (mip6_get_md_state_hook
) {
830 * If we are in UNDEFINED state and a router appears,
831 * select that router and change state.
832 * This case takes care of transitions from UNDEFINED
833 * to FOREIGN when the prefix is not known from before.
835 if ((*mip6_get_md_state_hook
)() == MIP6_MD_UNDEFINED
) {
836 if (mip6_select_defrtr_hook
)
837 (*mip6_select_defrtr_hook
)();
848 struct nd_prefix
*pr
;
850 struct nd_pfxrouter
*pfr
, *next
;
858 /* unlink ndpr_entry from nd_prefix list */
859 LIST_REMOVE(pr
, ndpr_entry
);
862 /* free list of routers that adversed the prefix */
863 for (pfr
= pr
->ndpr_advrtrs
.lh_first
; pfr
; pfr
= next
) {
864 next
= pfr
->pfr_next
;
866 _FREE(pfr
, M_IP6NDP
);
870 pfxlist_onlink_check();
874 * NOTE: We set address lifetime to keep
875 * address lifetime <= prefix lifetime
876 * invariant. This is to simplify on-link determination code.
877 * If onlink determination is udated, this routine may have to be updated too.
880 prelist_update(new, dr
, m
)
881 struct nd_prefix
*new;
882 struct nd_defrouter
*dr
; /* may be NULL */
885 struct in6_ifaddr
*ia6
= NULL
;
886 struct nd_prefix
*pr
;
888 int s
= splsoftnet();
894 struct in6_addrlifetime
*lt6
;
895 u_char onlink
; /* Mobile IPv6 */
900 * Authenticity for NA consists authentication for
901 * both IP header and IP datagrams, doesn't it ?
903 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
904 auth
= (m
->m_flags
& M_AUTHIPHDR
905 && m
->m_flags
& M_AUTHIPDGM
) ? 1 : 0;
909 if ((pr
= prefix_lookup(new)) != NULL
) {
910 if (pr
->ndpr_ifp
!= new->ndpr_ifp
) {
911 error
= EADDRNOTAVAIL
;
916 if (mip6_get_home_prefix_hook
) {
918 * The home prefix should be kept away from updates.
919 * XXXYYY Tunneled RA? New Home Prefix? Unless
920 * configured, the code below will be executed.
922 if (pr
== (*mip6_get_home_prefix_hook
)())
927 /* update prefix information */
928 pr
->ndpr_flags
= new->ndpr_flags
;
929 pr
->ndpr_vltime
= new->ndpr_vltime
;
930 pr
->ndpr_pltime
= new->ndpr_pltime
;
931 pr
->ndpr_preferred
= new->ndpr_preferred
;
932 pr
->ndpr_expire
= new->ndpr_expire
;
935 * RFC 2462 5.5.3 (d) or (e)
936 * We got a prefix which we have seen in the past.
938 if (!new->ndpr_raf_auto
)
941 if (IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
))
944 ia6
= in6ifa_ifpwithaddr(pr
->ndpr_ifp
, &pr
->ndpr_addr
);
949 * (1) We have seen the prefix advertised before, but
950 * we have never performed autoconfig for this prefix.
951 * This is because Autonomous bit was 0 previously, or
952 * autoconfig failed due to some other reasons.
953 * (2) We have seen the prefix advertised before and
954 * we have performed autoconfig in the past, but
955 * we seem to have no interface address right now.
956 * This is because the interface address have expired.
958 * This prefix is fresh, with respect to autoconfig
961 * Add an address based on RFC 2462 5.5.3 (d).
963 ia6
= in6_ifadd(pr
->ndpr_ifp
,
964 &pr
->ndpr_prefix
.sin6_addr
, &pr
->ndpr_addr
,
967 error
= EADDRNOTAVAIL
;
968 log(LOG_ERR
, "prelist_update: failed to add a "
973 lt6
= &ia6
->ia6_lifetime
;
975 /* address lifetime <= prefix lifetime */
976 lt6
->ia6t_vltime
= new->ndpr_vltime
;
977 lt6
->ia6t_pltime
= new->ndpr_pltime
;
978 in6_init_address_ltimes(new, lt6
, 1);
980 #define TWOHOUR (120*60)
982 * We have seen the prefix before, and we have added
983 * interface address in the past. We still have
984 * the interface address assigned.
986 * update address lifetime based on RFC 2462
991 lt6
= &ia6
->ia6_lifetime
;
993 #if 0 /* RFC 2462 5.5.3 (e) */
994 lt6
->ia6t_pltime
= new->ndpr_pltime
;
995 if (TWOHOUR
< new->ndpr_vltime
996 || lt6pr
->nd
< new->ndpr_vltime
) {
997 lt6
->ia6t_vltime
= new->ndpr_vltime
;
1000 && lt6
->ia6t_vltime
<= TWOHOUR0
1001 && new->ndpr_vltime
<= lt6
->ia6t_vltime
) {
1002 lt6
->ia6t_vltime
= new->ndpr_vltime
;
1005 lt6
->ia6t_vltime
= TWOHOUR
;
1009 /* 2 hour rule is not imposed for pref lifetime */
1010 new->ndpr_apltime
= new->ndpr_pltime
;
1011 lt6
->ia6t_pltime
= new->ndpr_pltime
;
1012 #else /* update from Jim Bound, (ipng 6712) */
1013 if (TWOHOUR
< new->ndpr_vltime
1014 || lt6
->ia6t_vltime
< new->ndpr_vltime
) {
1015 lt6
->ia6t_vltime
= new->ndpr_vltime
;
1018 lt6
->ia6t_vltime
= new->ndpr_vltime
;
1022 /* jim bound rule is not imposed for pref lifetime */
1023 lt6
->ia6t_pltime
= new->ndpr_pltime
;
1025 in6_init_address_ltimes(new, lt6
, update
);
1031 /* address lifetime expire processing, RFC 2462 5.5.4. */
1032 if (pr
->ndpr_preferred
&& pr
->ndpr_preferred
< time_second
) {
1033 struct in6_ifaddr
*ia6
;
1035 ia6
= in6ifa_ifpwithaddr(pr
->ndpr_ifp
, &pr
->ndpr_addr
);
1037 ia6
->ia6_flags
&= ~IN6_IFF_DEPRECATED
;
1041 onlink
= pr
->ndpr_statef_onlink
; /* Mobile IPv6 */
1043 if (dr
&& pfxrtr_lookup(pr
, dr
) == NULL
)
1047 if (mip6_prelist_update_hook
) {
1049 * Check for home prefix. It can't be a fresh prefix
1050 * (since it's static), so check here.
1052 (*mip6_prelist_update_hook
)(pr
, dr
);
1055 if (mip6_probe_pfxrtrs_hook
) {
1057 * If this prefix previously was detached, maybe we
1061 (*mip6_probe_pfxrtrs_hook
)();
1068 if (new->ndpr_vltime
== 0) goto end
;
1070 bzero(&new->ndpr_addr
, sizeof(struct in6_addr
));
1073 * RFC 2462 5.5.3 (d)
1074 * We got a fresh prefix. Perform some sanity checks
1075 * and add an interface address by appending interface ID
1076 * to the advertised prefix.
1078 if (!new->ndpr_raf_auto
)
1081 ia6
= in6_ifadd(new->ndpr_ifp
, &new->ndpr_prefix
.sin6_addr
,
1082 &new->ndpr_addr
, new->ndpr_plen
);
1084 error
= EADDRNOTAVAIL
;
1085 log(LOG_ERR
, "prelist_update: "
1086 "failed to add a new address\n");
1089 /* set onlink bit if an interface route is configured */
1090 new->ndpr_statef_onlink
= (ia6
->ia_flags
& IFA_ROUTE
) ? 1 : 0;
1092 lt6
= &ia6
->ia6_lifetime
;
1094 /* address lifetime <= prefix lifetime */
1095 lt6
->ia6t_vltime
= new->ndpr_vltime
;
1096 lt6
->ia6t_pltime
= new->ndpr_pltime
;
1097 in6_init_address_ltimes(new, lt6
, 1);
1100 error_tmp
= prelist_add(new, dr
);
1101 error
= error_tmp
? error_tmp
: error
;
1104 if (mip6_probe_pfxrtrs_hook
) {
1105 /* This is a new prefix, maybe we have moved. */
1106 (*mip6_probe_pfxrtrs_hook
)();
1109 if (mip6_minus_a_case_hook
) {
1111 * If we are still looking for an autoconfigured home
1112 * address when we are in "minus a" case, here's a new
1113 * prefix and hopefully we can use the address derived
1117 (*mip6_minus_a_case_hook
)(new);
1129 * A supplement function used in the on-link detection below;
1130 * detect if a given prefix has a (probably) reachable advertising router.
1131 * XXX: lengthy function name...
1133 struct nd_pfxrouter
*
1134 find_pfxlist_reachable_router(pr
)
1135 struct nd_prefix
*pr
;
1137 struct nd_pfxrouter
*pfxrtr
;
1139 struct llinfo_nd6
*ln
;
1141 for (pfxrtr
= LIST_FIRST(&pr
->ndpr_advrtrs
); pfxrtr
;
1142 pfxrtr
= LIST_NEXT(pfxrtr
, pfr_entry
)) {
1143 if ((rt
= nd6_lookup(&pfxrtr
->router
->rtaddr
, 0,
1144 pfxrtr
->router
->ifp
)) &&
1145 (ln
= (struct llinfo_nd6
*)rt
->rt_llinfo
) &&
1146 ND6_IS_LLINFO_PROBREACH(ln
))
1155 * Check if each prefix in the prefix list has at least one available router
1156 * that advertised the prefix (A router is "available" if its neighbor cache
1157 * entry has reachable or probably reachable).
1158 * If the check fails, the prefix may be off-link, because, for example,
1159 * we have moved from the network but the lifetime of the prefix has not
1160 * been expired yet. So we should not use the prefix if there is another
1161 * prefix that has an available router.
1162 * But if there is no prefix that has an available router, we still regards
1163 * all the prefixes as on-link. This is because we can't tell if all the
1164 * routers are simply dead or if we really moved from the network and there
1165 * is no router around us.
1168 pfxlist_onlink_check()
1170 struct nd_prefix
*pr
;
1173 * Check if there is a prefix that has a reachable advertising
1176 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
1177 if (find_pfxlist_reachable_router(pr
))
1183 * There is at least one prefix that has a reachable router.
1184 * First, detach prefixes which has no reachable advertising
1185 * router and then attach other prefixes.
1186 * The order is important since an attached prefix and a
1187 * detached prefix may have a same interface route.
1189 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
1190 if (find_pfxlist_reachable_router(pr
) == NULL
&&
1191 pr
->ndpr_statef_onlink
) {
1192 pr
->ndpr_statef_onlink
= 0;
1193 nd6_detach_prefix(pr
);
1196 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
) {
1197 if (find_pfxlist_reachable_router(pr
) &&
1198 pr
->ndpr_statef_onlink
== 0)
1199 nd6_attach_prefix(pr
);
1203 /* there is no prefix that has a reachable router */
1204 for (pr
= nd_prefix
.lh_first
; pr
; pr
= pr
->ndpr_next
)
1205 if (pr
->ndpr_statef_onlink
== 0)
1206 nd6_attach_prefix(pr
);
1211 nd6_detach_prefix(pr
)
1212 struct nd_prefix
*pr
;
1214 struct in6_ifaddr
*ia6
;
1215 struct sockaddr_in6 sa6
, mask6
;
1218 * Delete the interface route associated with the prefix.
1220 bzero(&sa6
, sizeof(sa6
));
1221 sa6
.sin6_family
= AF_INET6
;
1222 sa6
.sin6_len
= sizeof(sa6
);
1223 bcopy(&pr
->ndpr_prefix
.sin6_addr
, &sa6
.sin6_addr
,
1224 sizeof(struct in6_addr
));
1225 bzero(&mask6
, sizeof(mask6
));
1226 mask6
.sin6_family
= AF_INET6
;
1227 mask6
.sin6_len
= sizeof(sa6
);
1228 bcopy(&pr
->ndpr_mask
, &mask6
.sin6_addr
, sizeof(struct in6_addr
));
1232 e
= rtrequest(RTM_DELETE
, (struct sockaddr
*)&sa6
, NULL
,
1233 (struct sockaddr
*)&mask6
, 0, NULL
);
1236 "nd6_detach_prefix: failed to delete route: "
1237 "%s/%d (errno = %d)\n",
1238 ip6_sprintf(&sa6
.sin6_addr
),
1245 * Mark the address derived from the prefix detached so that
1246 * it won't be used as a source address for a new connection.
1248 if (IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
))
1251 ia6
= in6ifa_ifpwithaddr(pr
->ndpr_ifp
, &pr
->ndpr_addr
);
1254 if (mip6_get_home_prefix_hook
)
1255 if (pr
!= (*mip6_get_home_prefix_hook
)())
1256 ia6
->ia6_flags
|= IN6_IFF_DETACHED
;
1258 ia6
->ia6_flags
|= IN6_IFF_DETACHED
;
1263 nd6_attach_prefix(pr
)
1264 struct nd_prefix
*pr
;
1267 struct in6_ifaddr
*ia6
;
1270 * Add the interface route associated with the prefix(if necessary)
1271 * Should we consider if the L bit is set in pr->ndpr_flags?
1273 ifa
= ifaof_ifpforaddr((struct sockaddr
*)&pr
->ndpr_prefix
,
1277 "nd6_attach_prefix: failed to find any ifaddr"
1278 " to add route for a prefix(%s/%d)\n",
1279 ip6_sprintf(&pr
->ndpr_addr
), pr
->ndpr_plen
);
1283 struct sockaddr_in6 mask6
;
1285 bzero(&mask6
, sizeof(mask6
));
1286 mask6
.sin6_family
= AF_INET6
;
1287 mask6
.sin6_len
= sizeof(mask6
);
1288 mask6
.sin6_addr
= pr
->ndpr_mask
;
1289 e
= rtrequest(RTM_ADD
, (struct sockaddr
*)&pr
->ndpr_prefix
,
1290 ifa
->ifa_addr
, (struct sockaddr
*)&mask6
,
1291 ifa
->ifa_flags
, NULL
);
1293 pr
->ndpr_statef_onlink
= 1;
1296 "nd6_attach_prefix: failed to add route for"
1297 " a prefix(%s/%d), errno = %d\n",
1298 ip6_sprintf(&pr
->ndpr_addr
), pr
->ndpr_plen
, e
);
1303 * Now the address derived from the prefix can be used as a source
1304 * for a new connection, so clear the detached flag.
1306 if (IN6_IS_ADDR_UNSPECIFIED(&pr
->ndpr_addr
))
1309 ia6
= in6ifa_ifpwithaddr(pr
->ndpr_ifp
, &pr
->ndpr_addr
);
1311 ia6
->ia6_flags
&= ~IN6_IFF_DETACHED
;
1312 if (pr
->ndpr_statef_onlink
)
1313 ia6
->ia_flags
|= IFA_ROUTE
;
1317 static struct in6_ifaddr
*
1318 in6_ifadd(ifp
, in6
, addr
, prefixlen
)
1320 struct in6_addr
*in6
;
1321 struct in6_addr
*addr
;
1322 int prefixlen
; /* prefix len of the new prefix in "in6" */
1325 struct in6_ifaddr
*ia
, *ib
, *oia
;
1327 struct in6_addr mask
;
1329 in6_len2mask(&mask
, prefixlen
);
1331 /* find link-local address (will be interface ID) */
1332 ifa
= (struct ifaddr
*)in6ifa_ifpforlinklocal(ifp
, 0);/* 0 is OK? */
1334 ib
= (struct in6_ifaddr
*)ifa
;
1338 #if 0 /* don't care link local addr state, and always do DAD */
1339 /* if link-local address is not eligible, do not autoconfigure. */
1340 if (((struct in6_ifaddr
*)ifa
)->ia6_flags
& IN6_IFF_NOTREADY
) {
1341 printf("in6_ifadd: link-local address not ready\n");
1346 /* prefixlen + ifidlen must be equal to 128 */
1347 if (prefixlen
!= in6_mask2len(&ib
->ia_prefixmask
.sin6_addr
)) {
1348 log(LOG_ERR
, "in6_ifadd: wrong prefixlen for %s"
1349 "(prefix=%d ifid=%d)\n", if_name(ifp
),
1351 128 - in6_mask2len(&ib
->ia_prefixmask
.sin6_addr
));
1356 ia
= (struct in6_ifaddr
*)_MALLOC(sizeof(*ia
), M_IFADDR
, M_DONTWAIT
);
1358 printf("ENOBUFS in in6_ifadd %d\n", __LINE__
);
1362 bzero((caddr_t
)ia
, sizeof(*ia
));
1363 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1364 if (ifp
->if_flags
& IFF_POINTOPOINT
)
1365 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
1367 ia
->ia_ifa
.ifa_dstaddr
= NULL
;
1368 ia
->ia_ifa
.ifa_netmask
= (struct sockaddr
*)&ia
->ia_prefixmask
;
1371 /* link to in6_ifaddr */
1372 if ((oia
= in6_ifaddr
) != NULL
) {
1373 for( ; oia
->ia_next
; oia
= oia
->ia_next
)
1378 ia
->ia_ifa
.ifa_refcnt
++;
1380 /* link to if_addrlist */
1381 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1382 if ((ifa
= ifp
->if_addrlist
) != NULL
) {
1383 for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
1385 ifa
->ifa_next
= (struct ifaddr
*)ia
;
1388 if (ifp
->if_addrlist
.tqh_first
!= NULL
) {
1389 TAILQ_INSERT_TAIL(&ifp
->if_addrlist
, (struct ifaddr
*)ia
,
1391 ia
->ia_ifa
.ifa_refcnt
++;
1397 * this should not be the case because there is at least one
1398 * link-local address(see the beginning of the function).
1400 TAILQ_INIT(&ifp
->if_addrlist
);
1405 ia
->ia_addr
.sin6_len
= sizeof(struct sockaddr_in6
);
1406 ia
->ia_addr
.sin6_family
= AF_INET6
;
1408 bcopy(in6
, &ia
->ia_addr
.sin6_addr
, sizeof(ia
->ia_addr
.sin6_addr
));
1409 ia
->ia_addr
.sin6_addr
.s6_addr32
[0] &= mask
.s6_addr32
[0];
1410 ia
->ia_addr
.sin6_addr
.s6_addr32
[1] &= mask
.s6_addr32
[1];
1411 ia
->ia_addr
.sin6_addr
.s6_addr32
[2] &= mask
.s6_addr32
[2];
1412 ia
->ia_addr
.sin6_addr
.s6_addr32
[3] &= mask
.s6_addr32
[3];
1414 ia
->ia_addr
.sin6_addr
.s6_addr32
[0]
1415 |= (ib
->ia_addr
.sin6_addr
.s6_addr32
[0] & ~mask
.s6_addr32
[0]);
1416 ia
->ia_addr
.sin6_addr
.s6_addr32
[1]
1417 |= (ib
->ia_addr
.sin6_addr
.s6_addr32
[1] & ~mask
.s6_addr32
[1]);
1418 ia
->ia_addr
.sin6_addr
.s6_addr32
[2]
1419 |= (ib
->ia_addr
.sin6_addr
.s6_addr32
[2] & ~mask
.s6_addr32
[2]);
1420 ia
->ia_addr
.sin6_addr
.s6_addr32
[3]
1421 |= (ib
->ia_addr
.sin6_addr
.s6_addr32
[3] & ~mask
.s6_addr32
[3]);
1424 ia
->ia_prefixmask
.sin6_len
= sizeof(struct sockaddr_in6
);
1425 ia
->ia_prefixmask
.sin6_family
= AF_INET6
;
1426 bcopy(&mask
, &ia
->ia_prefixmask
.sin6_addr
,
1427 sizeof(ia
->ia_prefixmask
.sin6_addr
));
1430 ia
->ia_ifa
.ifa_rtrequest
=
1431 (ifp
->if_type
== IFT_PPP
) ? nd6_p2p_rtrequest
: nd6_rtrequest
;
1432 ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
1433 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1435 /* add interface route */
1436 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_UP
|RTF_CLONING
))) {
1437 log(LOG_NOTICE
, "in6_ifadd: failed to add an interface route "
1438 "for %s/%d on %s, errno = %d\n",
1439 ip6_sprintf(&ia
->ia_addr
.sin6_addr
), prefixlen
,
1440 if_name(ifp
), error
);
1443 ia
->ia_flags
|= IFA_ROUTE
;
1445 *addr
= ia
->ia_addr
.sin6_addr
;
1447 if (ifp
->if_flags
& IFF_MULTICAST
) {
1448 int error
; /* not used */
1449 struct in6_addr sol6
;
1451 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1452 /* Restore saved multicast addresses(if any). */
1453 in6_restoremkludge(ia
, ifp
);
1456 /* join solicited node multicast address */
1457 bzero(&sol6
, sizeof(sol6
));
1458 sol6
.s6_addr16
[0] = htons(0xff02);
1459 sol6
.s6_addr16
[1] = htons(ifp
->if_index
);
1460 sol6
.s6_addr32
[1] = 0;
1461 sol6
.s6_addr32
[2] = htonl(1);
1462 sol6
.s6_addr32
[3] = ia
->ia_addr
.sin6_addr
.s6_addr32
[3];
1463 sol6
.s6_addr8
[12] = 0xff;
1464 (void)in6_addmulti(&sol6
, ifp
, &error
);
1467 ia
->ia6_flags
|= IN6_IFF_TENTATIVE
;
1470 * To make the interface up. Only AF_INET6 in ia is used...
1473 error
= dlil_ioctl(PF_INET6
, ifp
, SIOCSIFADDR
, (caddr_t
)ia
);
1474 if (error
== EOPNOTSUPP
)
1483 /* Perform DAD, if needed. */
1484 nd6_dad_start((struct ifaddr
*)ia
, NULL
);
1492 struct in6_addr
*in6
;
1494 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1497 struct in6_ifaddr
*ia
= (struct in6_ifaddr
*)NULL
;
1498 struct in6_ifaddr
*oia
= (struct in6_ifaddr
*)NULL
;
1503 ia
= in6ifa_ifpwithaddr(ifp
, in6
);
1507 if (ifp
->if_flags
& IFF_MULTICAST
) {
1509 * delete solicited multicast addr for deleting host id
1511 struct in6_multi
*in6m
;
1512 struct in6_addr llsol
;
1513 bzero(&llsol
, sizeof(struct in6_addr
));
1514 llsol
.s6_addr16
[0] = htons(0xff02);
1515 llsol
.s6_addr16
[1] = htons(ifp
->if_index
);
1516 llsol
.s6_addr32
[1] = 0;
1517 llsol
.s6_addr32
[2] = htonl(1);
1518 llsol
.s6_addr32
[3] =
1519 ia
->ia_addr
.sin6_addr
.s6_addr32
[3];
1520 llsol
.s6_addr8
[12] = 0xff;
1522 IN6_LOOKUP_MULTI(llsol
, ifp
, in6m
);
1527 if (ia
->ia_flags
& IFA_ROUTE
) {
1528 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1529 ia
->ia_flags
&= ~IFA_ROUTE
;
1532 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1533 if ((ifa
= ifp
->if_addrlist
) == (struct ifaddr
*)ia
) {
1534 ifp
->if_addrlist
= ifa
->ifa_next
;
1536 while (ifa
->ifa_next
&&
1537 (ifa
->ifa_next
!= (struct ifaddr
*)ia
))
1538 ifa
= ifa
->ifa_next
;
1540 ifa
->ifa_next
= ((struct ifaddr
*)ia
)->ifa_next
;
1545 TAILQ_REMOVE(&ifp
->if_addrlist
, (struct ifaddr
*)ia
, ifa_list
);
1547 IFAFREE(&ia
->ia_ifa
);
1549 /* lladdr is never deleted */
1551 if (oia
== (ia
= in6_ifaddr
))
1552 in6_ifaddr
= ia
->ia_next
;
1554 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
1557 ia
->ia_next
= oia
->ia_next
;
1562 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1563 in6_savemkludge(oia
);
1565 IFAFREE((&oia
->ia_ifa
));
1567 rtrequest(RTM_DELETE,
1568 (struct sockaddr *)&ia->ia_addr,
1569 (struct sockaddr *)0
1570 (struct sockaddr *)&ia->ia_prefixmask,
1572 (struct rtentry **)0);
1578 in6_init_prefix_ltimes(struct nd_prefix
*ndpr
)
1580 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1581 long time_second
= time
.tv_sec
;
1584 /* check if preferred lifetime > valid lifetime */
1585 if (ndpr
->ndpr_pltime
> ndpr
->ndpr_vltime
) {
1586 log(LOG_INFO
, "in6_init_prefix_ltimes: preferred lifetime"
1587 "(%d) is greater than valid lifetime(%d)\n",
1588 (u_int
)ndpr
->ndpr_pltime
, (u_int
)ndpr
->ndpr_vltime
);
1591 if (ndpr
->ndpr_pltime
== ND6_INFINITE_LIFETIME
)
1592 ndpr
->ndpr_preferred
= 0;
1594 ndpr
->ndpr_preferred
= time_second
+ ndpr
->ndpr_pltime
;
1595 if (ndpr
->ndpr_vltime
== ND6_INFINITE_LIFETIME
)
1596 ndpr
->ndpr_expire
= 0;
1598 ndpr
->ndpr_expire
= time_second
+ ndpr
->ndpr_vltime
;
1604 in6_init_address_ltimes(struct nd_prefix
*new,
1605 struct in6_addrlifetime
*lt6
,
1608 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__)
1609 long time_second
= time
.tv_sec
;
1612 /* Valid lifetime must not be updated unless explicitly specified. */
1613 if (update_vltime
) {
1614 /* init ia6t_expire */
1615 if (lt6
->ia6t_vltime
== ND6_INFINITE_LIFETIME
)
1616 lt6
->ia6t_expire
= 0;
1618 lt6
->ia6t_expire
= time_second
;
1619 lt6
->ia6t_expire
+= lt6
->ia6t_vltime
;
1621 /* Ensure addr lifetime <= prefix lifetime. */
1622 if (new->ndpr_expire
&& lt6
->ia6t_expire
&&
1623 new->ndpr_expire
< lt6
->ia6t_expire
)
1624 lt6
->ia6t_expire
= new->ndpr_expire
;
1627 /* init ia6t_preferred */
1628 if (lt6
->ia6t_pltime
== ND6_INFINITE_LIFETIME
)
1629 lt6
->ia6t_preferred
= 0;
1631 lt6
->ia6t_preferred
= time_second
;
1632 lt6
->ia6t_preferred
+= lt6
->ia6t_pltime
;
1634 /* Ensure addr lifetime <= prefix lifetime. */
1635 if (new->ndpr_preferred
&& lt6
->ia6t_preferred
1636 && new->ndpr_preferred
< lt6
->ia6t_preferred
)
1637 lt6
->ia6t_preferred
= new->ndpr_preferred
;
1641 * Delete all the routing table entries that use the specified gateway.
1642 * XXX: this function causes search through all entries of routing table, so
1643 * it shouldn't be called when acting as a router.
1646 rt6_flush(gateway
, ifp
)
1647 struct in6_addr
*gateway
;
1650 struct radix_node_head
*rnh
= rt_tables
[AF_INET6
];
1652 int s
= splsoftnet();
1657 /* We'll care only link-local addresses */
1658 if (!IN6_IS_ADDR_LINKLOCAL(gateway
)) {
1662 /* XXX: hack for KAME's link-local address kludge */
1663 gateway
->s6_addr16
[1] = htons(ifp
->if_index
);
1665 rnh
->rnh_walktree(rnh
, rt6_deleteroute
, (void *)gateway
);
1670 rt6_deleteroute(rn
, arg
)
1671 struct radix_node
*rn
;
1674 #define SIN6(s) ((struct sockaddr_in6 *)s)
1675 struct rtentry
*rt
= (struct rtentry
*)rn
;
1676 struct in6_addr
*gate
= (struct in6_addr
*)arg
;
1678 if (rt
->rt_gateway
== NULL
|| rt
->rt_gateway
->sa_family
!= AF_INET6
)
1681 if (!IN6_ARE_ADDR_EQUAL(gate
, &SIN6(rt
->rt_gateway
)->sin6_addr
))
1685 * We delete only host route. This means, in particular, we don't
1686 * delete default route.
1688 if ((rt
->rt_flags
& RTF_HOST
) == 0)
1691 return(rtrequest(RTM_DELETE
, rt_key(rt
),
1692 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
, 0));
1697 nd6_setdefaultiface(ifindex
)
1702 if (ifindex
< 0 || if_index
< ifindex
)
1705 if (nd6_defifindex
!= ifindex
) {
1706 nd6_defifindex
= ifindex
;
1707 if (nd6_defifindex
> 0)
1708 nd6_defifp
= ifindex2ifnet
[nd6_defifindex
];
1713 * If the Default Router List is empty, install a route
1714 * to the specified interface as default or remove the default
1715 * route when the default interface becomes canceled.
1716 * The check for the queue is actually redundant, but
1717 * we do this here to avoid re-install the default route
1718 * if the list is NOT empty.
1720 if (TAILQ_FIRST(&nd_defrouter
) == NULL
)