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 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; |
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 |
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; |
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{ |
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 */ |
631 if (TAILQ_EMPTY(&V_nd_defrouter)) |
632 return; |
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 |
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; |
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 */ |
749 if (dr->installed && rtpref(new) == oldpref) |
750 return (dr); |
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 } |
765 return (dr); 766 } 767 768 /* entry does not exist */ |
769 if (new->rtlifetime == 0) |
770 return (NULL); |
771 772 n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT); |
773 if (n == NULL) |
774 return (NULL); |
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 |
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; |
860 int i; |
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 |
889 /* link ndpr_entry to nd_prefix list */ 890 LIST_INSERT_HEAD(&V_nd_prefix, new, ndpr_entry); |
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; |
915 int e; |
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 |
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 } |
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; |
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: |
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; |
2090 2091 /* We'll care only link-local addresses */ |
2092 if (!IN6_IS_ADDR_LINKLOCAL(gateway)) |
2093 return; |
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 } |
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 --- |