nd6_rtr.c (231852) | nd6_rtr.c (241686) |
---|---|
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 231852 2012-02-17 02:39:58Z bz $"); | 33__FBSDID("$FreeBSD: head/sys/netinet6/nd6_rtr.c 241686 2012-10-18 13:57:24Z andre $"); |
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> --- 426 unchanged lines hidden (view full) --- 468 ifa_free(ifa); 469} 470 471static void 472defrouter_addreq(struct nd_defrouter *new) 473{ 474 struct sockaddr_in6 def, mask, gate; 475 struct rtentry *newrt = NULL; | 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> --- 426 unchanged lines hidden (view full) --- 468 ifa_free(ifa); 469} 470 471static void 472defrouter_addreq(struct nd_defrouter *new) 473{ 474 struct sockaddr_in6 def, mask, gate; 475 struct rtentry *newrt = NULL; |
476 int s; | |
477 int error; 478 479 bzero(&def, sizeof(def)); 480 bzero(&mask, sizeof(mask)); 481 bzero(&gate, sizeof(gate)); 482 483 def.sin6_len = mask.sin6_len = gate.sin6_len = 484 sizeof(struct sockaddr_in6); 485 def.sin6_family = gate.sin6_family = AF_INET6; 486 gate.sin6_addr = new->rtaddr; 487 | 476 int error; 477 478 bzero(&def, sizeof(def)); 479 bzero(&mask, sizeof(mask)); 480 bzero(&gate, sizeof(gate)); 481 482 def.sin6_len = mask.sin6_len = gate.sin6_len = 483 sizeof(struct sockaddr_in6); 484 def.sin6_family = gate.sin6_family = AF_INET6; 485 gate.sin6_addr = new->rtaddr; 486 |
488 s = splnet(); | |
489 error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def, 490 (struct sockaddr *)&gate, (struct sockaddr *)&mask, 491 RTF_GATEWAY, &newrt, RT_DEFAULT_FIB); 492 if (newrt) { 493 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */ 494 RTFREE(newrt); 495 } 496 if (error == 0) 497 new->installed = 1; | 487 error = in6_rtrequest(RTM_ADD, (struct sockaddr *)&def, 488 (struct sockaddr *)&gate, (struct sockaddr *)&mask, 489 RTF_GATEWAY, &newrt, RT_DEFAULT_FIB); 490 if (newrt) { 491 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */ 492 RTFREE(newrt); 493 } 494 if (error == 0) 495 new->installed = 1; |
498 splx(s); | |
499 return; 500} 501 502struct nd_defrouter * 503defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp) 504{ 505 struct nd_defrouter *dr; 506 --- 112 unchanged lines hidden (view full) --- 619 * At this moment, we do not try to install more than one default router, 620 * even when the multipath routing is available, because we're not sure about 621 * the benefits for stub hosts comparing to the risk of making the code 622 * complicated and the possibility of introducing bugs. 623 */ 624void 625defrouter_select(void) 626{ | 496 return; 497} 498 499struct nd_defrouter * 500defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp) 501{ 502 struct nd_defrouter *dr; 503 --- 112 unchanged lines hidden (view full) --- 616 * At this moment, we do not try to install more than one default router, 617 * even when the multipath routing is available, because we're not sure about 618 * the benefits for stub hosts comparing to the risk of making the code 619 * complicated and the possibility of introducing bugs. 620 */ 621void 622defrouter_select(void) 623{ |
627 int s = splnet(); | |
628 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL; 629 struct llentry *ln = NULL; 630 631 /* 632 * Let's handle easy case (3) first: 633 * If default router list is empty, there's nothing to be done. 634 */ | 624 struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL; 625 struct llentry *ln = NULL; 626 627 /* 628 * Let's handle easy case (3) first: 629 * If default router list is empty, there's nothing to be done. 630 */ |
635 if (TAILQ_EMPTY(&V_nd_defrouter)) { 636 splx(s); | 631 if (TAILQ_EMPTY(&V_nd_defrouter)) |
637 return; | 632 return; |
638 } | |
639 640 /* 641 * Search for a (probably) reachable router from the list. 642 * We just pick up the first reachable one (if any), assuming that 643 * the ordering rule of the list described in defrtrlist_update(). 644 */ 645 TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { 646 IF_AFDATA_LOCK(dr->ifp); --- 47 unchanged lines hidden (view full) --- 694 * Note that the selected router is never NULL here. 695 */ 696 if (installed_dr != selected_dr) { 697 if (installed_dr) 698 defrouter_delreq(installed_dr); 699 defrouter_addreq(selected_dr); 700 } 701 | 633 634 /* 635 * Search for a (probably) reachable router from the list. 636 * We just pick up the first reachable one (if any), assuming that 637 * the ordering rule of the list described in defrtrlist_update(). 638 */ 639 TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry) { 640 IF_AFDATA_LOCK(dr->ifp); --- 47 unchanged lines hidden (view full) --- 688 * Note that the selected router is never NULL here. 689 */ 690 if (installed_dr != selected_dr) { 691 if (installed_dr) 692 defrouter_delreq(installed_dr); 693 defrouter_addreq(selected_dr); 694 } 695 |
702 splx(s); | |
703 return; 704} 705 706/* 707 * for default router selection 708 * regards router-preference field as a 2-bit signed integer 709 */ 710static int --- 18 unchanged lines hidden (view full) --- 729 } 730 /* NOTREACHED */ 731} 732 733static struct nd_defrouter * 734defrtrlist_update(struct nd_defrouter *new) 735{ 736 struct nd_defrouter *dr, *n; | 696 return; 697} 698 699/* 700 * for default router selection 701 * regards router-preference field as a 2-bit signed integer 702 */ 703static int --- 18 unchanged lines hidden (view full) --- 722 } 723 /* NOTREACHED */ 724} 725 726static struct nd_defrouter * 727defrtrlist_update(struct nd_defrouter *new) 728{ 729 struct nd_defrouter *dr, *n; |
737 int s = splnet(); | |
738 739 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) { 740 /* entry exists */ 741 if (new->rtlifetime == 0) { 742 defrtrlist_del(dr); 743 dr = NULL; 744 } else { 745 int oldpref = rtpref(dr); 746 747 /* override */ 748 dr->flags = new->flags; /* xxx flag check */ 749 dr->rtlifetime = new->rtlifetime; 750 dr->expire = new->expire; 751 752 /* 753 * If the preference does not change, there's no need 754 * to sort the entries. Also make sure the selected 755 * router is still installed in the kernel. 756 */ | 730 731 if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) { 732 /* entry exists */ 733 if (new->rtlifetime == 0) { 734 defrtrlist_del(dr); 735 dr = NULL; 736 } else { 737 int oldpref = rtpref(dr); 738 739 /* override */ 740 dr->flags = new->flags; /* xxx flag check */ 741 dr->rtlifetime = new->rtlifetime; 742 dr->expire = new->expire; 743 744 /* 745 * If the preference does not change, there's no need 746 * to sort the entries. Also make sure the selected 747 * router is still installed in the kernel. 748 */ |
757 if (dr->installed && rtpref(new) == oldpref) { 758 splx(s); | 749 if (dr->installed && rtpref(new) == oldpref) |
759 return (dr); | 750 return (dr); |
760 } | |
761 762 /* 763 * preferred router may be changed, so relocate 764 * this router. 765 * XXX: calling TAILQ_REMOVE directly is a bad manner. 766 * However, since defrtrlist_del() has many side 767 * effects, we intentionally do so here. 768 * defrouter_select() below will handle routing 769 * changes later. 770 */ 771 TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); 772 n = dr; 773 goto insert; 774 } | 751 752 /* 753 * preferred router may be changed, so relocate 754 * this router. 755 * XXX: calling TAILQ_REMOVE directly is a bad manner. 756 * However, since defrtrlist_del() has many side 757 * effects, we intentionally do so here. 758 * defrouter_select() below will handle routing 759 * changes later. 760 */ 761 TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry); 762 n = dr; 763 goto insert; 764 } |
775 splx(s); | |
776 return (dr); 777 } 778 779 /* entry does not exist */ | 765 return (dr); 766 } 767 768 /* entry does not exist */ |
780 if (new->rtlifetime == 0) { 781 splx(s); | 769 if (new->rtlifetime == 0) |
782 return (NULL); | 770 return (NULL); |
783 } | |
784 785 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT); | 771 772 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT); |
786 if (n == NULL) { 787 splx(s); | 773 if (n == NULL) |
788 return (NULL); | 774 return (NULL); |
789 } | |
790 bzero(n, sizeof(*n)); 791 *n = *new; 792 793insert: 794 /* 795 * Insert the new router in the Default Router List; 796 * The Default Router List should be in the descending order 797 * of router-preferece. Routers with the same preference are --- 7 unchanged lines hidden (view full) --- 805 } 806 if (dr) 807 TAILQ_INSERT_BEFORE(dr, n, dr_entry); 808 else 809 TAILQ_INSERT_TAIL(&V_nd_defrouter, n, dr_entry); 810 811 defrouter_select(); 812 | 775 bzero(n, sizeof(*n)); 776 *n = *new; 777 778insert: 779 /* 780 * Insert the new router in the Default Router List; 781 * The Default Router List should be in the descending order 782 * of router-preferece. Routers with the same preference are --- 7 unchanged lines hidden (view full) --- 790 } 791 if (dr) 792 TAILQ_INSERT_BEFORE(dr, n, dr_entry); 793 else 794 TAILQ_INSERT_TAIL(&V_nd_defrouter, n, dr_entry); 795 796 defrouter_select(); 797 |
813 splx(s); 814 | |
815 return (n); 816} 817 818static struct nd_pfxrouter * 819pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr) 820{ 821 struct nd_pfxrouter *search; 822 --- 46 unchanged lines hidden (view full) --- 869} 870 871int 872nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, 873 struct nd_prefix **newp) 874{ 875 struct nd_prefix *new = NULL; 876 int error = 0; | 798 return (n); 799} 800 801static struct nd_pfxrouter * 802pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr) 803{ 804 struct nd_pfxrouter *search; 805 --- 46 unchanged lines hidden (view full) --- 852} 853 854int 855nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, 856 struct nd_prefix **newp) 857{ 858 struct nd_prefix *new = NULL; 859 int error = 0; |
877 int i, s; | 860 int i; |
878 char ip6buf[INET6_ADDRSTRLEN]; 879 880 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT); 881 if (new == NULL) 882 return(ENOMEM); 883 bzero(new, sizeof(*new)); 884 new->ndpr_ifp = pr->ndpr_ifp; 885 new->ndpr_prefix = pr->ndpr_prefix; --- 12 unchanged lines hidden (view full) --- 898 /* initialization */ 899 LIST_INIT(&new->ndpr_advrtrs); 900 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen); 901 /* make prefix in the canonical form */ 902 for (i = 0; i < 4; i++) 903 new->ndpr_prefix.sin6_addr.s6_addr32[i] &= 904 new->ndpr_mask.s6_addr32[i]; 905 | 861 char ip6buf[INET6_ADDRSTRLEN]; 862 863 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT); 864 if (new == NULL) 865 return(ENOMEM); 866 bzero(new, sizeof(*new)); 867 new->ndpr_ifp = pr->ndpr_ifp; 868 new->ndpr_prefix = pr->ndpr_prefix; --- 12 unchanged lines hidden (view full) --- 881 /* initialization */ 882 LIST_INIT(&new->ndpr_advrtrs); 883 in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen); 884 /* make prefix in the canonical form */ 885 for (i = 0; i < 4; i++) 886 new->ndpr_prefix.sin6_addr.s6_addr32[i] &= 887 new->ndpr_mask.s6_addr32[i]; 888 |
906 s = splnet(); | |
907 /* link ndpr_entry to nd_prefix list */ 908 LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry); | 889 /* link ndpr_entry to nd_prefix list */ 890 LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry); |
909 splx(s); | |
910 911 /* ND_OPT_PI_FLAG_ONLINK processing */ 912 if (new->ndpr_raf_onlink) { 913 int e; 914 915 if ((e = nd6_prefix_onlink(new)) != 0) { 916 nd6log((LOG_ERR, "nd6_prelist_add: failed to make " 917 "the prefix %s/%d on-link on %s (errno=%d)\n", --- 8 unchanged lines hidden (view full) --- 926 927 return 0; 928} 929 930void 931prelist_remove(struct nd_prefix *pr) 932{ 933 struct nd_pfxrouter *pfr, *next; | 891 892 /* ND_OPT_PI_FLAG_ONLINK processing */ 893 if (new->ndpr_raf_onlink) { 894 int e; 895 896 if ((e = nd6_prefix_onlink(new)) != 0) { 897 nd6log((LOG_ERR, "nd6_prelist_add: failed to make " 898 "the prefix %s/%d on-link on %s (errno=%d)\n", --- 8 unchanged lines hidden (view full) --- 907 908 return 0; 909} 910 911void 912prelist_remove(struct nd_prefix *pr) 913{ 914 struct nd_pfxrouter *pfr, *next; |
934 int e, s; | 915 int e; |
935 char ip6buf[INET6_ADDRSTRLEN]; 936 937 /* make sure to invalidate the prefix until it is really freed. */ 938 pr->ndpr_vltime = 0; 939 pr->ndpr_pltime = 0; 940 941 /* 942 * Though these flags are now meaningless, we'd rather keep the value --- 8 unchanged lines hidden (view full) --- 951 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), 952 pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); 953 /* what should we do? */ 954 } 955 956 if (pr->ndpr_refcnt > 0) 957 return; /* notice here? */ 958 | 916 char ip6buf[INET6_ADDRSTRLEN]; 917 918 /* make sure to invalidate the prefix until it is really freed. */ 919 pr->ndpr_vltime = 0; 920 pr->ndpr_pltime = 0; 921 922 /* 923 * Though these flags are now meaningless, we'd rather keep the value --- 8 unchanged lines hidden (view full) --- 932 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr), 933 pr->ndpr_plen, if_name(pr->ndpr_ifp), e)); 934 /* what should we do? */ 935 } 936 937 if (pr->ndpr_refcnt > 0) 938 return; /* notice here? */ 939 |
959 s = splnet(); 960 | |
961 /* unlink ndpr_entry from nd_prefix list */ 962 LIST_REMOVE(pr, ndpr_entry); 963 964 /* free list of routers that adversed the prefix */ 965 LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) { 966 free(pfr, M_IP6NDP); 967 } | 940 /* unlink ndpr_entry from nd_prefix list */ 941 LIST_REMOVE(pr, ndpr_entry); 942 943 /* free list of routers that adversed the prefix */ 944 LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next) { 945 free(pfr, M_IP6NDP); 946 } |
968 splx(s); 969 | |
970 free(pr, M_IP6NDP); 971 972 pfxlist_onlink_check(); 973} 974 975/* 976 * dr - may be NULL 977 */ 978 979static int 980prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, 981 struct mbuf *m, int mcast) 982{ 983 struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL; 984 struct ifaddr *ifa; 985 struct ifnet *ifp = new->ndpr_ifp; 986 struct nd_prefix *pr; | 947 free(pr, M_IP6NDP); 948 949 pfxlist_onlink_check(); 950} 951 952/* 953 * dr - may be NULL 954 */ 955 956static int 957prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, 958 struct mbuf *m, int mcast) 959{ 960 struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL; 961 struct ifaddr *ifa; 962 struct ifnet *ifp = new->ndpr_ifp; 963 struct nd_prefix *pr; |
987 int s = splnet(); | |
988 int error = 0; 989 int newprefix = 0; 990 int auth; 991 struct in6_addrlifetime lt6_tmp; 992 char ip6buf[INET6_ADDRSTRLEN]; 993 994 auth = 0; 995 if (m) { --- 308 unchanged lines hidden (view full) --- 1304 pfxlist_onlink_check(); 1305 } else { 1306 /* just set an error. do not bark here. */ 1307 error = EADDRNOTAVAIL; /* XXX: might be unused. */ 1308 } 1309 } 1310 1311 end: | 964 int error = 0; 965 int newprefix = 0; 966 int auth; 967 struct in6_addrlifetime lt6_tmp; 968 char ip6buf[INET6_ADDRSTRLEN]; 969 970 auth = 0; 971 if (m) { --- 308 unchanged lines hidden (view full) --- 1280 pfxlist_onlink_check(); 1281 } else { 1282 /* just set an error. do not bark here. */ 1283 error = EADDRNOTAVAIL; /* XXX: might be unused. */ 1284 } 1285 } 1286 1287 end: |
1312 splx(s); | |
1313 return error; 1314} 1315 1316/* 1317 * A supplement function used in the on-link detection below; 1318 * detect if a given prefix has a (probably) reachable advertising router. 1319 * XXX: lengthy function name... 1320 */ --- 786 unchanged lines hidden (view full) --- 2107 * XXX: this function causes search through all entries of routing table, so 2108 * it shouldn't be called when acting as a router. 2109 */ 2110void 2111rt6_flush(struct in6_addr *gateway, struct ifnet *ifp) 2112{ 2113 struct radix_node_head *rnh; 2114 u_int fibnum; | 1288 return error; 1289} 1290 1291/* 1292 * A supplement function used in the on-link detection below; 1293 * detect if a given prefix has a (probably) reachable advertising router. 1294 * XXX: lengthy function name... 1295 */ --- 786 unchanged lines hidden (view full) --- 2082 * XXX: this function causes search through all entries of routing table, so 2083 * it shouldn't be called when acting as a router. 2084 */ 2085void 2086rt6_flush(struct in6_addr *gateway, struct ifnet *ifp) 2087{ 2088 struct radix_node_head *rnh; 2089 u_int fibnum; |
2115 int s = splnet(); | |
2116 2117 /* We'll care only link-local addresses */ | 2090 2091 /* We'll care only link-local addresses */ |
2118 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) { 2119 splx(s); | 2092 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) |
2120 return; | 2093 return; |
2121 } | |
2122 2123 /* XXX Do we really need to walk any but the default FIB? */ 2124 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 2125 rnh = rt_tables_get_rnh(fibnum, AF_INET6); 2126 if (rnh == NULL) 2127 continue; 2128 2129 RADIX_NODE_HEAD_LOCK(rnh); 2130 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway); 2131 RADIX_NODE_HEAD_UNLOCK(rnh); 2132 } | 2094 2095 /* XXX Do we really need to walk any but the default FIB? */ 2096 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 2097 rnh = rt_tables_get_rnh(fibnum, AF_INET6); 2098 if (rnh == NULL) 2099 continue; 2100 2101 RADIX_NODE_HEAD_LOCK(rnh); 2102 rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway); 2103 RADIX_NODE_HEAD_UNLOCK(rnh); 2104 } |
2133 splx(s); | |
2134} 2135 2136static int 2137rt6_deleteroute(struct radix_node *rn, void *arg) 2138{ 2139#define SIN6(s) ((struct sockaddr_in6 *)s) 2140 struct rtentry *rt = (struct rtentry *)rn; 2141 struct in6_addr *gate = (struct in6_addr *)arg; --- 55 unchanged lines hidden --- | 2105} 2106 2107static int 2108rt6_deleteroute(struct radix_node *rn, void *arg) 2109{ 2110#define SIN6(s) ((struct sockaddr_in6 *)s) 2111 struct rtentry *rt = (struct rtentry *)rn; 2112 struct in6_addr *gate = (struct in6_addr *)arg; --- 55 unchanged lines hidden --- |