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 --- |