inet6: Send RTM_MISS when we fail to resolve an address. Takes the same approach as when adding a new address - we no longer announce the new lladdr right away but we announce the result. This will either be RTM_ADD or RTM_MISS. RTM_DELETE is only sent if we have a lladdr assigned OR gc'ed. This results in less messages via route(4) and tells us when a new lladdr has been added (RTM_ADD), changed (RTM_CHANGE), deleted (RTM_DELETED) or has failed to been resolved (RTM_MISS). The latter case can be interpreted as unreachable.diff -r1.251 -r1.252 src/sys/net/rtsock.c
(roy)
--- src/sys/net/rtsock.c 2019/08/22 21:14:45 1.251
+++ src/sys/net/rtsock.c 2019/09/01 18:54:38 1.252
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rtsock.c,v 1.251 2019/08/22 21:14:45 roy Exp $ */ | 1 | /* $NetBSD: rtsock.c,v 1.252 2019/09/01 18:54:38 roy Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -51,27 +51,27 @@ | @@ -51,27 +51,27 @@ | |||
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
58 | * SUCH DAMAGE. | 58 | * SUCH DAMAGE. | |
59 | * | 59 | * | |
60 | * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 | 60 | * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 | |
61 | */ | 61 | */ | |
62 | 62 | |||
63 | #include <sys/cdefs.h> | 63 | #include <sys/cdefs.h> | |
64 | __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.251 2019/08/22 21:14:45 roy Exp $"); | 64 | __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.252 2019/09/01 18:54:38 roy Exp $"); | |
65 | 65 | |||
66 | #ifdef _KERNEL_OPT | 66 | #ifdef _KERNEL_OPT | |
67 | #include "opt_inet.h" | 67 | #include "opt_inet.h" | |
68 | #include "opt_compat_netbsd.h" | 68 | #include "opt_compat_netbsd.h" | |
69 | #endif | 69 | #endif | |
70 | 70 | |||
71 | #include <sys/param.h> | 71 | #include <sys/param.h> | |
72 | #include <sys/systm.h> | 72 | #include <sys/systm.h> | |
73 | #include <sys/proc.h> | 73 | #include <sys/proc.h> | |
74 | #include <sys/socket.h> | 74 | #include <sys/socket.h> | |
75 | #include <sys/socketvar.h> | 75 | #include <sys/socketvar.h> | |
76 | #include <sys/domain.h> | 76 | #include <sys/domain.h> | |
77 | #include <sys/protosw.h> | 77 | #include <sys/protosw.h> | |
@@ -142,41 +142,41 @@ if_addrflags(struct ifaddr *ifa) | @@ -142,41 +142,41 @@ if_addrflags(struct ifaddr *ifa) | |||
142 | 142 | |||
143 | 143 | |||
144 | /* | 144 | /* | |
145 | * Send a routing message as mimicing that a cloned route is added. | 145 | * Send a routing message as mimicing that a cloned route is added. | |
146 | */ | 146 | */ | |
147 | void | 147 | void | |
148 | rt_clonedmsg(int type, const struct sockaddr *dst, const uint8_t *lladdr, | 148 | rt_clonedmsg(int type, const struct sockaddr *dst, const uint8_t *lladdr, | |
149 | const struct ifnet *ifp) | 149 | const struct ifnet *ifp) | |
150 | { | 150 | { | |
151 | struct rt_addrinfo info; | 151 | struct rt_addrinfo info; | |
152 | /* Mimic flags exactly */ | 152 | /* Mimic flags exactly */ | |
153 | #define RTF_LLINFO 0x400 | 153 | #define RTF_LLINFO 0x400 | |
154 | #define RTF_CLONED 0x2000 | 154 | #define RTF_CLONED 0x2000 | |
155 | int flags = RTF_HOST | RTF_DONE | RTF_LLINFO | RTF_CLONED; | 155 | int flags = RTF_DONE; | |
156 | union { | 156 | union { | |
157 | struct sockaddr sa; | 157 | struct sockaddr sa; | |
158 | struct sockaddr_storage ss; | 158 | struct sockaddr_storage ss; | |
159 | struct sockaddr_dl sdl; | 159 | struct sockaddr_dl sdl; | |
160 | } u; | 160 | } u; | |
161 | uint8_t namelen = strlen(ifp->if_xname); | |||
162 | uint8_t addrlen = ifp->if_addrlen; | |||
163 | 161 | |||
164 | if (type != RTM_DELETE) | 162 | if (type != RTM_MISS) | |
163 | flags |= RTF_HOST | RTF_CLONED | RTF_LLINFO; | |||
164 | if (type == RTM_ADD || type == RTM_CHANGE) | |||
165 | flags |= RTF_UP; | 165 | flags |= RTF_UP; | |
166 | memset(&info, 0, sizeof(info)); | 166 | memset(&info, 0, sizeof(info)); | |
167 | info.rti_info[RTAX_DST] = dst; | 167 | info.rti_info[RTAX_DST] = dst; | |
168 | sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, ifp->if_type, | 168 | sockaddr_dl_init(&u.sdl, sizeof(u.ss), ifp->if_index, ifp->if_type, | |
169 | NULL, namelen, lladdr, addrlen); | 169 | NULL, 0, lladdr, ifp->if_addrlen); | |
170 | info.rti_info[RTAX_GATEWAY] = &u.sa; | 170 | info.rti_info[RTAX_GATEWAY] = &u.sa; | |
171 | 171 | |||
172 | rt_missmsg(type, &info, flags, 0); | 172 | rt_missmsg(type, &info, flags, 0); | |
173 | #undef RTF_LLINFO | 173 | #undef RTF_LLINFO | |
174 | #undef RTF_CLONED | 174 | #undef RTF_CLONED | |
175 | } | 175 | } | |
176 | 176 | |||
177 | 177 | |||
178 | /* | 178 | /* | |
179 | * The remaining code implements the routing-table sysctl node. It is | 179 | * The remaining code implements the routing-table sysctl node. It is | |
180 | * compiled only for the non-COMPAT case. | 180 | * compiled only for the non-COMPAT case. | |
181 | */ | 181 | */ | |
182 | 182 |
--- src/sys/netinet6/nd6.c 2019/08/31 01:49:45 1.261
+++ src/sys/netinet6/nd6.c 2019/09/01 18:54:38 1.262
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: nd6.c,v 1.261 2019/08/31 01:49:45 roy Exp $ */ | 1 | /* $NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $ */ | |
2 | /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ | 2 | /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 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.c,v 1.261 2019/08/31 01:49:45 roy Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $"); | |
35 | 35 | |||
36 | #ifdef _KERNEL_OPT | 36 | #ifdef _KERNEL_OPT | |
37 | #include "opt_net_mpsafe.h" | 37 | #include "opt_net_mpsafe.h" | |
38 | #endif | 38 | #endif | |
39 | 39 | |||
40 | #include "bridge.h" | 40 | #include "bridge.h" | |
41 | #include "carp.h" | 41 | #include "carp.h" | |
42 | 42 | |||
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/systm.h> | 44 | #include <sys/systm.h> | |
45 | #include <sys/callout.h> | 45 | #include <sys/callout.h> | |
46 | #include <sys/kmem.h> | 46 | #include <sys/kmem.h> | |
47 | #include <sys/mbuf.h> | 47 | #include <sys/mbuf.h> | |
@@ -451,71 +451,76 @@ nd6_llinfo_get_holdsrc(struct llentry *l | @@ -451,71 +451,76 @@ nd6_llinfo_get_holdsrc(struct llentry *l | |||
451 | src = NULL; | 451 | src = NULL; | |
452 | 452 | |||
453 | return src; | 453 | return src; | |
454 | } | 454 | } | |
455 | 455 | |||
456 | static void | 456 | static void | |
457 | nd6_llinfo_timer(void *arg) | 457 | nd6_llinfo_timer(void *arg) | |
458 | { | 458 | { | |
459 | struct llentry *ln = arg; | 459 | struct llentry *ln = arg; | |
460 | struct ifnet *ifp; | 460 | struct ifnet *ifp; | |
461 | struct nd_ifinfo *ndi = NULL; | 461 | struct nd_ifinfo *ndi = NULL; | |
462 | bool send_ns = false; | 462 | bool send_ns = false; | |
463 | const struct in6_addr *daddr6 = NULL; | 463 | const struct in6_addr *daddr6 = NULL; | |
464 | const struct in6_addr *taddr6 = &ln->r_l3addr.addr6; | |||
465 | struct sockaddr_in6 sin6; | |||
464 | 466 | |||
465 | SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE(); | 467 | SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE(); | |
466 | 468 | |||
467 | LLE_WLOCK(ln); | 469 | LLE_WLOCK(ln); | |
468 | if ((ln->la_flags & LLE_LINKED) == 0) | 470 | if ((ln->la_flags & LLE_LINKED) == 0) | |
469 | goto out; | 471 | goto out; | |
470 | if (ln->ln_ntick > 0) { | 472 | if (ln->ln_ntick > 0) { | |
471 | nd6_llinfo_settimer(ln, ln->ln_ntick); | 473 | nd6_llinfo_settimer(ln, ln->ln_ntick); | |
472 | goto out; | 474 | goto out; | |
473 | } | 475 | } | |
474 | 476 | |||
475 | ||||
476 | ifp = ln->lle_tbl->llt_ifp; | 477 | ifp = ln->lle_tbl->llt_ifp; | |
477 | KASSERT(ifp != NULL); | 478 | KASSERT(ifp != NULL); | |
478 | 479 | |||
479 | ndi = ND_IFINFO(ifp); | 480 | ndi = ND_IFINFO(ifp); | |
480 | 481 | |||
481 | switch (ln->ln_state) { | 482 | switch (ln->ln_state) { | |
482 | case ND6_LLINFO_INCOMPLETE: | 483 | case ND6_LLINFO_INCOMPLETE: | |
483 | if (ln->ln_asked < nd6_mmaxtries) { | 484 | if (ln->ln_asked < nd6_mmaxtries) { | |
484 | ln->ln_asked++; | 485 | ln->ln_asked++; | |
485 | send_ns = true; | 486 | send_ns = true; | |
486 | } else { | 487 | break; | |
487 | struct mbuf *m = ln->ln_hold; | 488 | } | |
488 | if (m) { | |||
489 | struct mbuf *m0; | |||
490 | 489 | |||
491 | /* | 490 | if (ln->ln_hold) { | |
492 | * assuming every packet in ln_hold has | 491 | struct mbuf *m = ln->ln_hold, *m0; | |
493 | * the same IP header | 492 | ||
494 | */ | 493 | /* | |
495 | m0 = m->m_nextpkt; | 494 | * assuming every packet in ln_hold has | |
496 | m->m_nextpkt = NULL; | 495 | * the same IP header | |
497 | ln->ln_hold = m0; | 496 | */ | |
498 | clear_llinfo_pqueue(ln); | 497 | m0 = m->m_nextpkt; | |
499 | } | 498 | m->m_nextpkt = NULL; | |
500 | LLE_REMREF(ln); | 499 | ln->ln_hold = m0; | |
501 | nd6_free(ln, 0); | 500 | clear_llinfo_pqueue(ln); | |
502 | ln = NULL; | 501 | ||
503 | if (m != NULL) { | 502 | icmp6_error2(m, ICMP6_DST_UNREACH, | |
504 | icmp6_error2(m, ICMP6_DST_UNREACH, | 503 | ICMP6_DST_UNREACH_ADDR, 0, ifp); | |
505 | ICMP6_DST_UNREACH_ADDR, 0, ifp); | |||
506 | } | |||
507 | } | 504 | } | |
505 | ||||
506 | sockaddr_in6_init(&sin6, taddr6, 0, 0, 0); | |||
507 | rt_clonedmsg(RTM_MISS, sin6tosa(&sin6), NULL, ifp); | |||
508 | ||||
509 | LLE_REMREF(ln); | |||
510 | nd6_free(ln, 0); | |||
511 | ln = NULL; | |||
508 | break; | 512 | break; | |
513 | ||||
509 | case ND6_LLINFO_REACHABLE: | 514 | case ND6_LLINFO_REACHABLE: | |
510 | if (!ND6_LLINFO_PERMANENT(ln)) { | 515 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
511 | ln->ln_state = ND6_LLINFO_STALE; | 516 | ln->ln_state = ND6_LLINFO_STALE; | |
512 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); | 517 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); | |
513 | } | 518 | } | |
514 | break; | 519 | break; | |
515 | 520 | |||
516 | case ND6_LLINFO_PURGE: | 521 | case ND6_LLINFO_PURGE: | |
517 | case ND6_LLINFO_STALE: | 522 | case ND6_LLINFO_STALE: | |
518 | /* Garbage Collection(RFC 2461 5.3) */ | 523 | /* Garbage Collection(RFC 2461 5.3) */ | |
519 | if (!ND6_LLINFO_PERMANENT(ln)) { | 524 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
520 | LLE_REMREF(ln); | 525 | LLE_REMREF(ln); | |
521 | nd6_free(ln, 1); | 526 | nd6_free(ln, 1); | |
@@ -540,27 +545,26 @@ nd6_llinfo_timer(void *arg) | @@ -540,27 +545,26 @@ nd6_llinfo_timer(void *arg) | |||
540 | ln->ln_asked++; | 545 | ln->ln_asked++; | |
541 | daddr6 = &ln->r_l3addr.addr6; | 546 | daddr6 = &ln->r_l3addr.addr6; | |
542 | send_ns = true; | 547 | send_ns = true; | |
543 | } else { | 548 | } else { | |
544 | LLE_REMREF(ln); | 549 | LLE_REMREF(ln); | |
545 | nd6_free(ln, 0); | 550 | nd6_free(ln, 0); | |
546 | ln = NULL; | 551 | ln = NULL; | |
547 | } | 552 | } | |
548 | break; | 553 | break; | |
549 | } | 554 | } | |
550 | 555 | |||
551 | if (send_ns) { | 556 | if (send_ns) { | |
552 | struct in6_addr src, *psrc; | 557 | struct in6_addr src, *psrc; | |
553 | const struct in6_addr *taddr6 = &ln->r_l3addr.addr6; | |||
554 | 558 | |||
555 | nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000); | 559 | nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000); | |
556 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | 560 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | |
557 | LLE_FREE_LOCKED(ln); | 561 | LLE_FREE_LOCKED(ln); | |
558 | ln = NULL; | 562 | ln = NULL; | |
559 | nd6_ns_output(ifp, daddr6, taddr6, psrc, NULL); | 563 | nd6_ns_output(ifp, daddr6, taddr6, psrc, NULL); | |
560 | } | 564 | } | |
561 | 565 | |||
562 | out: | 566 | out: | |
563 | if (ln != NULL) | 567 | if (ln != NULL) | |
564 | LLE_FREE_LOCKED(ln); | 568 | LLE_FREE_LOCKED(ln); | |
565 | SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); | 569 | SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); | |
566 | } | 570 | } | |
@@ -1181,28 +1185,26 @@ nd6_is_addr_neighbor(const struct sockad | @@ -1181,28 +1185,26 @@ nd6_is_addr_neighbor(const struct sockad | |||
1181 | } | 1185 | } | |
1182 | 1186 | |||
1183 | /* | 1187 | /* | |
1184 | * Free an nd6 llinfo entry. | 1188 | * Free an nd6 llinfo entry. | |
1185 | * Since the function would cause significant changes in the kernel, DO NOT | 1189 | * Since the function would cause significant changes in the kernel, DO NOT | |
1186 | * make it global, unless you have a strong reason for the change, and are sure | 1190 | * make it global, unless you have a strong reason for the change, and are sure | |
1187 | * that the change is safe. | 1191 | * that the change is safe. | |
1188 | */ | 1192 | */ | |
1189 | static void | 1193 | static void | |
1190 | nd6_free(struct llentry *ln, int gc) | 1194 | nd6_free(struct llentry *ln, int gc) | |
1191 | { | 1195 | { | |
1192 | struct ifnet *ifp; | 1196 | struct ifnet *ifp; | |
1193 | struct in6_addr *in6; | 1197 | struct in6_addr *in6; | |
1194 | struct sockaddr_in6 sin6; | |||
1195 | const char *lladdr; | |||
1196 | 1198 | |||
1197 | KASSERT(ln != NULL); | 1199 | KASSERT(ln != NULL); | |
1198 | LLE_WLOCK_ASSERT(ln); | 1200 | LLE_WLOCK_ASSERT(ln); | |
1199 | 1201 | |||
1200 | ifp = ln->lle_tbl->llt_ifp; | 1202 | ifp = ln->lle_tbl->llt_ifp; | |
1201 | in6 = &ln->r_l3addr.addr6; | 1203 | in6 = &ln->r_l3addr.addr6; | |
1202 | /* | 1204 | /* | |
1203 | * we used to have pfctlinput(PRC_HOSTDEAD) here. | 1205 | * we used to have pfctlinput(PRC_HOSTDEAD) here. | |
1204 | * even though it is not harmful, it was not really necessary. | 1206 | * even though it is not harmful, it was not really necessary. | |
1205 | */ | 1207 | */ | |
1206 | 1208 | |||
1207 | if (!ip6_forwarding && ln->ln_router) { | 1209 | if (!ip6_forwarding && ln->ln_router) { | |
1208 | if (ln->ln_state == ND6_LLINFO_STALE && gc) { | 1210 | if (ln->ln_state == ND6_LLINFO_STALE && gc) { | |
@@ -1272,29 +1274,35 @@ nd6_free(struct llentry *ln, int gc) | @@ -1272,29 +1274,35 @@ nd6_free(struct llentry *ln, int gc) | |||
1272 | #ifdef __FreeBSD__ | 1274 | #ifdef __FreeBSD__ | |
1273 | /* | 1275 | /* | |
1274 | * If this entry was added by an on-link redirect, remove the | 1276 | * If this entry was added by an on-link redirect, remove the | |
1275 | * corresponding host route. | 1277 | * corresponding host route. | |
1276 | */ | 1278 | */ | |
1277 | if (ln->la_flags & LLE_REDIRECT) | 1279 | if (ln->la_flags & LLE_REDIRECT) | |
1278 | nd6_free_redirect(ln); | 1280 | nd6_free_redirect(ln); | |
1279 | #endif | 1281 | #endif | |
1280 | 1282 | |||
1281 | ND6_UNLOCK(); | 1283 | ND6_UNLOCK(); | |
1282 | LLE_WLOCK(ln); | 1284 | LLE_WLOCK(ln); | |
1283 | } | 1285 | } | |
1284 | 1286 | |||
1285 | sockaddr_in6_init(&sin6, in6, 0, 0, 0); | 1287 | if (ln->la_flags & LLE_VALID || gc) { | |
1286 | lladdr = ln->la_flags & LLE_VALID ? (const char *)&ln->ll_addr : NULL; | 1288 | struct sockaddr_in6 sin6; | |
1287 | rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6), lladdr, ifp); | 1289 | const char *lladdr; | |
1290 | ||||
1291 | sockaddr_in6_init(&sin6, in6, 0, 0, 0); | |||
1292 | lladdr = ln->la_flags & LLE_VALID ? | |||
1293 | (const char *)&ln->ll_addr : NULL; | |||
1294 | rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6), lladdr, ifp); | |||
1295 | } | |||
1288 | 1296 | |||
1289 | /* | 1297 | /* | |
1290 | * Save to unlock. We still hold an extra reference and will not | 1298 | * Save to unlock. We still hold an extra reference and will not | |
1291 | * free(9) in llentry_free() if someone else holds one as well. | 1299 | * free(9) in llentry_free() if someone else holds one as well. | |
1292 | */ | 1300 | */ | |
1293 | LLE_WUNLOCK(ln); | 1301 | LLE_WUNLOCK(ln); | |
1294 | IF_AFDATA_LOCK(ifp); | 1302 | IF_AFDATA_LOCK(ifp); | |
1295 | LLE_WLOCK(ln); | 1303 | LLE_WLOCK(ln); | |
1296 | 1304 | |||
1297 | lltable_free_entry(LLTABLE6(ifp), ln); | 1305 | lltable_free_entry(LLTABLE6(ifp), ln); | |
1298 | 1306 | |||
1299 | IF_AFDATA_UNLOCK(ifp); | 1307 | IF_AFDATA_UNLOCK(ifp); | |
1300 | } | 1308 | } | |
@@ -2208,27 +2216,27 @@ nd6_cache_lladdr( | @@ -2208,27 +2216,27 @@ nd6_cache_lladdr( | |||
2208 | ln->ln_router = 0; | 2216 | ln->ln_router = 0; | |
2209 | break; | 2217 | break; | |
2210 | case ND_ROUTER_ADVERT: | 2218 | case ND_ROUTER_ADVERT: | |
2211 | /* | 2219 | /* | |
2212 | * Mark an entry with lladdr as a router. | 2220 | * Mark an entry with lladdr as a router. | |
2213 | */ | 2221 | */ | |
2214 | if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */ | 2222 | if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */ | |
2215 | (is_newentry && lladdr)) { /* (7) */ | 2223 | (is_newentry && lladdr)) { /* (7) */ | |
2216 | ln->ln_router = 1; | 2224 | ln->ln_router = 1; | |
2217 | } | 2225 | } | |
2218 | break; | 2226 | break; | |
2219 | } | 2227 | } | |
2220 | 2228 | |||
2221 | if (do_update) { | 2229 | if (do_update && lladdr != NULL) { | |
2222 | struct sockaddr_in6 sin6; | 2230 | struct sockaddr_in6 sin6; | |
2223 | 2231 | |||
2224 | sockaddr_in6_init(&sin6, from, 0, 0, 0); | 2232 | sockaddr_in6_init(&sin6, from, 0, 0, 0); | |
2225 | rt_clonedmsg(is_newentry ? RTM_ADD : RTM_CHANGE, | 2233 | rt_clonedmsg(is_newentry ? RTM_ADD : RTM_CHANGE, | |
2226 | sin6tosa(&sin6), lladdr, ifp); | 2234 | sin6tosa(&sin6), lladdr, ifp); | |
2227 | } | 2235 | } | |
2228 | 2236 | |||
2229 | if (ln != NULL) { | 2237 | if (ln != NULL) { | |
2230 | router = ln->ln_router; | 2238 | router = ln->ln_router; | |
2231 | LLE_WUNLOCK(ln); | 2239 | LLE_WUNLOCK(ln); | |
2232 | } | 2240 | } | |
2233 | 2241 | |||
2234 | /* | 2242 | /* | |
@@ -2324,47 +2332,41 @@ nd6_resolve(struct ifnet *ifp, const str | @@ -2324,47 +2332,41 @@ nd6_resolve(struct ifnet *ifp, const str | |||
2324 | if (ln != NULL && (ln->la_flags & LLE_VALID) != 0 && | 2332 | if (ln != NULL && (ln->la_flags & LLE_VALID) != 0 && | |
2325 | ln->ln_state == ND6_LLINFO_REACHABLE) { | 2333 | ln->ln_state == ND6_LLINFO_REACHABLE) { | |
2326 | /* Fast path */ | 2334 | /* Fast path */ | |
2327 | memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); | 2335 | memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); | |
2328 | LLE_RUNLOCK(ln); | 2336 | LLE_RUNLOCK(ln); | |
2329 | return 0; | 2337 | return 0; | |
2330 | } | 2338 | } | |
2331 | if (ln != NULL) | 2339 | if (ln != NULL) | |
2332 | LLE_RUNLOCK(ln); | 2340 | LLE_RUNLOCK(ln); | |
2333 | 2341 | |||
2334 | /* Slow path */ | 2342 | /* Slow path */ | |
2335 | ln = nd6_lookup(&dst->sin6_addr, ifp, true); | 2343 | ln = nd6_lookup(&dst->sin6_addr, ifp, true); | |
2336 | if (ln == NULL && nd6_is_addr_neighbor(dst, ifp)) { | 2344 | if (ln == NULL && nd6_is_addr_neighbor(dst, ifp)) { | |
2337 | struct sockaddr_in6 sin6; | |||
2338 | /* | 2345 | /* | |
2339 | * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), | 2346 | * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), | |
2340 | * the condition below is not very efficient. But we believe | 2347 | * the condition below is not very efficient. But we believe | |
2341 | * it is tolerable, because this should be a rare case. | 2348 | * it is tolerable, because this should be a rare case. | |
2342 | */ | 2349 | */ | |
2343 | ln = nd6_create(&dst->sin6_addr, ifp); | 2350 | ln = nd6_create(&dst->sin6_addr, ifp); | |
2344 | if (ln == NULL) { | 2351 | if (ln == NULL) { | |
2345 | char ip6buf[INET6_ADDRSTRLEN]; | 2352 | char ip6buf[INET6_ADDRSTRLEN]; | |
2346 | log(LOG_DEBUG, | 2353 | log(LOG_DEBUG, | |
2347 | "%s: can't allocate llinfo for %s " | 2354 | "%s: can't allocate llinfo for %s " | |
2348 | "(ln=%p, rt=%p)\n", __func__, | 2355 | "(ln=%p, rt=%p)\n", __func__, | |
2349 | IN6_PRINT(ip6buf, &dst->sin6_addr), ln, rt); | 2356 | IN6_PRINT(ip6buf, &dst->sin6_addr), ln, rt); | |
2350 | m_freem(m); | 2357 | m_freem(m); | |
2351 | return ENOBUFS; | 2358 | return ENOBUFS; | |
2352 | } | 2359 | } | |
2353 | ||||
2354 | sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0); | |||
2355 | if (rt != NULL) | |||
2356 | rt_clonedmsg(RTM_ADD, sin6tosa(&sin6), NULL, ifp); | |||
2357 | ||||
2358 | created = true; | 2360 | created = true; | |
2359 | } | 2361 | } | |
2360 | 2362 | |||
2361 | if (ln == NULL) { | 2363 | if (ln == NULL) { | |
2362 | m_freem(m); | 2364 | m_freem(m); | |
2363 | return ENETDOWN; /* better error? */ | 2365 | return ENETDOWN; /* better error? */ | |
2364 | } | 2366 | } | |
2365 | 2367 | |||
2366 | LLE_WLOCK_ASSERT(ln); | 2368 | LLE_WLOCK_ASSERT(ln); | |
2367 | 2369 | |||
2368 | /* We don't have to do link-layer address resolution on a p2p link. */ | 2370 | /* We don't have to do link-layer address resolution on a p2p link. */ | |
2369 | if ((ifp->if_flags & IFF_POINTOPOINT) != 0 && | 2371 | if ((ifp->if_flags & IFF_POINTOPOINT) != 0 && | |
2370 | ln->ln_state < ND6_LLINFO_REACHABLE) { | 2372 | ln->ln_state < ND6_LLINFO_REACHABLE) { | |
@@ -2429,32 +2431,29 @@ nd6_resolve(struct ifnet *ifp, const str | @@ -2429,32 +2431,29 @@ nd6_resolve(struct ifnet *ifp, const str | |||
2429 | } | 2431 | } | |
2430 | 2432 | |||
2431 | /* | 2433 | /* | |
2432 | * If there has been no NS for the neighbor after entering the | 2434 | * If there has been no NS for the neighbor after entering the | |
2433 | * INCOMPLETE state, send the first solicitation. | 2435 | * INCOMPLETE state, send the first solicitation. | |
2434 | */ | 2436 | */ | |
2435 | if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { | 2437 | if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { | |
2436 | struct in6_addr src, *psrc; | 2438 | struct in6_addr src, *psrc; | |
2437 | 2439 | |||
2438 | ln->ln_asked++; | 2440 | ln->ln_asked++; | |
2439 | nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans * hz / 1000); | 2441 | nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans * hz / 1000); | |
2440 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | 2442 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | |
2441 | LLE_WUNLOCK(ln); | 2443 | LLE_WUNLOCK(ln); | |
2442 | ln = NULL; | |||
2443 | nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL); | 2444 | nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL); | |
2444 | } else { | 2445 | } else | |
2445 | /* We did the lookup so we need to do the unlock here. */ | |||
2446 | LLE_WUNLOCK(ln); | 2446 | LLE_WUNLOCK(ln); | |
2447 | } | |||
2448 | 2447 | |||
2449 | if (created) | 2448 | if (created) | |
2450 | nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr); | 2449 | nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr); | |
2451 | 2450 | |||
2452 | return EWOULDBLOCK; | 2451 | return EWOULDBLOCK; | |
2453 | } | 2452 | } | |
2454 | 2453 | |||
2455 | int | 2454 | int | |
2456 | nd6_need_cache(struct ifnet *ifp) | 2455 | nd6_need_cache(struct ifnet *ifp) | |
2457 | { | 2456 | { | |
2458 | /* | 2457 | /* | |
2459 | * XXX: we currently do not make neighbor cache on any interface | 2458 | * XXX: we currently do not make neighbor cache on any interface | |
2460 | * other than ARCnet, Ethernet, FDDI and GIF. | 2459 | * other than ARCnet, Ethernet, FDDI and GIF. |
--- src/sys/netinet6/nd6_nbr.c 2019/08/30 08:40:25 1.171
+++ src/sys/netinet6/nd6_nbr.c 2019/09/01 18:54:38 1.172
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: nd6_nbr.c,v 1.171 2019/08/30 08:40:25 roy Exp $ */ | 1 | /* $NetBSD: nd6_nbr.c,v 1.172 2019/09/01 18:54:38 roy Exp $ */ | |
2 | /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */ | 2 | /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 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 | |
@@ -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_nbr.c,v 1.171 2019/08/30 08:40:25 roy Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.172 2019/09/01 18:54:38 roy Exp $"); | |
35 | 35 | |||
36 | #ifdef _KERNEL_OPT | 36 | #ifdef _KERNEL_OPT | |
37 | #include "opt_inet.h" | 37 | #include "opt_inet.h" | |
38 | #include "opt_net_mpsafe.h" | 38 | #include "opt_net_mpsafe.h" | |
39 | #endif | 39 | #endif | |
40 | 40 | |||
41 | #include <sys/param.h> | 41 | #include <sys/param.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | #include <sys/kmem.h> | 43 | #include <sys/kmem.h> | |
44 | #include <sys/mbuf.h> | 44 | #include <sys/mbuf.h> | |
45 | #include <sys/socket.h> | 45 | #include <sys/socket.h> | |
46 | #include <sys/socketvar.h> | 46 | #include <sys/socketvar.h> | |
47 | #include <sys/sockio.h> | 47 | #include <sys/sockio.h> | |
@@ -595,33 +595,33 @@ nd6_ns_output(struct ifnet *ifp, const s | @@ -595,33 +595,33 @@ nd6_ns_output(struct ifnet *ifp, const s | |||
595 | void | 595 | void | |
596 | nd6_na_input(struct mbuf *m, int off, int icmp6len) | 596 | nd6_na_input(struct mbuf *m, int off, int icmp6len) | |
597 | { | 597 | { | |
598 | struct ifnet *ifp; | 598 | struct ifnet *ifp; | |
599 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); | 599 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); | |
600 | struct nd_neighbor_advert *nd_na; | 600 | struct nd_neighbor_advert *nd_na; | |
601 | struct in6_addr saddr6 = ip6->ip6_src; | 601 | struct in6_addr saddr6 = ip6->ip6_src; | |
602 | struct in6_addr daddr6 = ip6->ip6_dst; | 602 | struct in6_addr daddr6 = ip6->ip6_dst; | |
603 | struct in6_addr taddr6; | 603 | struct in6_addr taddr6; | |
604 | int flags; | 604 | int flags; | |
605 | int is_router; | 605 | int is_router; | |
606 | int is_solicited; | 606 | int is_solicited; | |
607 | int is_override; | 607 | int is_override; | |
608 | int rt_cmd; | |||
608 | char *lladdr = NULL; | 609 | char *lladdr = NULL; | |
609 | int lladdrlen = 0; | 610 | int lladdrlen = 0; | |
610 | struct ifaddr *ifa; | 611 | struct ifaddr *ifa; | |
611 | struct llentry *ln = NULL; | 612 | struct llentry *ln = NULL; | |
612 | union nd_opts ndopts; | 613 | union nd_opts ndopts; | |
613 | struct sockaddr_in6 ssin6; | 614 | struct sockaddr_in6 ssin6; | |
614 | bool rt_announce; | |||
615 | bool checklink = false; | 615 | bool checklink = false; | |
616 | struct psref psref; | 616 | struct psref psref; | |
617 | struct psref psref_ia; | 617 | struct psref psref_ia; | |
618 | char ip6buf[INET6_ADDRSTRLEN], ip6buf2[INET6_ADDRSTRLEN]; | 618 | char ip6buf[INET6_ADDRSTRLEN], ip6buf2[INET6_ADDRSTRLEN]; | |
619 | 619 | |||
620 | ifp = m_get_rcvif_psref(m, &psref); | 620 | ifp = m_get_rcvif_psref(m, &psref); | |
621 | if (ifp == NULL) | 621 | if (ifp == NULL) | |
622 | goto freeit; | 622 | goto freeit; | |
623 | 623 | |||
624 | if (ip6->ip6_hlim != 255) { | 624 | if (ip6->ip6_hlim != 255) { | |
625 | nd6log(LOG_ERR, | 625 | nd6log(LOG_ERR, | |
626 | "invalid hlim (%d) from %s to %s on %s\n", | 626 | "invalid hlim (%d) from %s to %s on %s\n", | |
627 | ip6->ip6_hlim, IN6_PRINT(ip6buf, &ip6->ip6_src), | 627 | ip6->ip6_hlim, IN6_PRINT(ip6buf, &ip6->ip6_src), | |
@@ -725,41 +725,41 @@ nd6_na_input(struct mbuf *m, int off, in | @@ -725,41 +725,41 @@ nd6_na_input(struct mbuf *m, int off, in | |||
725 | nd6log(LOG_INFO, "ND packet from non-neighbor %s on %s\n", | 725 | nd6log(LOG_INFO, "ND packet from non-neighbor %s on %s\n", | |
726 | IN6_PRINT(ip6buf, &saddr6), if_name(ifp)); | 726 | IN6_PRINT(ip6buf, &saddr6), if_name(ifp)); | |
727 | goto bad; | 727 | goto bad; | |
728 | } | 728 | } | |
729 | 729 | |||
730 | /* | 730 | /* | |
731 | * If no neighbor cache entry is found, NA SHOULD silently be | 731 | * If no neighbor cache entry is found, NA SHOULD silently be | |
732 | * discarded. | 732 | * discarded. | |
733 | */ | 733 | */ | |
734 | ln = nd6_lookup(&taddr6, ifp, true); | 734 | ln = nd6_lookup(&taddr6, ifp, true); | |
735 | if (ln == NULL) | 735 | if (ln == NULL) | |
736 | goto freeit; | 736 | goto freeit; | |
737 | 737 | |||
738 | rt_announce = false; | 738 | rt_cmd = 0; | |
739 | if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { | 739 | if (ln->ln_state == ND6_LLINFO_INCOMPLETE) { | |
740 | /* | 740 | /* | |
741 | * If the link-layer has address, and no lladdr option came, | 741 | * If the link-layer has address, and no lladdr option came, | |
742 | * discard the packet. | 742 | * discard the packet. | |
743 | */ | 743 | */ | |
744 | if (ifp->if_addrlen && !lladdr) | 744 | if (ifp->if_addrlen && !lladdr) | |
745 | goto freeit; | 745 | goto freeit; | |
746 | 746 | |||
747 | /* | 747 | /* | |
748 | * Record link-layer address, and update the state. | 748 | * Record link-layer address, and update the state. | |
749 | */ | 749 | */ | |
750 | memcpy(&ln->ll_addr, lladdr, ifp->if_addrlen); | 750 | memcpy(&ln->ll_addr, lladdr, ifp->if_addrlen); | |
751 | ln->la_flags |= LLE_VALID; | 751 | ln->la_flags |= LLE_VALID; | |
752 | rt_announce = true; | 752 | rt_cmd = RTM_ADD; | |
753 | if (is_solicited) { | 753 | if (is_solicited) { | |
754 | ln->ln_state = ND6_LLINFO_REACHABLE; | 754 | ln->ln_state = ND6_LLINFO_REACHABLE; | |
755 | ln->ln_byhint = 0; | 755 | ln->ln_byhint = 0; | |
756 | if (!ND6_LLINFO_PERMANENT(ln)) { | 756 | if (!ND6_LLINFO_PERMANENT(ln)) { | |
757 | nd6_llinfo_settimer(ln, | 757 | nd6_llinfo_settimer(ln, | |
758 | ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz); | 758 | ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz); | |
759 | } | 759 | } | |
760 | } else { | 760 | } else { | |
761 | ln->ln_state = ND6_LLINFO_STALE; | 761 | ln->ln_state = ND6_LLINFO_STALE; | |
762 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); | 762 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); | |
763 | } | 763 | } | |
764 | if ((ln->ln_router = is_router) != 0) { | 764 | if ((ln->ln_router = is_router) != 0) { | |
765 | /* | 765 | /* | |
@@ -770,32 +770,34 @@ nd6_na_input(struct mbuf *m, int off, in | @@ -770,32 +770,34 @@ nd6_na_input(struct mbuf *m, int off, in | |||
770 | checklink = true; | 770 | checklink = true; | |
771 | } | 771 | } | |
772 | } else { | 772 | } else { | |
773 | bool llchange; | 773 | bool llchange; | |
774 | 774 | |||
775 | /* | 775 | /* | |
776 | * Check if the link-layer address has changed or not. | 776 | * Check if the link-layer address has changed or not. | |
777 | */ | 777 | */ | |
778 | if (lladdr == NULL) | 778 | if (lladdr == NULL) | |
779 | llchange = false; | 779 | llchange = false; | |
780 | else { | 780 | else { | |
781 | if (ln->la_flags & LLE_VALID) { | 781 | if (ln->la_flags & LLE_VALID) { | |
782 | if (memcmp(lladdr, &ln->ll_addr, ifp->if_addrlen)) | 782 | if (memcmp(lladdr, &ln->ll_addr, ifp->if_addrlen)) | |
783 | llchange = rt_announce = true; | 783 | llchange = true; | |
784 | else | 784 | else | |
785 | llchange = false; | 785 | llchange = false; | |
786 | } else | 786 | } else | |
787 | llchange = rt_announce = true; | 787 | llchange = true; | |
788 | } | 788 | } | |
789 | if (llchange) | |||
790 | rt_cmd = RTM_CHANGE; | |||
789 | 791 | |||
790 | /* | 792 | /* | |
791 | * This is VERY complex. Look at it with care. | 793 | * This is VERY complex. Look at it with care. | |
792 | * | 794 | * | |
793 | * override solicit lladdr llchange action | 795 | * override solicit lladdr llchange action | |
794 | * (L: record lladdr) | 796 | * (L: record lladdr) | |
795 | * | 797 | * | |
796 | * 0 0 n -- (2c) | 798 | * 0 0 n -- (2c) | |
797 | * 0 0 y n (2b) L | 799 | * 0 0 y n (2b) L | |
798 | * 0 0 y y (1) REACHABLE->STALE | 800 | * 0 0 y y (1) REACHABLE->STALE | |
799 | * 0 1 n -- (2c) *->REACHABLE | 801 | * 0 1 n -- (2c) *->REACHABLE | |
800 | * 0 1 y n (2b) L *->REACHABLE | 802 | * 0 1 y n (2b) L *->REACHABLE | |
801 | * 0 1 y y (1) REACHABLE->STALE | 803 | * 0 1 y y (1) REACHABLE->STALE | |
@@ -872,31 +874,31 @@ nd6_na_input(struct mbuf *m, int off, in | @@ -872,31 +874,31 @@ nd6_na_input(struct mbuf *m, int off, in | |||
872 | nd6_rt_flush(&ip6->ip6_src, ln->lle_tbl->llt_ifp); | 874 | nd6_rt_flush(&ip6->ip6_src, ln->lle_tbl->llt_ifp); | |
873 | } | 875 | } | |
874 | ND6_UNLOCK(); | 876 | ND6_UNLOCK(); | |
875 | } | 877 | } | |
876 | ln->ln_router = is_router; | 878 | ln->ln_router = is_router; | |
877 | } | 879 | } | |
878 | /* | 880 | /* | |
879 | * XXX: does this matter? | 881 | * XXX: does this matter? | |
880 | * rt->rt_flags &= ~RTF_REJECT; | 882 | * rt->rt_flags &= ~RTF_REJECT; | |
881 | */ | 883 | */ | |
882 | ln->ln_asked = 0; | 884 | ln->ln_asked = 0; | |
883 | nd6_llinfo_release_pkts(ln, ifp); | 885 | nd6_llinfo_release_pkts(ln, ifp); | |
884 | 886 | |||
885 | if (rt_announce) { | 887 | if (rt_cmd != 0) { | |
886 | struct sockaddr_in6 sin6; | 888 | struct sockaddr_in6 sin6; | |
887 | 889 | |||
888 | sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0); | 890 | sockaddr_in6_init(&sin6, &ln->r_l3addr.addr6, 0, 0, 0); | |
889 | rt_clonedmsg(RTM_CHANGE, sin6tosa(&sin6), | 891 | rt_clonedmsg(rt_cmd, sin6tosa(&sin6), | |
890 | (char *)&ln->ll_addr, ln->lle_tbl->llt_ifp); | 892 | (char *)&ln->ll_addr, ln->lle_tbl->llt_ifp); | |
891 | } | 893 | } | |
892 | 894 | |||
893 | freeit: | 895 | freeit: | |
894 | if (ln != NULL) | 896 | if (ln != NULL) | |
895 | LLE_WUNLOCK(ln); | 897 | LLE_WUNLOCK(ln); | |
896 | 898 | |||
897 | if (checklink) { | 899 | if (checklink) { | |
898 | ND6_WLOCK(); | 900 | ND6_WLOCK(); | |
899 | nd6_pfxlist_onlink_check(); | 901 | nd6_pfxlist_onlink_check(); | |
900 | ND6_UNLOCK(); | 902 | ND6_UNLOCK(); | |
901 | } | 903 | } | |
902 | 904 |