Deleted Added
full compact
nd6_rtr.c (185751) nd6_rtr.c (186119)
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $
30 */
31
32#include <sys/cdefs.h>
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/netinet6/nd6_rtr.c 185751 2008-12-08 00:28:21Z imp $");
33__FBSDID("$FreeBSD: head/sys/netinet6/nd6_rtr.c 186119 2008-12-15 06:10:57Z qingli $");
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>

--- 11 unchanged lines hidden (view full) ---

53#include <net/if.h>
54#include <net/if_types.h>
55#include <net/if_dl.h>
56#include <net/route.h>
57#include <net/radix.h>
58#include <net/vnet.h>
59
60#include <netinet/in.h>
34
35#include "opt_inet.h"
36#include "opt_inet6.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>

--- 11 unchanged lines hidden (view full) ---

53#include <net/if.h>
54#include <net/if_types.h>
55#include <net/if_dl.h>
56#include <net/route.h>
57#include <net/radix.h>
58#include <net/vnet.h>
59
60#include <netinet/in.h>
61#include <net/if_llatbl.h>
61#include <netinet6/in6_var.h>
62#include <netinet6/in6_ifattach.h>
63#include <netinet/ip6.h>
64#include <netinet6/ip6_var.h>
65#include <netinet6/nd6.h>
66#include <netinet/icmp6.h>
67#include <netinet6/scope6_var.h>
68#include <netinet6/vinet6.h>

--- 397 unchanged lines hidden (view full) ---

466 def.sin6_family = gate.sin6_family = AF_INET6;
467 gate.sin6_addr = new->rtaddr;
468
469 s = splnet();
470 error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
471 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
472 RTF_GATEWAY, &newrt);
473 if (newrt) {
62#include <netinet6/in6_var.h>
63#include <netinet6/in6_ifattach.h>
64#include <netinet/ip6.h>
65#include <netinet6/ip6_var.h>
66#include <netinet6/nd6.h>
67#include <netinet/icmp6.h>
68#include <netinet6/scope6_var.h>
69#include <netinet6/vinet6.h>

--- 397 unchanged lines hidden (view full) ---

467 def.sin6_family = gate.sin6_family = AF_INET6;
468 gate.sin6_addr = new->rtaddr;
469
470 s = splnet();
471 error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
472 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
473 RTF_GATEWAY, &newrt);
474 if (newrt) {
474 RT_LOCK(newrt);
475 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
475 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
476 RT_REMREF(newrt);
477 RT_UNLOCK(newrt);
476 RTFREE(newrt);
478 }
479 if (error == 0)
480 new->installed = 1;
481 splx(s);
482 return;
483}
484
485struct nd_defrouter *

--- 124 unchanged lines hidden (view full) ---

610 * complicated and the possibility of introducing bugs.
611 */
612void
613defrouter_select(void)
614{
615 INIT_VNET_INET6(curvnet);
616 int s = splnet();
617 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
477 }
478 if (error == 0)
479 new->installed = 1;
480 splx(s);
481 return;
482}
483
484struct nd_defrouter *

--- 124 unchanged lines hidden (view full) ---

