| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: nd6_rtr.c,v 1.93.2.3 2015/05/02 18:23:25 martin Exp $ */ | | 1 | /* $NetBSD: nd6_rtr.c,v 1.93.2.4 2020/04/15 14:52:28 martin 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.93.2.3 2015/05/02 18:23:25 martin Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.93.2.4 2020/04/15 14:52:28 martin 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> |
| @@ -462,26 +462,30 @@ defrouter_addreq(struct nd_defrouter *ne | | | @@ -462,26 +462,30 @@ defrouter_addreq(struct nd_defrouter *ne |
462 | gate.sin6.sin6_scope_id = 0; /* XXX */ | | 462 | gate.sin6.sin6_scope_id = 0; /* XXX */ |
463 | #endif | | 463 | #endif |
464 | | | 464 | |
465 | s = splsoftnet(); | | 465 | s = splsoftnet(); |
466 | error = rtrequest(RTM_ADD, &def.sa, &gate.sa, &mask.sa, | | 466 | error = rtrequest(RTM_ADD, &def.sa, &gate.sa, &mask.sa, |
467 | RTF_GATEWAY, &newrt); | | 467 | RTF_GATEWAY, &newrt); |
468 | if (newrt) { | | 468 | if (newrt) { |
469 | nd6_rtmsg(RTM_ADD, newrt); /* tell user process */ | | 469 | nd6_rtmsg(RTM_ADD, newrt); /* tell user process */ |
470 | newrt->rt_refcnt--; | | 470 | newrt->rt_refcnt--; |
471 | nd6_numroutes++; | | 471 | nd6_numroutes++; |
472 | } | | 472 | } |
473 | if (error == 0) | | 473 | if (error == 0) |
474 | new->installed = 1; | | 474 | new->installed = 1; |
| | | 475 | else |
| | | 476 | log(LOG_ERR, "defrouter_addreq: " |
| | | 477 | "error %d adding default router %s on %s\n", |
| | | 478 | error, ip6_sprintf(&new->rtaddr), new->ifp->if_xname); |
475 | splx(s); | | 479 | splx(s); |
476 | return; | | 480 | return; |
477 | } | | 481 | } |
478 | | | 482 | |
479 | struct nd_defrouter * | | 483 | struct nd_defrouter * |
480 | defrouter_lookup(const struct in6_addr *addr, struct ifnet *ifp) | | 484 | defrouter_lookup(const struct in6_addr *addr, struct ifnet *ifp) |
481 | { | | 485 | { |
482 | struct nd_defrouter *dr; | | 486 | struct nd_defrouter *dr; |
483 | | | 487 | |
484 | TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) { | | 488 | TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) { |
485 | if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) | | 489 | if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr)) |
486 | break; | | 490 | break; |
487 | } | | 491 | } |
| @@ -549,59 +553,65 @@ defrtrlist_del(struct nd_defrouter *dr, | | | @@ -549,59 +553,65 @@ defrtrlist_del(struct nd_defrouter *dr, |
549 | /* | | 553 | /* |
550 | * Remove the default route for a given router. | | 554 | * Remove the default route for a given router. |
551 | * This is just a subroutine function for defrouter_select(), and should | | 555 | * This is just a subroutine function for defrouter_select(), and should |
552 | * not be called from anywhere else. | | 556 | * not be called from anywhere else. |
553 | */ | | 557 | */ |
554 | static void | | 558 | static void |
555 | defrouter_delreq(struct nd_defrouter *dr) | | 559 | defrouter_delreq(struct nd_defrouter *dr) |
556 | { | | 560 | { |
557 | union { | | 561 | union { |
558 | struct sockaddr_in6 sin6; | | 562 | struct sockaddr_in6 sin6; |
559 | struct sockaddr sa; | | 563 | struct sockaddr sa; |
560 | } def, mask, gw; | | 564 | } def, mask, gw; |
561 | struct rtentry *oldrt = NULL; | | 565 | struct rtentry *oldrt = NULL; |
| | | 566 | int error; |
562 | | | 567 | |
563 | #ifdef DIAGNOSTIC | | 568 | #ifdef DIAGNOSTIC |
564 | if (dr == NULL) | | 569 | if (dr == NULL) |
565 | panic("dr == NULL in defrouter_delreq"); | | 570 | panic("dr == NULL in defrouter_delreq"); |
566 | #endif | | 571 | #endif |
567 | | | 572 | |
568 | memset(&def, 0, sizeof(def)); | | 573 | memset(&def, 0, sizeof(def)); |
569 | memset(&mask, 0, sizeof(mask)); | | 574 | memset(&mask, 0, sizeof(mask)); |
570 | memset(&gw, 0, sizeof(gw)); /* for safety */ | | 575 | memset(&gw, 0, sizeof(gw)); /* for safety */ |
571 | | | 576 | |
572 | def.sin6.sin6_len = mask.sin6.sin6_len = gw.sin6.sin6_len = | | 577 | def.sin6.sin6_len = mask.sin6.sin6_len = gw.sin6.sin6_len = |
573 | sizeof(struct sockaddr_in6); | | 578 | sizeof(struct sockaddr_in6); |
574 | def.sin6.sin6_family = mask.sin6.sin6_family = gw.sin6.sin6_family = AF_INET6; | | 579 | def.sin6.sin6_family = mask.sin6.sin6_family = gw.sin6.sin6_family = AF_INET6; |
575 | gw.sin6.sin6_addr = dr->rtaddr; | | 580 | gw.sin6.sin6_addr = dr->rtaddr; |
576 | #ifndef SCOPEDROUTING | | 581 | #ifndef SCOPEDROUTING |
577 | gw.sin6.sin6_scope_id = 0; /* XXX */ | | 582 | gw.sin6.sin6_scope_id = 0; /* XXX */ |
578 | #endif | | 583 | #endif |
579 | | | 584 | |
580 | rtrequest(RTM_DELETE, &def.sa, &gw.sa, &mask.sa, RTF_GATEWAY, &oldrt); | | 585 | error = rtrequest(RTM_DELETE, &def.sa, &gw.sa, &mask.sa, RTF_GATEWAY, &oldrt); |
581 | if (oldrt) { | | 586 | if (oldrt) { |
582 | nd6_rtmsg(RTM_DELETE, oldrt); | | 587 | nd6_rtmsg(RTM_DELETE, oldrt); |
583 | if (oldrt->rt_refcnt <= 0) { | | 588 | if (oldrt->rt_refcnt <= 0) { |
584 | /* | | 589 | /* |
585 | * XXX: borrowed from the RTM_DELETE case of | | 590 | * XXX: borrowed from the RTM_DELETE case of |
586 | * rtrequest(). | | 591 | * rtrequest(). |
587 | */ | | 592 | */ |
588 | oldrt->rt_refcnt++; | | 593 | oldrt->rt_refcnt++; |
589 | rtfree(oldrt); | | 594 | rtfree(oldrt); |
590 | nd6_numroutes--; | | 595 | nd6_numroutes--; |
591 | } | | 596 | } |
592 | } | | 597 | } |
593 | | | 598 | |
594 | dr->installed = 0; | | 599 | if (error == 0) |
| | | 600 | dr->installed = 0; |
| | | 601 | else |
| | | 602 | log(LOG_ERR, "defrouter_delreq: " |
| | | 603 | "error %d deleting default router %s on %s\n", |
| | | 604 | error, ip6_sprintf(&dr->rtaddr), dr->ifp->if_xname); |
595 | } | | 605 | } |
596 | | | 606 | |
597 | /* | | 607 | /* |
598 | * remove all default routes from default router list | | 608 | * remove all default routes from default router list |
599 | */ | | 609 | */ |
600 | void | | 610 | void |
601 | defrouter_reset(void) | | 611 | defrouter_reset(void) |
602 | { | | 612 | { |
603 | struct nd_defrouter *dr; | | 613 | struct nd_defrouter *dr; |
604 | | | 614 | |
605 | for (dr = TAILQ_FIRST(&nd_defrouter); dr; | | 615 | for (dr = TAILQ_FIRST(&nd_defrouter); dr; |
606 | dr = TAILQ_NEXT(dr, dr_entry)) | | 616 | dr = TAILQ_NEXT(dr, dr_entry)) |
607 | defrouter_delreq(dr); | | 617 | defrouter_delreq(dr); |
| @@ -662,44 +672,44 @@ defrouter_select(void) | | | @@ -662,44 +672,44 @@ defrouter_select(void) |
662 | */ | | 672 | */ |
663 | if (!TAILQ_FIRST(&nd_defrouter)) { | | 673 | if (!TAILQ_FIRST(&nd_defrouter)) { |
664 | splx(s); | | 674 | splx(s); |
665 | return; | | 675 | return; |
666 | } | | 676 | } |
667 | | | 677 | |
668 | /* | | 678 | /* |
669 | * Search for a (probably) reachable router from the list. | | 679 | * Search for a (probably) reachable router from the list. |
670 | * We just pick up the first reachable one (if any), assuming that | | 680 | * We just pick up the first reachable one (if any), assuming that |
671 | * the ordering rule of the list described in defrtrlist_update(). | | 681 | * the ordering rule of the list described in defrtrlist_update(). |
672 | */ | | 682 | */ |
673 | for (dr = TAILQ_FIRST(&nd_defrouter); dr; | | 683 | for (dr = TAILQ_FIRST(&nd_defrouter); dr; |
674 | dr = TAILQ_NEXT(dr, dr_entry)) { | | 684 | dr = TAILQ_NEXT(dr, dr_entry)) { |
| | | 685 | if (dr->installed && !installed_dr) |
| | | 686 | installed_dr = dr; |
| | | 687 | else if (dr->installed && installed_dr) { |
| | | 688 | /* this should not happen. warn for diagnosis. */ |
| | | 689 | log(LOG_ERR, "defrouter_select: more than one router" |
| | | 690 | " is installed\n"); |
| | | 691 | } |
| | | 692 | |
675 | ndi = ND_IFINFO(dr->ifp); | | 693 | ndi = ND_IFINFO(dr->ifp); |
676 | if (nd6_accepts_rtadv(ndi)) | | 694 | if (!nd6_accepts_rtadv(ndi)) |
677 | continue; | | 695 | continue; |
678 | | | 696 | |
679 | if (selected_dr == NULL && | | 697 | if (selected_dr == NULL && |
680 | (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) != NULL && | | 698 | (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) != NULL && |
681 | (ln = (struct llinfo_nd6 *)rt->rt_llinfo) != NULL && | | 699 | (ln = (struct llinfo_nd6 *)rt->rt_llinfo) != NULL && |
682 | ND6_IS_LLINFO_PROBREACH(ln)) { | | 700 | ND6_IS_LLINFO_PROBREACH(ln)) { |
683 | selected_dr = dr; | | 701 | selected_dr = dr; |
684 | } | | 702 | } |
685 | | | | |
686 | if (dr->installed && !installed_dr) | | | |
687 | installed_dr = dr; | | | |
688 | else if (dr->installed && installed_dr) { | | | |
689 | /* this should not happen. warn for diagnosis. */ | | | |
690 | log(LOG_ERR, "defrouter_select: more than one router" | | | |
691 | " is installed\n"); | | | |
692 | } | | | |
693 | } | | 703 | } |
694 | /* | | 704 | /* |
695 | * If none of the default routers was found to be reachable, | | 705 | * If none of the default routers was found to be reachable, |
696 | * round-robin the list regardless of preference. | | 706 | * round-robin the list regardless of preference. |
697 | * Otherwise, if we have an installed router, check if the selected | | 707 | * Otherwise, if we have an installed router, check if the selected |
698 | * (reachable) router should really be preferred to the installed one. | | 708 | * (reachable) router should really be preferred to the installed one. |
699 | * We only prefer the new router when the old one is not reachable | | 709 | * We only prefer the new router when the old one is not reachable |
700 | * or when the new one has a really higher preference value. | | 710 | * or when the new one has a really higher preference value. |
701 | */ | | 711 | */ |
702 | if (selected_dr == NULL) { | | 712 | if (selected_dr == NULL) { |
703 | if (installed_dr == NULL || !TAILQ_NEXT(installed_dr, dr_entry)) | | 713 | if (installed_dr == NULL || !TAILQ_NEXT(installed_dr, dr_entry)) |
704 | selected_dr = TAILQ_FIRST(&nd_defrouter); | | 714 | selected_dr = TAILQ_FIRST(&nd_defrouter); |
705 | else | | 715 | else |