Move the detaching and making tentative addresses out if in6_if_up and into in6_if_link_up. This fixes a possible panic where link is up but not the interface. Note that a better solution would be to listen to the routing socket in the kernel, but I don't know how to do that. Reachable Router tests for IFF_UP as well.diff -r1.79 -r1.80 src/sys/dev/mii/mii_physubr.c
(roy)
--- src/sys/dev/mii/mii_physubr.c 2013/06/16 06:29:08 1.79
+++ src/sys/dev/mii/mii_physubr.c 2013/06/20 13:56:29 1.80
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: mii_physubr.c,v 1.79 2013/06/16 06:29:08 msaitoh Exp $ */ | 1 | /* $NetBSD: mii_physubr.c,v 1.80 2013/06/20 13:56:29 roy Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center. | 9 | * NASA Ames Research Center. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * Subroutines common to all PHYs. | 34 | * Subroutines common to all PHYs. | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.79 2013/06/16 06:29:08 msaitoh Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.80 2013/06/20 13:56:29 roy Exp $"); | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/device.h> | 41 | #include <sys/device.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | #include <sys/kernel.h> | 43 | #include <sys/kernel.h> | |
44 | #include <sys/socket.h> | 44 | #include <sys/socket.h> | |
45 | #include <sys/errno.h> | 45 | #include <sys/errno.h> | |
46 | #include <sys/module.h> | 46 | #include <sys/module.h> | |
47 | #include <sys/proc.h> | 47 | #include <sys/proc.h> | |
48 | 48 | |||
49 | #include <net/if.h> | 49 | #include <net/if.h> | |
50 | #include <net/if_media.h> | 50 | #include <net/if_media.h> | |
51 | #include <net/route.h> | 51 | #include <net/route.h> | |
@@ -426,37 +426,34 @@ mii_phy_update(struct mii_softc *sc, int | @@ -426,37 +426,34 @@ mii_phy_update(struct mii_softc *sc, int | |||
426 | cmd == MII_MEDIACHG) { | 426 | cmd == MII_MEDIACHG) { | |
427 | mii_phy_statusmsg(sc); | 427 | mii_phy_statusmsg(sc); | |
428 | (*mii->mii_statchg)(mii->mii_ifp); | 428 | (*mii->mii_statchg)(mii->mii_ifp); | |
429 | sc->mii_media_active = mii->mii_media_active; | 429 | sc->mii_media_active = mii->mii_media_active; | |
430 | sc->mii_media_status = mii->mii_media_status; | 430 | sc->mii_media_status = mii->mii_media_status; | |
431 | } | 431 | } | |
432 | } | 432 | } | |
433 | 433 | |||
434 | static void | 434 | static void | |
435 | mii_phy_statusmsg(struct mii_softc *sc) | 435 | mii_phy_statusmsg(struct mii_softc *sc) | |
436 | { | 436 | { | |
437 | struct mii_data *mii = sc->mii_pdata; | 437 | struct mii_data *mii = sc->mii_pdata; | |
438 | struct ifnet *ifp = mii->mii_ifp; | 438 | struct ifnet *ifp = mii->mii_ifp; | |
439 | int s; | |||
440 | 439 | |||
441 | s = splnet(); | |||
442 | if (mii->mii_media_status & IFM_AVALID) { | 440 | if (mii->mii_media_status & IFM_AVALID) { | |
443 | if (mii->mii_media_status & IFM_ACTIVE) | 441 | if (mii->mii_media_status & IFM_ACTIVE) | |
444 | if_link_state_change(ifp, LINK_STATE_UP); | 442 | if_link_state_change(ifp, LINK_STATE_UP); | |
445 | else | 443 | else | |
446 | if_link_state_change(ifp, LINK_STATE_DOWN); | 444 | if_link_state_change(ifp, LINK_STATE_DOWN); | |
447 | } else | 445 | } else | |
448 | if_link_state_change(ifp, LINK_STATE_UNKNOWN); | 446 | if_link_state_change(ifp, LINK_STATE_UNKNOWN); | |
449 | splx(s); | |||
450 | 447 | |||
451 | ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); | 448 | ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); | |
452 | } | 449 | } | |
453 | 450 | |||
454 | /* | 451 | /* | |
455 | * Initialize generic PHY media based on BMSR, called when a PHY is | 452 | * Initialize generic PHY media based on BMSR, called when a PHY is | |
456 | * attached. We expect to be set up to print a comma-separated list | 453 | * attached. We expect to be set up to print a comma-separated list | |
457 | * of media names. Does not print a newline. | 454 | * of media names. Does not print a newline. | |
458 | */ | 455 | */ | |
459 | void | 456 | void | |
460 | mii_phy_add_media(struct mii_softc *sc) | 457 | mii_phy_add_media(struct mii_softc *sc) | |
461 | { | 458 | { | |
462 | struct mii_data *mii = sc->mii_pdata; | 459 | struct mii_data *mii = sc->mii_pdata; |
--- src/sys/net/if.c 2013/06/11 12:08:29 1.263
+++ src/sys/net/if.c 2013/06/20 13:56:29 1.264
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if.c,v 1.263 2013/06/11 12:08:29 roy Exp $ */ | 1 | /* $NetBSD: if.c,v 1.264 2013/06/20 13:56:29 roy Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by William Studenmund and Jason R. Thorpe. | 8 | * by William Studenmund and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -80,27 +80,27 @@ | @@ -80,27 +80,27 @@ | |||
80 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 80 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
81 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 81 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
82 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 82 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
83 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 83 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
84 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 84 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
85 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 85 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
86 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 86 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
87 | * SUCH DAMAGE. | 87 | * SUCH DAMAGE. | |
88 | * | 88 | * | |
89 | * @(#)if.c 8.5 (Berkeley) 1/9/95 | 89 | * @(#)if.c 8.5 (Berkeley) 1/9/95 | |
90 | */ | 90 | */ | |
91 | 91 | |||
92 | #include <sys/cdefs.h> | 92 | #include <sys/cdefs.h> | |
93 | __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.263 2013/06/11 12:08:29 roy Exp $"); | 93 | __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.264 2013/06/20 13:56:29 roy Exp $"); | |
94 | 94 | |||
95 | #include "opt_inet.h" | 95 | #include "opt_inet.h" | |
96 | 96 | |||
97 | #include "opt_atalk.h" | 97 | #include "opt_atalk.h" | |
98 | #include "opt_natm.h" | 98 | #include "opt_natm.h" | |
99 | #include "opt_pfil_hooks.h" | 99 | #include "opt_pfil_hooks.h" | |
100 | 100 | |||
101 | #include <sys/param.h> | 101 | #include <sys/param.h> | |
102 | #include <sys/mbuf.h> | 102 | #include <sys/mbuf.h> | |
103 | #include <sys/systm.h> | 103 | #include <sys/systm.h> | |
104 | #include <sys/callout.h> | 104 | #include <sys/callout.h> | |
105 | #include <sys/proc.h> | 105 | #include <sys/proc.h> | |
106 | #include <sys/socket.h> | 106 | #include <sys/socket.h> | |
@@ -1323,76 +1323,83 @@ link_rtrequest(int cmd, struct rtentry * | @@ -1323,76 +1323,83 @@ link_rtrequest(int cmd, struct rtentry * | |||
1323 | 1323 | |||
1324 | if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL || | 1324 | if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL || | |
1325 | (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL) | 1325 | (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL) | |
1326 | return; | 1326 | return; | |
1327 | if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { | 1327 | if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { | |
1328 | rt_replace_ifa(rt, ifa); | 1328 | rt_replace_ifa(rt, ifa); | |
1329 | if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) | 1329 | if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) | |
1330 | ifa->ifa_rtrequest(cmd, rt, info); | 1330 | ifa->ifa_rtrequest(cmd, rt, info); | |
1331 | } | 1331 | } | |
1332 | } | 1332 | } | |
1333 | 1333 | |||
1334 | /* | 1334 | /* | |
1335 | * Handle a change in the interface link state. | 1335 | * Handle a change in the interface link state. | |
1336 | * XXX: We should listen to the routing socket in-kernel rather | |||
1337 | * than calling in6_if_link_* functions directly from here. | |||
1336 | */ | 1338 | */ | |
1337 | void | 1339 | void | |
1338 | if_link_state_change(struct ifnet *ifp, int link_state) | 1340 | if_link_state_change(struct ifnet *ifp, int link_state) | |
1339 | { | 1341 | { | |
1340 | int old_link_state; | 1342 | int old_link_state, s; | |
1341 | 1343 | |||
1342 | if (ifp->if_link_state == link_state) | 1344 | s = splnet(); | |
1345 | if (ifp->if_link_state == link_state) { | |||
1346 | splx(s); | |||
1343 | return; | 1347 | return; | |
1348 | } | |||
1344 | 1349 | |||
1345 | old_link_state = ifp->if_link_state; | 1350 | old_link_state = ifp->if_link_state; | |
1346 | ifp->if_link_state = link_state; | 1351 | ifp->if_link_state = link_state; | |
1347 | #ifdef DEBUG | 1352 | #ifdef DEBUG | |
1348 | log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname, | 1353 | log(LOG_DEBUG, "%s: link state %s (was %s)\n", ifp->if_xname, | |
1349 | link_state == LINK_STATE_UP ? "UP" : | 1354 | link_state == LINK_STATE_UP ? "UP" : | |
1350 | link_state == LINK_STATE_DOWN ? "DOWN" : | 1355 | link_state == LINK_STATE_DOWN ? "DOWN" : | |
1351 | "UNKNOWN", | 1356 | "UNKNOWN", | |
1352 | old_link_state == LINK_STATE_UP ? "UP" : | 1357 | old_link_state == LINK_STATE_UP ? "UP" : | |
1353 | old_link_state == LINK_STATE_DOWN ? "DOWN" : | 1358 | old_link_state == LINK_STATE_DOWN ? "DOWN" : | |
1354 | "UNKNOWN"); | 1359 | "UNKNOWN"); | |
1355 | #endif | 1360 | #endif | |
1356 | 1361 | |||
1357 | #ifdef INET6 | 1362 | #ifdef INET6 | |
1358 | /* | 1363 | /* | |
1359 | * When going from UNKNOWN to UP, we need to mark existing | 1364 | * When going from UNKNOWN to UP, we need to mark existing | |
1360 | * IPv6 addresses as tentative and restart DAD as we may have | 1365 | * IPv6 addresses as tentative and restart DAD as we may have | |
1361 | * erroneously not found a duplicate. | 1366 | * erroneously not found a duplicate. | |
1362 | * | 1367 | * | |
1363 | * This needs to happen before rt_ifmsg to avoid a race where | 1368 | * This needs to happen before rt_ifmsg to avoid a race where | |
1364 | * listeners would have an address and expect it to work right | 1369 | * listeners would have an address and expect it to work right | |
1365 | * away. | 1370 | * away. | |
1366 | */ | 1371 | */ | |
1367 | if (link_state == LINK_STATE_UP && | 1372 | if (link_state == LINK_STATE_UP && | |
1368 | old_link_state == LINK_STATE_UNKNOWN) | 1373 | old_link_state == LINK_STATE_UNKNOWN) | |
1369 | in6_if_down(ifp); | 1374 | in6_if_link_down(ifp); | |
1370 | #endif | 1375 | #endif | |
1371 | 1376 | |||
1372 | /* Notify that the link state has changed. */ | 1377 | /* Notify that the link state has changed. */ | |
1373 | rt_ifmsg(ifp); | 1378 | rt_ifmsg(ifp); | |
1374 | 1379 | |||
1375 | #if NCARP > 0 | 1380 | #if NCARP > 0 | |
1376 | if (ifp->if_carp) | 1381 | if (ifp->if_carp) | |
1377 | carp_carpdev_state(ifp); | 1382 | carp_carpdev_state(ifp); | |
1378 | #endif | 1383 | #endif | |
1379 | 1384 | |||
1380 | #ifdef INET6 | 1385 | #ifdef INET6 | |
1381 | if (link_state == LINK_STATE_DOWN) | 1386 | if (link_state == LINK_STATE_DOWN) | |
1382 | in6_if_down(ifp); | 1387 | in6_if_link_down(ifp); | |
1383 | else if (link_state == LINK_STATE_UP) | 1388 | else if (link_state == LINK_STATE_UP) | |
1384 | in6_if_up(ifp); | 1389 | in6_if_link_up(ifp); | |
1385 | #endif | 1390 | #endif | |
1391 | ||||
1392 | splx(s); | |||
1386 | } | 1393 | } | |
1387 | 1394 | |||
1388 | /* | 1395 | /* | |
1389 | * Mark an interface down and notify protocols of | 1396 | * Mark an interface down and notify protocols of | |
1390 | * the transition. | 1397 | * the transition. | |
1391 | * NOTE: must be called at splsoftnet or equivalent. | 1398 | * NOTE: must be called at splsoftnet or equivalent. | |
1392 | */ | 1399 | */ | |
1393 | void | 1400 | void | |
1394 | if_down(struct ifnet *ifp) | 1401 | if_down(struct ifnet *ifp) | |
1395 | { | 1402 | { | |
1396 | struct ifaddr *ifa; | 1403 | struct ifaddr *ifa; | |
1397 | 1404 | |||
1398 | ifp->if_flags &= ~IFF_UP; | 1405 | ifp->if_flags &= ~IFF_UP; |
--- src/sys/netinet6/in6.c 2013/06/11 12:08:29 1.164
+++ src/sys/netinet6/in6.c 2013/06/20 13:56:29 1.165
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: in6.c,v 1.164 2013/06/11 12:08:29 roy Exp $ */ | 1 | /* $NetBSD: in6.c,v 1.165 2013/06/20 13:56:29 roy Exp $ */ | |
2 | /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ | 2 | /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -52,27 +52,27 @@ | @@ -52,27 +52,27 @@ | |||
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
59 | * SUCH DAMAGE. | 59 | * SUCH DAMAGE. | |
60 | * | 60 | * | |
61 | * @(#)in.c 8.2 (Berkeley) 11/15/93 | 61 | * @(#)in.c 8.2 (Berkeley) 11/15/93 | |
62 | */ | 62 | */ | |
63 | 63 | |||
64 | #include <sys/cdefs.h> | 64 | #include <sys/cdefs.h> | |
65 | __KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.164 2013/06/11 12:08:29 roy Exp $"); | 65 | __KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.165 2013/06/20 13:56:29 roy Exp $"); | |
66 | 66 | |||
67 | #include "opt_inet.h" | 67 | #include "opt_inet.h" | |
68 | #include "opt_pfil_hooks.h" | 68 | #include "opt_pfil_hooks.h" | |
69 | #include "opt_compat_netbsd.h" | 69 | #include "opt_compat_netbsd.h" | |
70 | 70 | |||
71 | #include <sys/param.h> | 71 | #include <sys/param.h> | |
72 | #include <sys/ioctl.h> | 72 | #include <sys/ioctl.h> | |
73 | #include <sys/errno.h> | 73 | #include <sys/errno.h> | |
74 | #include <sys/malloc.h> | 74 | #include <sys/malloc.h> | |
75 | #include <sys/socket.h> | 75 | #include <sys/socket.h> | |
76 | #include <sys/socketvar.h> | 76 | #include <sys/socketvar.h> | |
77 | #include <sys/sockio.h> | 77 | #include <sys/sockio.h> | |
78 | #include <sys/systm.h> | 78 | #include <sys/systm.h> | |
@@ -2155,27 +2155,27 @@ in6_ifawithifp(struct ifnet *ifp, struct | @@ -2155,27 +2155,27 @@ in6_ifawithifp(struct ifnet *ifp, struct | |||
2155 | /* use the last-resort values, that are, deprecated addresses */ | 2155 | /* use the last-resort values, that are, deprecated addresses */ | |
2156 | if (dep[0]) | 2156 | if (dep[0]) | |
2157 | return dep[0]; | 2157 | return dep[0]; | |
2158 | if (dep[1]) | 2158 | if (dep[1]) | |
2159 | return dep[1]; | 2159 | return dep[1]; | |
2160 | 2160 | |||
2161 | return NULL; | 2161 | return NULL; | |
2162 | } | 2162 | } | |
2163 | 2163 | |||
2164 | /* | 2164 | /* | |
2165 | * perform DAD when interface becomes IFF_UP. | 2165 | * perform DAD when interface becomes IFF_UP. | |
2166 | */ | 2166 | */ | |
2167 | void | 2167 | void | |
2168 | in6_if_up(struct ifnet *ifp) | 2168 | in6_if_link_up(struct ifnet *ifp) | |
2169 | { | 2169 | { | |
2170 | struct ifaddr *ifa; | 2170 | struct ifaddr *ifa; | |
2171 | struct in6_ifaddr *ia; | 2171 | struct in6_ifaddr *ia; | |
2172 | 2172 | |||
2173 | /* Ensure it's sane to run DAD */ | 2173 | /* Ensure it's sane to run DAD */ | |
2174 | if (ifp->if_link_state == LINK_STATE_DOWN) | 2174 | if (ifp->if_link_state == LINK_STATE_DOWN) | |
2175 | return; | 2175 | return; | |
2176 | if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) | 2176 | if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) | |
2177 | return; | 2177 | return; | |
2178 | 2178 | |||
2179 | IFADDR_FOREACH(ifa, ifp) { | 2179 | IFADDR_FOREACH(ifa, ifp) { | |
2180 | if (ifa->ifa_addr->sa_family != AF_INET6) | 2180 | if (ifa->ifa_addr->sa_family != AF_INET6) | |
2181 | continue; | 2181 | continue; | |
@@ -2196,72 +2196,86 @@ in6_if_up(struct ifnet *ifp) | @@ -2196,72 +2196,86 @@ in6_if_up(struct ifnet *ifp) | |||
2196 | if (ia->ia6_flags & IN6_IFF_TENTATIVE) { | 2196 | if (ia->ia6_flags & IN6_IFF_TENTATIVE) { | |
2197 | /* | 2197 | /* | |
2198 | * The TENTATIVE flag was likely set by hand | 2198 | * The TENTATIVE flag was likely set by hand | |
2199 | * beforehand, implicitly indicating the need for DAD. | 2199 | * beforehand, implicitly indicating the need for DAD. | |
2200 | * We may be able to skip the random delay in this | 2200 | * We may be able to skip the random delay in this | |
2201 | * case, but we impose delays just in case. | 2201 | * case, but we impose delays just in case. | |
2202 | */ | 2202 | */ | |
2203 | nd6_dad_start(ifa, | 2203 | nd6_dad_start(ifa, | |
2204 | cprng_fast32() % | 2204 | cprng_fast32() % | |
2205 | (MAX_RTR_SOLICITATION_DELAY * hz)); | 2205 | (MAX_RTR_SOLICITATION_DELAY * hz)); | |
2206 | } | 2206 | } | |
2207 | } | 2207 | } | |
2208 | 2208 | |||
2209 | /* Restore any detached prefixes */ | |||
2210 | pfxlist_onlink_check(); | |||
2211 | } | |||
2212 | ||||
2213 | void | |||
2214 | in6_if_up(struct ifnet *ifp) | |||
2215 | { | |||
2216 | ||||
2209 | /* | 2217 | /* | |
2210 | * special cases, like 6to4, are handled in in6_ifattach | 2218 | * special cases, like 6to4, are handled in in6_ifattach | |
2211 | */ | 2219 | */ | |
2212 | in6_ifattach(ifp, NULL); | 2220 | in6_ifattach(ifp, NULL); | |
2213 | 2221 | |||
2214 | /* Restore any detached prefixes */ | 2222 | /* interface may not support link state, so bring it up also */ | |
2215 | pfxlist_onlink_check(); | 2223 | in6_if_link_up(ifp); | |
2216 | } | 2224 | } | |
2217 | ||||
2218 | /* | 2225 | /* | |
2219 | * Mark all addresses as detached. | 2226 | * Mark all addresses as detached. | |
2220 | */ | 2227 | */ | |
2221 | void | 2228 | void | |
2222 | in6_if_down(struct ifnet *ifp) | 2229 | in6_if_link_down(struct ifnet *ifp) | |
2223 | { | 2230 | { | |
2224 | struct ifaddr *ifa; | 2231 | struct ifaddr *ifa; | |
2225 | struct in6_ifaddr *ia; | 2232 | struct in6_ifaddr *ia; | |
2226 | 2233 | |||
2234 | /* Any prefixes on this interface should be detached as well */ | |||
2235 | pfxlist_onlink_check(); | |||
2236 | ||||
2227 | IFADDR_FOREACH(ifa, ifp) { | 2237 | IFADDR_FOREACH(ifa, ifp) { | |
2228 | if (ifa->ifa_addr->sa_family != AF_INET6) | 2238 | if (ifa->ifa_addr->sa_family != AF_INET6) | |
2229 | continue; | 2239 | continue; | |
2230 | ia = (struct in6_ifaddr *)ifa; | 2240 | ia = (struct in6_ifaddr *)ifa; | |
2231 | 2241 | |||
2232 | /* Stop DAD processing */ | 2242 | /* Stop DAD processing */ | |
2233 | nd6_dad_stop(ifa); | 2243 | nd6_dad_stop(ifa); | |
2234 | 2244 | |||
2235 | /* | 2245 | /* | |
2236 | * Mark the address as detached. | 2246 | * Mark the address as detached. | |
2237 | * This satisfies RFC4862 Section 5.3, but we should apply | 2247 | * This satisfies RFC4862 Section 5.3, but we should apply | |
2238 | * this logic to all addresses to be a good citizen and | 2248 | * this logic to all addresses to be a good citizen and | |
2239 | * avoid potential duplicated addresses. | 2249 | * avoid potential duplicated addresses. | |
2240 | * When the interface comes up again, detached addresses | 2250 | * When the interface comes up again, detached addresses | |
2241 | * are marked tentative and DAD commences. | 2251 | * are marked tentative and DAD commences. | |
2242 | */ | 2252 | */ | |
2243 | if (!(ia->ia6_flags & IN6_IFF_DETACHED)) { | 2253 | if (!(ia->ia6_flags & IN6_IFF_DETACHED)) { | |
2244 | nd6log((LOG_DEBUG, "in6_if_down: " | 2254 | nd6log((LOG_DEBUG, "in6_if_down: " | |
2245 | "%s marked detached\n", | 2255 | "%s marked detached\n", | |
2246 | ip6_sprintf(&ia->ia_addr.sin6_addr))); | 2256 | ip6_sprintf(&ia->ia_addr.sin6_addr))); | |
2247 | ia->ia6_flags |= IN6_IFF_DETACHED; | 2257 | ia->ia6_flags |= IN6_IFF_DETACHED; | |
2248 | ia->ia6_flags &= ~IN6_IFF_TENTATIVE; | 2258 | ia->ia6_flags &= ~IN6_IFF_TENTATIVE; | |
2249 | nd6_newaddrmsg(ifa); | 2259 | nd6_newaddrmsg(ifa); | |
2250 | } | 2260 | } | |
2251 | } | 2261 | } | |
2262 | } | |||
2252 | 2263 | |||
2253 | /* Any prefixes on this interface should be detached as well */ | 2264 | void | |
2254 | pfxlist_onlink_check(); | 2265 | in6_if_down(struct ifnet *ifp) | |
2266 | { | |||
2267 | ||||
2268 | in6_if_link_down(ifp); | |||
2255 | } | 2269 | } | |
2256 | 2270 | |||
2257 | int | 2271 | int | |
2258 | in6if_do_dad(struct ifnet *ifp) | 2272 | in6if_do_dad(struct ifnet *ifp) | |
2259 | { | 2273 | { | |
2260 | if ((ifp->if_flags & IFF_LOOPBACK) != 0) | 2274 | if ((ifp->if_flags & IFF_LOOPBACK) != 0) | |
2261 | return 0; | 2275 | return 0; | |
2262 | 2276 | |||
2263 | switch (ifp->if_type) { | 2277 | switch (ifp->if_type) { | |
2264 | case IFT_FAITH: | 2278 | case IFT_FAITH: | |
2265 | /* | 2279 | /* | |
2266 | * These interfaces do not have the IFF_LOOPBACK flag, | 2280 | * These interfaces do not have the IFF_LOOPBACK flag, | |
2267 | * but loop packets back. We do not have to do DAD on such | 2281 | * but loop packets back. We do not have to do DAD on such |
--- src/sys/netinet6/in6.h 2013/06/11 12:08:29 1.72
+++ src/sys/netinet6/in6.h 2013/06/20 13:56:29 1.73
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: in6.h,v 1.72 2013/06/11 12:08:29 roy Exp $ */ | 1 | /* $NetBSD: in6.h,v 1.73 2013/06/20 13:56:29 roy Exp $ */ | |
2 | /* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */ | 2 | /* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -690,26 +690,28 @@ in6_cksum_phdr(const struct in6_addr *sr | @@ -690,26 +690,28 @@ in6_cksum_phdr(const struct in6_addr *sr | |||
690 | return (sum); | 690 | return (sum); | |
691 | } | 691 | } | |
692 | 692 | |||
693 | struct mbuf; | 693 | struct mbuf; | |
694 | struct ifnet; | 694 | struct ifnet; | |
695 | int sockaddr_in6_cmp(const struct sockaddr *, const struct sockaddr *); | 695 | int sockaddr_in6_cmp(const struct sockaddr *, const struct sockaddr *); | |
696 | struct sockaddr *sockaddr_in6_externalize(struct sockaddr *, socklen_t, | 696 | struct sockaddr *sockaddr_in6_externalize(struct sockaddr *, socklen_t, | |
697 | const struct sockaddr *); | 697 | const struct sockaddr *); | |
698 | int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t); | 698 | int in6_cksum(struct mbuf *, u_int8_t, u_int32_t, u_int32_t); | |
699 | void in6_delayed_cksum(struct mbuf *); | 699 | void in6_delayed_cksum(struct mbuf *); | |
700 | int in6_localaddr(const struct in6_addr *); | 700 | int in6_localaddr(const struct in6_addr *); | |
701 | int in6_addrscope(const struct in6_addr *); | 701 | int in6_addrscope(const struct in6_addr *); | |
702 | struct in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *); | 702 | struct in6_ifaddr *in6_ifawithifp(struct ifnet *, struct in6_addr *); | |
703 | extern void in6_if_link_up(struct ifnet *); | |||
704 | extern void in6_if_link_down(struct ifnet *); | |||
703 | extern void in6_if_up(struct ifnet *); | 705 | extern void in6_if_up(struct ifnet *); | |
704 | extern void in6_if_down(struct ifnet *); | 706 | extern void in6_if_down(struct ifnet *); | |
705 | #ifndef __FreeBSD__ | 707 | #ifndef __FreeBSD__ | |
706 | extern int in6_src_sysctl(void *, size_t *, void *, size_t); | 708 | extern int in6_src_sysctl(void *, size_t *, void *, size_t); | |
707 | #endif | 709 | #endif | |
708 | extern void addrsel_policy_init(void); | 710 | extern void addrsel_policy_init(void); | |
709 | extern u_char ip6_protox[]; | 711 | extern u_char ip6_protox[]; | |
710 | 712 | |||
711 | #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) | 713 | #define satosin6(sa) ((struct sockaddr_in6 *)(sa)) | |
712 | #define satocsin6(sa) ((const struct sockaddr_in6 *)(sa)) | 714 | #define satocsin6(sa) ((const struct sockaddr_in6 *)(sa)) | |
713 | #define sin6tosa(sin6) ((struct sockaddr *)(sin6)) | 715 | #define sin6tosa(sin6) ((struct sockaddr *)(sin6)) | |
714 | #define sin6tocsa(sin6) ((const struct sockaddr *)(sin6)) | 716 | #define sin6tocsa(sin6) ((const struct sockaddr *)(sin6)) | |
715 | #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) | 717 | #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) |
--- src/sys/netinet6/nd6_rtr.c 2013/06/11 12:08:29 1.88
+++ src/sys/netinet6/nd6_rtr.c 2013/06/20 13:56:29 1.89
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: nd6_rtr.c,v 1.88 2013/06/11 12:08:29 roy Exp $ */ | 1 | /* $NetBSD: nd6_rtr.c,v 1.89 2013/06/20 13:56:29 roy Exp $ */ | |
2 | /* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */ | 2 | /* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
@@ -21,27 +21,27 @@ | @@ -21,27 +21,27 @@ | |||
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.88 2013/06/11 12:08:29 roy Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.89 2013/06/20 13:56:29 roy Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/systm.h> | 37 | #include <sys/systm.h> | |
38 | #include <sys/malloc.h> | 38 | #include <sys/malloc.h> | |
39 | #include <sys/mbuf.h> | 39 | #include <sys/mbuf.h> | |
40 | #include <sys/socket.h> | 40 | #include <sys/socket.h> | |
41 | #include <sys/sockio.h> | 41 | #include <sys/sockio.h> | |
42 | #include <sys/time.h> | 42 | #include <sys/time.h> | |
43 | #include <sys/kernel.h> | 43 | #include <sys/kernel.h> | |
44 | #include <sys/errno.h> | 44 | #include <sys/errno.h> | |
45 | #include <sys/ioctl.h> | 45 | #include <sys/ioctl.h> | |
46 | #include <sys/syslog.h> | 46 | #include <sys/syslog.h> | |
47 | #include <sys/cprng.h> | 47 | #include <sys/cprng.h> | |
@@ -1394,31 +1394,32 @@ prelist_update(struct nd_prefixctl *new, | @@ -1394,31 +1394,32 @@ prelist_update(struct nd_prefixctl *new, | |||
1394 | * A supplement function used in the on-link detection below; | 1394 | * A supplement function used in the on-link detection below; | |
1395 | * detect if a given prefix has a (probably) reachable advertising router. | 1395 | * detect if a given prefix has a (probably) reachable advertising router. | |
1396 | * XXX: lengthy function name... | 1396 | * XXX: lengthy function name... | |
1397 | */ | 1397 | */ | |
1398 | static struct nd_pfxrouter * | 1398 | static struct nd_pfxrouter * | |
1399 | find_pfxlist_reachable_router(struct nd_prefix *pr) | 1399 | find_pfxlist_reachable_router(struct nd_prefix *pr) | |
1400 | { | 1400 | { | |
1401 | struct nd_pfxrouter *pfxrtr; | 1401 | struct nd_pfxrouter *pfxrtr; | |
1402 | struct rtentry *rt; | 1402 | struct rtentry *rt; | |
1403 | struct llinfo_nd6 *ln; | 1403 | struct llinfo_nd6 *ln; | |
1404 | 1404 | |||
1405 | for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr; | 1405 | for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr; | |
1406 | pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) { | 1406 | pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) { | |
1407 | if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0, | 1407 | if (pfxrtr->router->ifp->if_flags & IFF_UP && | |
1408 | pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN && | |||
1409 | (rt = nd6_lookup(&pfxrtr->router->rtaddr, 0, | |||
1408 | pfxrtr->router->ifp)) && | 1410 | pfxrtr->router->ifp)) && | |
1409 | (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && | 1411 | (ln = (struct llinfo_nd6 *)rt->rt_llinfo) && | |
1410 | ND6_IS_LLINFO_PROBREACH(ln) && | 1412 | ND6_IS_LLINFO_PROBREACH(ln)) | |
1411 | pfxrtr->router->ifp->if_link_state != LINK_STATE_DOWN) | |||
1412 | break; /* found */ | 1413 | break; /* found */ | |
1413 | } | 1414 | } | |
1414 | 1415 | |||
1415 | return (pfxrtr); | 1416 | return (pfxrtr); | |
1416 | } | 1417 | } | |
1417 | 1418 | |||
1418 | /* | 1419 | /* | |
1419 | * Check if each prefix in the prefix list has at least one available router | 1420 | * Check if each prefix in the prefix list has at least one available router | |
1420 | * that advertised the prefix (a router is "available" if its neighbor cache | 1421 | * that advertised the prefix (a router is "available" if its neighbor cache | |
1421 | * entry is reachable or probably reachable). | 1422 | * entry is reachable or probably reachable). | |
1422 | * If the check fails, the prefix may be off-link, because, for example, | 1423 | * If the check fails, the prefix may be off-link, because, for example, | |
1423 | * we have moved from the network but the lifetime of the prefix has not | 1424 | * we have moved from the network but the lifetime of the prefix has not | |
1424 | * expired yet. So we should not use the prefix if there is another prefix | 1425 | * expired yet. So we should not use the prefix if there is another prefix |