| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: nd6.c,v 1.262 2019/09/01 18:54:38 roy Exp $ */ | | 1 | /* $NetBSD: nd6.c,v 1.263 2019/09/01 19:26:21 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.262 2019/09/01 18:54:38 roy Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.263 2019/09/01 19:26:21 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> |
| @@ -470,55 +470,68 @@ nd6_llinfo_timer(void *arg) | | | @@ -470,55 +470,68 @@ nd6_llinfo_timer(void *arg) |
470 | if ((ln->la_flags & LLE_LINKED) == 0) | | 470 | if ((ln->la_flags & LLE_LINKED) == 0) |
471 | goto out; | | 471 | goto out; |
472 | if (ln->ln_ntick > 0) { | | 472 | if (ln->ln_ntick > 0) { |
473 | nd6_llinfo_settimer(ln, ln->ln_ntick); | | 473 | nd6_llinfo_settimer(ln, ln->ln_ntick); |
474 | goto out; | | 474 | goto out; |
475 | } | | 475 | } |
476 | | | 476 | |
477 | ifp = ln->lle_tbl->llt_ifp; | | 477 | ifp = ln->lle_tbl->llt_ifp; |
478 | KASSERT(ifp != NULL); | | 478 | KASSERT(ifp != NULL); |
479 | | | 479 | |
480 | ndi = ND_IFINFO(ifp); | | 480 | ndi = ND_IFINFO(ifp); |
481 | | | 481 | |
482 | switch (ln->ln_state) { | | 482 | switch (ln->ln_state) { |
| | | 483 | case ND6_LLINFO_WAITDELETE: |
| | | 484 | LLE_REMREF(ln); |
| | | 485 | nd6_free(ln, 0); |
| | | 486 | ln = NULL; |
| | | 487 | break; |
| | | 488 | |
483 | case ND6_LLINFO_INCOMPLETE: | | 489 | case ND6_LLINFO_INCOMPLETE: |
484 | if (ln->ln_asked < nd6_mmaxtries) { | | 490 | if (ln->ln_asked++ < nd6_mmaxtries) { |
485 | ln->ln_asked++; | | | |
486 | send_ns = true; | | 491 | send_ns = true; |
487 | break; | | 492 | break; |
488 | } | | 493 | } |
489 | | | 494 | |
490 | if (ln->ln_hold) { | | 495 | if (ln->ln_hold) { |
491 | struct mbuf *m = ln->ln_hold, *m0; | | 496 | struct mbuf *m = ln->ln_hold, *m0; |
492 | | | 497 | |
493 | /* | | 498 | /* |
494 | * assuming every packet in ln_hold has | | 499 | * assuming every packet in ln_hold has |
495 | * the same IP header | | 500 | * the same IP header |
496 | */ | | 501 | */ |
497 | m0 = m->m_nextpkt; | | 502 | m0 = m->m_nextpkt; |
498 | m->m_nextpkt = NULL; | | 503 | m->m_nextpkt = NULL; |
499 | ln->ln_hold = m0; | | 504 | ln->ln_hold = m0; |
500 | clear_llinfo_pqueue(ln); | | 505 | clear_llinfo_pqueue(ln); |
501 | | | 506 | |
502 | icmp6_error2(m, ICMP6_DST_UNREACH, | | 507 | icmp6_error2(m, ICMP6_DST_UNREACH, |
503 | ICMP6_DST_UNREACH_ADDR, 0, ifp); | | 508 | ICMP6_DST_UNREACH_ADDR, 0, ifp); |
504 | } | | 509 | } |
505 | | | 510 | |
506 | sockaddr_in6_init(&sin6, taddr6, 0, 0, 0); | | 511 | sockaddr_in6_init(&sin6, taddr6, 0, 0, 0); |
507 | rt_clonedmsg(RTM_MISS, sin6tosa(&sin6), NULL, ifp); | | 512 | rt_clonedmsg(RTM_MISS, sin6tosa(&sin6), NULL, ifp); |
508 | | | 513 | |
509 | LLE_REMREF(ln); | | 514 | /* |
510 | nd6_free(ln, 0); | | 515 | * Move to the ND6_LLINFO_WAITDELETE state for another |
511 | ln = NULL; | | 516 | * interval at which point the llentry will be freed |
| | | 517 | * unless it's attempted to be used again and we'll |
| | | 518 | * resend NS again, rinse and repeat. |
| | | 519 | */ |
| | | 520 | ln->ln_state = ND6_LLINFO_WAITDELETE; |
| | | 521 | if (ln->ln_asked == nd6_mmaxtries) |
| | | 522 | nd6_llinfo_settimer(ln, ndi->retrans * hz / 1000); |
| | | 523 | else |
| | | 524 | send_ns = true; |
512 | break; | | 525 | break; |
513 | | | 526 | |
514 | case ND6_LLINFO_REACHABLE: | | 527 | case ND6_LLINFO_REACHABLE: |
515 | if (!ND6_LLINFO_PERMANENT(ln)) { | | 528 | if (!ND6_LLINFO_PERMANENT(ln)) { |
516 | ln->ln_state = ND6_LLINFO_STALE; | | 529 | ln->ln_state = ND6_LLINFO_STALE; |
517 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); | | 530 | nd6_llinfo_settimer(ln, nd6_gctimer * hz); |
518 | } | | 531 | } |
519 | break; | | 532 | break; |
520 | | | 533 | |
521 | case ND6_LLINFO_PURGE: | | 534 | case ND6_LLINFO_PURGE: |
522 | case ND6_LLINFO_STALE: | | 535 | case ND6_LLINFO_STALE: |
523 | /* Garbage Collection(RFC 2461 5.3) */ | | 536 | /* Garbage Collection(RFC 2461 5.3) */ |
524 | if (!ND6_LLINFO_PERMANENT(ln)) { | | 537 | if (!ND6_LLINFO_PERMANENT(ln)) { |
| @@ -2302,26 +2315,27 @@ nd6_slowtimo(void *ignored_arg) | | | @@ -2302,26 +2315,27 @@ nd6_slowtimo(void *ignored_arg) |
2302 | | | 2315 | |
2303 | /* | | 2316 | /* |
2304 | * Return 0 if a neighbor cache is found. Return EWOULDBLOCK if a cache is not | | 2317 | * Return 0 if a neighbor cache is found. Return EWOULDBLOCK if a cache is not |
2305 | * found and trying to resolve a neighbor; in this case the mbuf is queued in | | 2318 | * found and trying to resolve a neighbor; in this case the mbuf is queued in |
2306 | * the list. Otherwise return errno after freeing the mbuf. | | 2319 | * the list. Otherwise return errno after freeing the mbuf. |
2307 | */ | | 2320 | */ |
2308 | int | | 2321 | int |
2309 | nd6_resolve(struct ifnet *ifp, const struct rtentry *rt, struct mbuf *m, | | 2322 | nd6_resolve(struct ifnet *ifp, const struct rtentry *rt, struct mbuf *m, |
2310 | const struct sockaddr *_dst, uint8_t *lldst, size_t dstsize) | | 2323 | const struct sockaddr *_dst, uint8_t *lldst, size_t dstsize) |
2311 | { | | 2324 | { |
2312 | struct llentry *ln = NULL; | | 2325 | struct llentry *ln = NULL; |
2313 | bool created = false; | | 2326 | bool created = false; |
2314 | const struct sockaddr_in6 *dst = satocsin6(_dst); | | 2327 | const struct sockaddr_in6 *dst = satocsin6(_dst); |
| | | 2328 | int error; |
2315 | | | 2329 | |
2316 | /* discard the packet if IPv6 operation is disabled on the interface */ | | 2330 | /* discard the packet if IPv6 operation is disabled on the interface */ |
2317 | if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { | | 2331 | if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { |
2318 | m_freem(m); | | 2332 | m_freem(m); |
2319 | return ENETDOWN; /* better error? */ | | 2333 | return ENETDOWN; /* better error? */ |
2320 | } | | 2334 | } |
2321 | | | 2335 | |
2322 | /* | | 2336 | /* |
2323 | * Address resolution or Neighbor Unreachability Detection | | 2337 | * Address resolution or Neighbor Unreachability Detection |
2324 | * for the next hop. | | 2338 | * for the next hop. |
2325 | * At this point, the destination of the packet must be a unicast | | 2339 | * At this point, the destination of the packet must be a unicast |
2326 | * or an anycast address(i.e. not a multicast). | | 2340 | * or an anycast address(i.e. not a multicast). |
2327 | */ | | 2341 | */ |
| @@ -2396,69 +2410,76 @@ nd6_resolve(struct ifnet *ifp, const str | | | @@ -2396,69 +2410,76 @@ nd6_resolve(struct ifnet *ifp, const str |
2396 | KASSERT((ln->la_flags & LLE_VALID) != 0); | | 2410 | KASSERT((ln->la_flags & LLE_VALID) != 0); |
2397 | memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); | | 2411 | memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); |
2398 | LLE_WUNLOCK(ln); | | 2412 | LLE_WUNLOCK(ln); |
2399 | return 0; | | 2413 | return 0; |
2400 | } | | 2414 | } |
2401 | | | 2415 | |
2402 | /* | | 2416 | /* |
2403 | * There is a neighbor cache entry, but no ethernet address | | 2417 | * There is a neighbor cache entry, but no ethernet address |
2404 | * response yet. Append this latest packet to the end of the | | 2418 | * response yet. Append this latest packet to the end of the |
2405 | * packet queue in the mbuf, unless the number of the packet | | 2419 | * packet queue in the mbuf, unless the number of the packet |
2406 | * does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen, | | 2420 | * does not exceed nd6_maxqueuelen. When it exceeds nd6_maxqueuelen, |
2407 | * the oldest packet in the queue will be removed. | | 2421 | * the oldest packet in the queue will be removed. |
2408 | */ | | 2422 | */ |
2409 | if (ln->ln_state == ND6_LLINFO_NOSTATE) | | 2423 | if (ln->ln_state == ND6_LLINFO_NOSTATE || |
| | | 2424 | ln->ln_state == ND6_LLINFO_WAITDELETE) |
2410 | ln->ln_state = ND6_LLINFO_INCOMPLETE; | | 2425 | ln->ln_state = ND6_LLINFO_INCOMPLETE; |
2411 | if (ln->ln_hold) { | | 2426 | if (ln->ln_hold) { |
2412 | struct mbuf *m_hold; | | 2427 | struct mbuf *m_hold; |
2413 | int i; | | 2428 | int i; |
2414 | | | 2429 | |
2415 | i = 0; | | 2430 | i = 0; |
2416 | for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) { | | 2431 | for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) { |
2417 | i++; | | 2432 | i++; |
2418 | if (m_hold->m_nextpkt == NULL) { | | 2433 | if (m_hold->m_nextpkt == NULL) { |
2419 | m_hold->m_nextpkt = m; | | 2434 | m_hold->m_nextpkt = m; |
2420 | break; | | 2435 | break; |
2421 | } | | 2436 | } |
2422 | } | | 2437 | } |
2423 | while (i >= nd6_maxqueuelen) { | | 2438 | while (i >= nd6_maxqueuelen) { |
2424 | m_hold = ln->ln_hold; | | 2439 | m_hold = ln->ln_hold; |
2425 | ln->ln_hold = ln->ln_hold->m_nextpkt; | | 2440 | ln->ln_hold = ln->ln_hold->m_nextpkt; |
2426 | m_freem(m_hold); | | 2441 | m_freem(m_hold); |
2427 | i--; | | 2442 | i--; |
2428 | } | | 2443 | } |
2429 | } else { | | 2444 | } else { |
2430 | ln->ln_hold = m; | | 2445 | ln->ln_hold = m; |
2431 | } | | 2446 | } |
2432 | | | 2447 | |
| | | 2448 | if (ln->ln_asked >= nd6_mmaxtries) |
| | | 2449 | error = (rt != NULL && rt->rt_flags & RTF_GATEWAY) ? |
| | | 2450 | EHOSTUNREACH : EHOSTDOWN; |
| | | 2451 | else |
| | | 2452 | error = EWOULDBLOCK; |
| | | 2453 | |
2433 | /* | | 2454 | /* |
2434 | * If there has been no NS for the neighbor after entering the | | 2455 | * If there has been no NS for the neighbor after entering the |
2435 | * INCOMPLETE state, send the first solicitation. | | 2456 | * INCOMPLETE state, send the first solicitation. |
2436 | */ | | 2457 | */ |
2437 | if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { | | 2458 | if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { |
2438 | struct in6_addr src, *psrc; | | 2459 | struct in6_addr src, *psrc; |
2439 | | | 2460 | |
2440 | ln->ln_asked++; | | 2461 | ln->ln_asked++; |
2441 | nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans * hz / 1000); | | 2462 | nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans * hz / 1000); |
2442 | psrc = nd6_llinfo_get_holdsrc(ln, &src); | | 2463 | psrc = nd6_llinfo_get_holdsrc(ln, &src); |
2443 | LLE_WUNLOCK(ln); | | 2464 | LLE_WUNLOCK(ln); |
2444 | nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL); | | 2465 | nd6_ns_output(ifp, NULL, &dst->sin6_addr, psrc, NULL); |
2445 | } else | | 2466 | } else |
2446 | LLE_WUNLOCK(ln); | | 2467 | LLE_WUNLOCK(ln); |
2447 | | | 2468 | |
2448 | if (created) | | 2469 | if (created) |
2449 | nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr); | | 2470 | nd6_gc_neighbors(LLTABLE6(ifp), &dst->sin6_addr); |
2450 | | | 2471 | |
2451 | return EWOULDBLOCK; | | 2472 | return error; |
2452 | } | | 2473 | } |
2453 | | | 2474 | |
2454 | int | | 2475 | int |
2455 | nd6_need_cache(struct ifnet *ifp) | | 2476 | nd6_need_cache(struct ifnet *ifp) |
2456 | { | | 2477 | { |
2457 | /* | | 2478 | /* |
2458 | * XXX: we currently do not make neighbor cache on any interface | | 2479 | * XXX: we currently do not make neighbor cache on any interface |
2459 | * other than ARCnet, Ethernet, FDDI and GIF. | | 2480 | * other than ARCnet, Ethernet, FDDI and GIF. |
2460 | * | | 2481 | * |
2461 | * RFC2893 says: | | 2482 | * RFC2893 says: |
2462 | * - unidirectional tunnels needs no ND | | 2483 | * - unidirectional tunnels needs no ND |
2463 | */ | | 2484 | */ |
2464 | switch (ifp->if_type) { | | 2485 | switch (ifp->if_type) { |