1/* 2 * Copyright (c) 1980, 1986, 1991, 1993 3 * The Regents of the University of California. 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 --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)route.c 8.3 (Berkeley) 1/9/95 |
34 * $FreeBSD: head/sys/net/route.c 85074 2001-10-17 18:07:05Z ru $ |
35 */ 36 37#include "opt_inet.h" 38#include "opt_mrouting.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/malloc.h> --- 117 unchanged lines hidden (view full) --- 160 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 161 /* 162 * If the new route specifies it be 163 * externally resolved, then go do that. 164 */ 165 msgtype = RTM_RESOLVE; 166 goto miss; 167 } |
168 /* Inform listeners of the new route. */ 169 bzero(&info, sizeof(info)); 170 info.rti_info[RTAX_DST] = rt_key(rt); 171 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 172 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 173 if (rt->rt_ifp != NULL) { 174 info.rti_info[RTAX_IFP] = 175 TAILQ_FIRST(&rt->rt_ifp->if_addrhead)->ifa_addr; 176 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 177 } 178 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0); |
179 } else 180 rt->rt_refcnt++; 181 } else { 182 /* 183 * Either we hit the root or couldn't find any match, 184 * Which basically means 185 * "caint get there frm here" 186 */ --- 107 unchanged lines hidden (view full) --- 294 * 295 */ 296void 297rtredirect(dst, gateway, netmask, flags, src, rtp) 298 struct sockaddr *dst, *gateway, *netmask, *src; 299 int flags; 300 struct rtentry **rtp; 301{ |
302 struct rtentry *rt; |
303 int error = 0; 304 short *stat = 0; 305 struct rt_addrinfo info; 306 struct ifaddr *ifa; 307 308 /* verify the gateway is directly reachable */ 309 if ((ifa = ifa_ifwithnet(gateway)) == 0) { 310 error = ENETUNREACH; --- 28 unchanged lines hidden (view full) --- 339 */ 340 if (rt->rt_flags & RTF_GATEWAY) { 341 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 342 /* 343 * Changing from route to net => route to host. 344 * Create new route, rather than smashing route to net. 345 */ 346 create: |
347 if (rt) 348 rtfree(rt); |
349 flags |= RTF_GATEWAY | RTF_DYNAMIC; |
350 bzero((caddr_t)&info, sizeof(info)); 351 info.rti_info[RTAX_DST] = dst; 352 info.rti_info[RTAX_GATEWAY] = gateway; 353 info.rti_info[RTAX_NETMASK] = netmask; 354 info.rti_ifa = ifa; 355 info.rti_flags = flags; 356 rt = NULL; 357 error = rtrequest1(RTM_ADD, &info, &rt); 358 if (rt != NULL) 359 flags = rt->rt_flags; |
360 stat = &rtstat.rts_dynamic; 361 } else { 362 /* 363 * Smash the current notion of the gateway to 364 * this destination. Should check about netmask!!! 365 */ 366 rt->rt_flags |= RTF_MODIFIED; 367 flags |= RTF_MODIFIED; --- 83 unchanged lines hidden (view full) --- 451 struct ifaddr *oifa = ifa; 452 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 453 if (ifa == 0) 454 ifa = oifa; 455 } 456 return (ifa); 457} 458 |
459static int rt_fixdelete __P((struct radix_node *, void *)); 460static int rt_fixchange __P((struct radix_node *, void *)); 461 462struct rtfc_arg { 463 struct rtentry *rt0; 464 struct radix_node_head *rnh; 465}; 466 467/* 468 * Do appropriate manipulations of a routing tree given 469 * all the bits of info needed 470 */ 471int 472rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 473 int req, flags; 474 struct sockaddr *dst, *gateway, *netmask; 475 struct rtentry **ret_nrt; 476{ |
477 struct rt_addrinfo info; 478 479 bzero((caddr_t)&info, sizeof(info)); 480 info.rti_flags = flags; 481 info.rti_info[RTAX_DST] = dst; 482 info.rti_info[RTAX_GATEWAY] = gateway; 483 info.rti_info[RTAX_NETMASK] = netmask; 484 return rtrequest1(req, &info, ret_nrt); 485} 486 487/* 488 * These (questionable) definitions of apparent local variables apply 489 * to the next two functions. XXXXXX!!! 490 */ 491#define dst info->rti_info[RTAX_DST] 492#define gateway info->rti_info[RTAX_GATEWAY] 493#define netmask info->rti_info[RTAX_NETMASK] 494#define ifaaddr info->rti_info[RTAX_IFA] 495#define ifpaddr info->rti_info[RTAX_IFP] 496#define flags info->rti_flags 497 498int 499rt_getifa(info) 500 struct rt_addrinfo *info; 501{ 502 struct ifaddr *ifa; 503 int error = 0; 504 505 /* 506 * ifp may be specified by sockaddr_dl 507 * when protocol address is ambiguous. 508 */ 509 if (info->rti_ifp == NULL && ifpaddr != NULL && 510 ifpaddr->sa_family == AF_LINK && 511 (ifa = ifa_ifwithnet(ifpaddr)) != NULL) 512 info->rti_ifp = ifa->ifa_ifp; 513 if (info->rti_ifa == NULL && ifaaddr != NULL) 514 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 515 if (info->rti_ifa == NULL) { 516 struct sockaddr *sa; 517 518 sa = ifaaddr != NULL ? ifaaddr : 519 (gateway != NULL ? gateway : dst); 520 if (sa != NULL && info->rti_ifp != NULL) 521 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 522 else if (dst != NULL && gateway != NULL) 523 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 524 else if (sa != NULL) 525 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 526 } 527 if ((ifa = info->rti_ifa) != NULL) { 528 if (info->rti_ifp == NULL) 529 info->rti_ifp = ifa->ifa_ifp; 530 } else 531 error = ENETUNREACH; 532 return (error); 533} 534 535int 536rtrequest1(req, info, ret_nrt) 537 int req; 538 struct rt_addrinfo *info; 539 struct rtentry **ret_nrt; 540{ |
541 int s = splnet(); int error = 0; 542 register struct rtentry *rt; 543 register struct radix_node *rn; 544 register struct radix_node_head *rnh; 545 struct ifaddr *ifa; 546 struct sockaddr *ndst; 547#define senderr(x) { error = x ; goto bad; } 548 549 /* 550 * Find the correct routing tree to use for this Address Family 551 */ 552 if ((rnh = rt_tables[dst->sa_family]) == 0) |
553 senderr(EAFNOSUPPORT); |
554 /* 555 * If we are adding a host route then we don't want to put 556 * a netmask in the tree, nor do we want to clone it. 557 */ 558 if (flags & RTF_HOST) { 559 netmask = 0; 560 flags &= ~(RTF_CLONING | RTF_PRCLONING); 561 } --- 38 unchanged lines hidden (view full) --- 600 * I'm not sure how RTF_UP helps matters. (JRE) 601 */ 602 rt->rt_flags &= ~RTF_UP; 603 604 /* 605 * give the protocol a chance to keep things in sync. 606 */ 607 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) |
608 ifa->ifa_rtrequest(RTM_DELETE, rt, info); |
609 610 /* 611 * one more rtentry floating around that is not 612 * linked to the routing table. 613 */ 614 rttrash++; 615 616 /* --- 20 unchanged lines hidden (view full) --- 637 if ((netmask = rt->rt_genmask) == 0) 638 flags |= RTF_HOST; 639 goto makeroute; 640 641 case RTM_ADD: 642 if ((flags & RTF_GATEWAY) && !gateway) 643 panic("rtrequest: GATEWAY but no gateway"); 644 |
645 if (info->rti_ifa == NULL && (error = rt_getifa(info))) 646 senderr(error); 647 ifa = info->rti_ifa; |
648 649 makeroute: 650 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 651 if (rt == 0) 652 senderr(ENOBUFS); 653 Bzero(rt, sizeof(*rt)); 654 rt->rt_flags = RTF_UP | flags; 655 /* --- 85 unchanged lines hidden (view full) --- 741 } 742 } 743 744 /* 745 * if this protocol has something to add to this then 746 * allow it to do that as well. 747 */ 748 if (ifa->ifa_rtrequest) |
749 ifa->ifa_rtrequest(req, rt, info); |
750 751 /* 752 * We repeat the same procedure from rt_setgate() here because 753 * it doesn't fire when we call it there because the node 754 * hasn't been added to the tree yet. 755 */ 756 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { 757 struct rtfc_arg arg; --- 7 unchanged lines hidden (view full) --- 765 * actually return a resultant rtentry and 766 * give the caller a single reference. 767 */ 768 if (ret_nrt) { 769 *ret_nrt = rt; 770 rt->rt_refcnt++; 771 } 772 break; |
773 default: 774 error = EOPNOTSUPP; |
775 } 776bad: 777 splx(s); 778 return (error); |
779#undef dst 780#undef gateway 781#undef netmask 782#undef ifaaddr 783#undef ifpaddr 784#undef flags |
785} 786 787/* 788 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' 789 * (i.e., the routes related to it by the operation of cloning). This 790 * routine is iterated over all potential former-child-routes by way of 791 * rnh->rnh_walktree_from() above, and those that actually are children of 792 * the late parent (passed in as VP here) are themselves deleted. --- 112 unchanged lines hidden (view full) --- 905 */ 906#ifdef DEBUG 907 if(rtfcdebug) printf("deleting\n"); 908#endif 909 return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, 910 rt_mask(rt), rt->rt_flags, (struct rtentry **)0); 911} 912 |
913#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 914 |
915int 916rt_setgate(rt0, dst, gate) 917 struct rtentry *rt0; 918 struct sockaddr *dst, *gate; 919{ 920 caddr_t new, old; 921 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 922 register struct rtentry *rt = rt0; --- 51 unchanged lines hidden (view full) --- 974 Bcopy(dst, new, dlen); 975 Free(old); 976 } 977 978 /* 979 * If there is already a gwroute, it's now almost definitly wrong 980 * so drop it. 981 */ |
982 if (rt->rt_gwroute != NULL) { 983 RTFREE(rt->rt_gwroute); 984 rt->rt_gwroute = NULL; |
985 } 986 /* 987 * Cloning loop avoidance: 988 * In the presence of protocol-cloning and bad configuration, 989 * it is possible to get stuck in bottomless mutual recursion 990 * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing 991 * protocol-cloning to operate for gateways (which is probably the 992 * correct choice anyway), and avoid the resulting reference loops --- 52 unchanged lines hidden (view full) --- 1045int 1046rtinit(ifa, cmd, flags) 1047 register struct ifaddr *ifa; 1048 int cmd, flags; 1049{ 1050 register struct rtentry *rt; 1051 register struct sockaddr *dst; 1052 register struct sockaddr *deldst; |
1053 struct sockaddr *netmask; |
1054 struct mbuf *m = 0; 1055 struct rtentry *nrt = 0; |
1056 struct radix_node_head *rnh; 1057 struct radix_node *rn; |
1058 int error; |
1059 struct rt_addrinfo info; |
1060 |
1061 if (flags & RTF_HOST) { 1062 dst = ifa->ifa_dstaddr; 1063 netmask = NULL; 1064 } else { 1065 dst = ifa->ifa_addr; 1066 netmask = ifa->ifa_netmask; 1067 } |
1068 /* 1069 * If it's a delete, check that if it exists, it's on the correct 1070 * interface or we might scrub a route to another ifa which would 1071 * be confusing at best and possibly worse. 1072 */ 1073 if (cmd == RTM_DELETE) { 1074 /* 1075 * It's a delete, so it should already exist.. 1076 * If it's a net, mask off the host bits 1077 * (Assuming we have a mask) 1078 */ |
1079 if (netmask != NULL) { |
1080 m = m_get(M_DONTWAIT, MT_SONAME); 1081 if (m == NULL) 1082 return(ENOBUFS); 1083 deldst = mtod(m, struct sockaddr *); |
1084 rt_maskedcopy(dst, deldst, netmask); |
1085 dst = deldst; 1086 } 1087 /* |
1088 * Look up an rtentry that is in the routing tree and 1089 * contains the correct info. |
1090 */ |
1091 if ((rnh = rt_tables[dst->sa_family]) == NULL || 1092 (rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL || 1093 (rn->rn_flags & RNF_ROOT) || 1094 ((struct rtentry *)rn)->rt_ifa != ifa || 1095 !equal(SA(rn->rn_key), dst)) { 1096 if (m) 1097 (void) m_free(m); 1098 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); |
1099 } 1100 /* XXX */ 1101#if 0 1102 else { 1103 /* 1104 * One would think that as we are deleting, and we know 1105 * it doesn't exist, we could just return at this point 1106 * with an "ELSE" clause, but apparently not.. 1107 */ |
1108 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); |
1109 } 1110#endif 1111 } 1112 /* 1113 * Do the actual request 1114 */ |
1115 bzero((caddr_t)&info, sizeof(info)); 1116 info.rti_ifa = ifa; 1117 info.rti_flags = flags | ifa->ifa_flags; 1118 info.rti_info[RTAX_DST] = dst; 1119 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 1120 info.rti_info[RTAX_NETMASK] = netmask; 1121 error = rtrequest1(cmd, &info, &nrt); 1122 if (error == 0 && (rt = nrt) != NULL) { |
1123 /* 1124 * notify any listenning routing agents of the change 1125 */ |
1126 rt_newaddrmsg(cmd, ifa, error, rt); 1127 if (cmd == RTM_DELETE) { |
1128 /* |
1129 * If we are deleting, and we found an entry, then 1130 * it's been removed from the tree.. now throw it away. |
1131 */ |
1132 if (rt->rt_refcnt <= 0) { 1133 rt->rt_refcnt++; /* make a 1->0 transition */ 1134 rtfree(rt); 1135 } 1136 } else if (cmd == RTM_ADD) { |
1137 /* |
1138 * We just wanted to add it.. we don't actually 1139 * need a reference. |
1140 */ |
1141 rt->rt_refcnt--; |
1142 } |
1143 } |
1144 if (m) 1145 (void) m_free(m); |
1146 return (error); 1147} 1148 1149/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */ 1150SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0); |