609 * complicated and the possibility of introducing bugs.
610 */
611void
612defrouter_select(void)
613{
614 INIT_VNET_INET6(curvnet);
615 int s = splnet();
616 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
618 struct rtentry *rt = NULL;
619 struct llinfo_nd6 *ln = NULL;
617 struct llentry *ln = NULL;
620
621 /*
622 * This function should be called only when acting as an autoconfigured
623 * host. Although the remaining part of this function is not effective
624 * if the node is not an autoconfigured host, we explicitly exclude
625 * such cases here for safety.
626 */
627 if (V_ip6_forwarding || !V_ip6_accept_rtadv) {

--- 15 unchanged lines hidden (view full) ---

643
644 /*
645 * Search for a (probably) reachable router from the list.
646 * We just pick up the first reachable one (if any), assuming that
647 * the ordering rule of the list described in defrtrlist_update().
648 */
649 for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
650 dr = TAILQ_NEXT(dr, dr_entry)) {
618
619 /*
620 * This function should be called only when acting as an autoconfigured
621 * host. Although the remaining part of this function is not effective
622 * if the node is not an autoconfigured host, we explicitly exclude
623 * such cases here for safety.
624 */
625 if (V_ip6_forwarding || !V_ip6_accept_rtadv) {

--- 15 unchanged lines hidden (view full) ---

641
642 /*
643 * Search for a (probably) reachable router from the list.
644 * We just pick up the first reachable one (if any), assuming that
645 * the ordering rule of the list described in defrtrlist_update().
646 */
647 for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
648 dr = TAILQ_NEXT(dr, dr_entry)) {
649 IF_AFDATA_LOCK(dr->ifp);
651 if (selected_dr == NULL &&
650 if (selected_dr == NULL &&
652 (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
653 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
651 (ln = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
654 ND6_IS_LLINFO_PROBREACH(ln)) {
655 selected_dr = dr;
656 }
652 ND6_IS_LLINFO_PROBREACH(ln)) {
653 selected_dr = dr;
654 }
655 IF_AFDATA_UNLOCK(dr->ifp);
657
658 if (dr->installed && installed_dr == NULL)
659 installed_dr = dr;
660 else if (dr->installed && installed_dr) {
661 /* this should not happen. warn for diagnosis. */
662 log(LOG_ERR, "defrouter_select: more than one router"
663 " is installed\n");
664 }

--- 6 unchanged lines hidden (view full) ---

671 * We only prefer the new router when the old one is not reachable
672 * or when the new one has a really higher preference value.
673 */
674 if (selected_dr == NULL) {
675 if (installed_dr == NULL || !TAILQ_NEXT(installed_dr, dr_entry))
676 selected_dr = TAILQ_FIRST(&V_nd_defrouter);
677 else
678 selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
656
657 if (dr->installed && installed_dr == NULL)
658 installed_dr = dr;
659 else if (dr->installed && installed_dr) {
660 /* this should not happen. warn for diagnosis. */
661 log(LOG_ERR, "defrouter_select: more than one router"
662 " is installed\n");
663 }

--- 6 unchanged lines hidden (view full) ---

670 * We only prefer the new router when the old one is not reachable
671 * or when the new one has a really higher preference value.
672 */
673 if (selected_dr == NULL) {
674 if (installed_dr == NULL || !TAILQ_NEXT(installed_dr, dr_entry))
675 selected_dr = TAILQ_FIRST(&V_nd_defrouter);
676 else
677 selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
679 } else if (installed_dr &&
680 (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
681 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
682 ND6_IS_LLINFO_PROBREACH(ln) &&
683 rtpref(selected_dr) <= rtpref(installed_dr)) {
684 selected_dr = installed_dr;
678 } else if (installed_dr) {
679 IF_AFDATA_LOCK(installed_dr->ifp);
680 if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
681 ND6_IS_LLINFO_PROBREACH(ln) &&
682 rtpref(selected_dr) <= rtpref(installed_dr)) {
683 selected_dr = installed_dr;
684 }
685 IF_AFDATA_UNLOCK(installed_dr->ifp);
685 }
686
687 /*
688 * If the selected router is different than the installed one,
689 * remove the installed router and install the selected one.
690 * Note that the selected router is never NULL here.
691 */
692 if (installed_dr != selected_dr) {

--- 625 unchanged lines hidden (view full) ---

1318 * A supplement function used in the on-link detection below;
1319 * detect if a given prefix has a (probably) reachable advertising router.
1320 * XXX: lengthy function name...
1321 */
1322static struct nd_pfxrouter *
1323find_pfxlist_reachable_router(struct nd_prefix *pr)
1324{
1325 struct nd_pfxrouter *pfxrtr;
686 }
687
688 /*
689 * If the selected router is different than the installed one,
690 * remove the installed router and install the selected one.
691 * Note that the selected router is never NULL here.
692 */
693 if (installed_dr != selected_dr) {

--- 625 unchanged lines hidden (view full) ---

1319 * A supplement function used in the on-link detection below;
1320 * detect if a given prefix has a (probably) reachable advertising router.
1321 * XXX: lengthy function name...
1322 */
1323static struct nd_pfxrouter *
1324find_pfxlist_reachable_router(struct nd_prefix *pr)
1325{
1326 struct nd_pfxrouter *pfxrtr;
1326 struct rtentry *rt;
1327 struct llinfo_nd6 *ln;
1327 struct llentry *ln;
1328
1329 for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1330 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1328
1329 for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1330 pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1331 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1331 IF_AFDATA_LOCK(pfxrtr->router->ifp);
1332 if ((ln = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1332 pfxrtr->router->ifp)) &&
1333 pfxrtr->router->ifp)) &&
1333 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1334 ND6_IS_LLINFO_PROBREACH(ln))
1334 ND6_IS_LLINFO_PROBREACH(ln)) {
1335 IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
1335 break; /* found */
1336 break; /* found */
1337 }
1338 IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
1336 }
1339 }
1337
1338 return (pfxrtr);
1339}
1340
1341/*
1342 * Check if each prefix in the prefix list has at least one available router
1343 * that advertised the prefix (a router is "available" if its neighbor cache
1344 * entry is reachable or probably reachable).
1345 * If the check fails, the prefix may be off-link, because, for example,

--- 190 unchanged lines hidden (view full) ---

1536{
1537 INIT_VNET_INET6(curvnet);
1538 struct ifaddr *ifa;
1539 struct ifnet *ifp = pr->ndpr_ifp;
1540 struct sockaddr_in6 mask6;
1541 struct nd_prefix *opr;
1542 u_long rtflags;
1543 int error = 0;
1340 return (pfxrtr);
1341}
1342
1343/*
1344 * Check if each prefix in the prefix list has at least one available router
1345 * that advertised the prefix (a router is "available" if its neighbor cache
1346 * entry is reachable or probably reachable).
1347 * If the check fails, the prefix may be off-link, because, for example,

--- 190 unchanged lines hidden (view full) ---

1538{
1539 INIT_VNET_INET6(curvnet);
1540 struct ifaddr *ifa;
1541 struct ifnet *ifp = pr->ndpr_ifp;
1542 struct sockaddr_in6 mask6;
1543 struct nd_prefix *opr;
1544 u_long rtflags;
1545 int error = 0;
1546 struct radix_node_head *rnh;
1544 struct rtentry *rt = NULL;
1545 char ip6buf[INET6_ADDRSTRLEN];
1547 struct rtentry *rt = NULL;
1548 char ip6buf[INET6_ADDRSTRLEN];
1549 struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
1546
1547 /* sanity check */
1548 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1549 nd6log((LOG_ERR,
1550 "nd6_prefix_onlink: %s/%d is already on-link\n",
1551 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1552 pr->ndpr_plen));
1553 return (EEXIST);

--- 50 unchanged lines hidden (view full) ---

1604
1605 /*
1606 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1607 * ifa->ifa_rtrequest = nd6_rtrequest;
1608 */
1609 bzero(&mask6, sizeof(mask6));
1610 mask6.sin6_len = sizeof(mask6);
1611 mask6.sin6_addr = pr->ndpr_mask;
1550
1551 /* sanity check */
1552 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1553 nd6log((LOG_ERR,
1554 "nd6_prefix_onlink: %s/%d is already on-link\n",
1555 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1556 pr->ndpr_plen));
1557 return (EEXIST);

--- 50 unchanged lines hidden (view full) ---

1608
1609 /*
1610 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1611 * ifa->ifa_rtrequest = nd6_rtrequest;
1612 */
1613 bzero(&mask6, sizeof(mask6));
1614 mask6.sin6_len = sizeof(mask6);
1615 mask6.sin6_addr = pr->ndpr_mask;
1612 rtflags = ifa->ifa_flags | RTF_CLONING | RTF_UP;
1613 if (nd6_need_cache(ifp)) {
1614 /* explicitly set in case ifa_flags does not set the flag. */
1615 rtflags |= RTF_CLONING;
1616 } else {
1617 /*
1618 * explicitly clear the cloning bit in case ifa_flags sets it.
1619 */
1620 rtflags &= ~RTF_CLONING;
1621 }
1616 rtflags = ifa->ifa_flags | RTF_UP;
1622 error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1623 ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
1624 if (error == 0) {
1617 error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1618 ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
1619 if (error == 0) {
1625 if (rt != NULL) /* this should be non NULL, though */
1620 if (rt != NULL) /* this should be non NULL, though */ {
1621 rnh = V_rt_tables[rt->rt_fibnum][AF_INET6];
1622 RADIX_NODE_HEAD_LOCK(rnh);
1623 RT_LOCK(rt);
1624 if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
1625 ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
1626 rt->rt_ifp->if_type;
1627 ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
1628 rt->rt_ifp->if_index;
1629 }
1630 RADIX_NODE_HEAD_UNLOCK(rnh);
1626 nd6_rtmsg(RTM_ADD, rt);
1631 nd6_rtmsg(RTM_ADD, rt);
1632 RT_UNLOCK(rt);
1633 }
1627 pr->ndpr_stateflags |= NDPRF_ONLINK;
1628 } else {
1629 char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
1630 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
1631 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1632 "errno = %d\n",
1633 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1634 pr->ndpr_plen, if_name(ifp),

--- 484 unchanged lines hidden ---
1634 pr->ndpr_stateflags |= NDPRF_ONLINK;
1635 } else {
1636 char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
1637 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
1638 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1639 "errno = %d\n",
1640 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1641 pr->ndpr_plen, if_name(ifp),

--- 484 unchanged lines hidden ---