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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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.2 (Berkeley) 11/15/93 34 * $Id: route.c,v 1.51 1999/01/27 22:42:14 dillon Exp $ 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> 43 #include <sys/mbuf.h> 44 #include <sys/socket.h> 45 #include <sys/domain.h> 46 #include <sys/kernel.h> 47 48 #include <net/if.h> 49 #include <net/route.h> 50 51 #include <netinet/in.h> 52 #include <netinet/ip_mroute.h> 53 54 #define SA(p) ((struct sockaddr *)(p)) 55 56 struct route_cb route_cb; 57 static struct rtstat rtstat; 58 struct radix_node_head *rt_tables[AF_MAX+1]; 59 60 static int rttrash; /* routes not in table but not freed */ 61 62 static void rt_maskedcopy __P((struct sockaddr *, 63 struct sockaddr *, struct sockaddr *)); 64 static void rtable_init __P((void **)); 65 66 static void 67 rtable_init(table) 68 void **table; 69 { 70 struct domain *dom; 71 for (dom = domains; dom; dom = dom->dom_next) 72 if (dom->dom_rtattach) 73 dom->dom_rtattach(&table[dom->dom_family], 74 dom->dom_rtoffset); 75 } 76 77 void 78 route_init() 79 { 80 rn_init(); /* initialize all zeroes, all ones, mask table */ 81 rtable_init((void **)rt_tables); 82 } 83 84 /* 85 * Packet routing routines. 86 */ 87 void 88 rtalloc(ro) 89 register struct route *ro; 90 { 91 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 92 return; /* XXX */ 93 ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL); 94 } 95 96 void 97 rtalloc_ign(ro, ignore) 98 register struct route *ro; 99 u_long ignore; 100 { 101 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 102 return; /* XXX */ 103 ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); 104 } 105 106 /* 107 * Look up the route that matches the address given 108 * Or, at least try.. Create a cloned route if needed. 109 */ 110 struct rtentry * 111 rtalloc1(dst, report, ignflags) 112 register struct sockaddr *dst; 113 int report; 114 u_long ignflags; 115 { 116 register struct radix_node_head *rnh = rt_tables[dst->sa_family]; 117 register struct rtentry *rt; 118 register struct radix_node *rn; 119 struct rtentry *newrt = 0; 120 struct rt_addrinfo info; 121 u_long nflags; 122 int s = splnet(), err = 0, msgtype = RTM_MISS; 123 124 /* 125 * Look up the address in the table for that Address Family 126 */ 127 if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && 128 ((rn->rn_flags & RNF_ROOT) == 0)) { 129 /* 130 * If we find it and it's not the root node, then 131 * get a refernce on the rtentry associated. 132 */ 133 newrt = rt = (struct rtentry *)rn; 134 nflags = rt->rt_flags & ~ignflags; 135 if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { 136 /* 137 * We are apparently adding (report = 0 in delete). 138 * If it requires that it be cloned, do so. 139 * (This implies it wasn't a HOST route.) 140 */ 141 err = rtrequest(RTM_RESOLVE, dst, SA(0), 142 SA(0), 0, &newrt); 143 if (err) { 144 /* 145 * If the cloning didn't succeed, maybe 146 * what we have will do. Return that. 147 */ 148 newrt = rt; 149 rt->rt_refcnt++; 150 goto miss; 151 } 152 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 153 /* 154 * If the new route specifies it be 155 * externally resolved, then go do that. 156 */ 157 msgtype = RTM_RESOLVE; 158 goto miss; 159 } 160 } else 161 rt->rt_refcnt++; 162 } else { 163 /* 164 * Either we hit the root or couldn't find any match, 165 * Which basically means 166 * "caint get there frm here" 167 */ 168 rtstat.rts_unreach++; 169 miss: if (report) { 170 /* 171 * If required, report the failure to the supervising 172 * Authorities. 173 * For a delete, this is not an error. (report == 0) 174 */ 175 bzero((caddr_t)&info, sizeof(info)); 176 info.rti_info[RTAX_DST] = dst; 177 rt_missmsg(msgtype, &info, 0, err); 178 } 179 } 180 splx(s); 181 return (newrt); 182 } 183 184 /* 185 * Remove a reference count from an rtentry. 186 * If the count gets low enough, take it out of the routing table 187 */ 188 void 189 rtfree(rt) 190 register struct rtentry *rt; 191 { 192 /* 193 * find the tree for that address family 194 */ 195 register struct radix_node_head *rnh = 196 rt_tables[rt_key(rt)->sa_family]; 197 register struct ifaddr *ifa; 198 199 if (rt == 0 || rnh == 0) 200 panic("rtfree"); 201 202 /* 203 * decrement the reference count by one and if it reaches 0, 204 * and there is a close function defined, call the close function 205 */ 206 rt->rt_refcnt--; 207 if(rnh->rnh_close && rt->rt_refcnt == 0) { 208 rnh->rnh_close((struct radix_node *)rt, rnh); 209 } 210 211 /* 212 * If we are no longer "up" (and ref == 0) 213 * then we can free the resources associated 214 * with the route. 215 */ 216 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 217 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 218 panic ("rtfree 2"); 219 /* 220 * the rtentry must have been removed from the routing table 221 * so it is represented in rttrash.. remove that now. 222 */ 223 rttrash--; 224 225 #ifdef DIAGNOSTIC 226 if (rt->rt_refcnt < 0) { 227 printf("rtfree: %p not freed (neg refs)\n", rt); 228 return; 229 } 230 #endif 231 232 /* 233 * release references on items we hold them on.. 234 * e.g other routes and ifaddrs. 235 */ 236 if((ifa = rt->rt_ifa)) 237 IFAFREE(ifa); 238 if (rt->rt_parent) { 239 RTFREE(rt->rt_parent); 240 } 241 242 /* 243 * The key is separatly alloc'd so free it (see rt_setgate()). 244 * This also frees the gateway, as they are always malloc'd 245 * together. 246 */ 247 Free(rt_key(rt)); 248 249 /* 250 * and the rtentry itself of course 251 */ 252 Free(rt); 253 } 254 } 255 256 void 257 ifafree(ifa) 258 register struct ifaddr *ifa; 259 { 260 if (ifa == NULL) 261 panic("ifafree"); 262 if (ifa->ifa_refcnt == 0) 263 free(ifa, M_IFADDR); 264 else 265 ifa->ifa_refcnt--; 266 } 267 268 /* 269 * Force a routing table entry to the specified 270 * destination to go through the given gateway. 271 * Normally called as a result of a routing redirect 272 * message from the network layer. 273 * 274 * N.B.: must be called at splnet 275 * 276 */ 277 void 278 rtredirect(dst, gateway, netmask, flags, src, rtp) 279 struct sockaddr *dst, *gateway, *netmask, *src; 280 int flags; 281 struct rtentry **rtp; 282 { 283 register struct rtentry *rt; 284 int error = 0; 285 short *stat = 0; 286 struct rt_addrinfo info; 287 struct ifaddr *ifa; 288 289 /* verify the gateway is directly reachable */ 290 if ((ifa = ifa_ifwithnet(gateway)) == 0) { 291 error = ENETUNREACH; 292 goto out; 293 } 294 rt = rtalloc1(dst, 0, 0UL); 295 /* 296 * If the redirect isn't from our current router for this dst, 297 * it's either old or wrong. If it redirects us to ourselves, 298 * we have a routing loop, perhaps as a result of an interface 299 * going down recently. 300 */ 301 #define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) 302 if (!(flags & RTF_DONE) && rt && 303 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 304 error = EINVAL; 305 else if (ifa_ifwithaddr(gateway)) 306 error = EHOSTUNREACH; 307 if (error) 308 goto done; 309 /* 310 * Create a new entry if we just got back a wildcard entry 311 * or the the lookup failed. This is necessary for hosts 312 * which use routing redirects generated by smart gateways 313 * to dynamically build the routing tables. 314 */ 315 if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 316 goto create; 317 /* 318 * Don't listen to the redirect if it's 319 * for a route to an interface. 320 */ 321 if (rt->rt_flags & RTF_GATEWAY) { 322 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 323 /* 324 * Changing from route to net => route to host. 325 * Create new route, rather than smashing route to net. 326 */ 327 create: 328 flags |= RTF_GATEWAY | RTF_DYNAMIC; 329 error = rtrequest((int)RTM_ADD, dst, gateway, 330 netmask, flags, 331 (struct rtentry **)0); 332 stat = &rtstat.rts_dynamic; 333 } else { 334 /* 335 * Smash the current notion of the gateway to 336 * this destination. Should check about netmask!!! 337 */ 338 rt->rt_flags |= RTF_MODIFIED; 339 flags |= RTF_MODIFIED; 340 stat = &rtstat.rts_newgateway; 341 /* 342 * add the key and gateway (in one malloc'd chunk). 343 */ 344 rt_setgate(rt, rt_key(rt), gateway); 345 } 346 } else 347 error = EHOSTUNREACH; 348 done: 349 if (rt) { 350 if (rtp && !error) 351 *rtp = rt; 352 else 353 rtfree(rt); 354 } 355 out: 356 if (error) 357 rtstat.rts_badredirect++; 358 else if (stat != NULL) 359 (*stat)++; 360 bzero((caddr_t)&info, sizeof(info)); 361 info.rti_info[RTAX_DST] = dst; 362 info.rti_info[RTAX_GATEWAY] = gateway; 363 info.rti_info[RTAX_NETMASK] = netmask; 364 info.rti_info[RTAX_AUTHOR] = src; 365 rt_missmsg(RTM_REDIRECT, &info, flags, error); 366 } 367 368 /* 369 * Routing table ioctl interface. 370 */ 371 int 372 rtioctl(req, data, p) 373 int req; 374 caddr_t data; 375 struct proc *p; 376 { 377 #ifdef INET 378 /* Multicast goop, grrr... */ 379 #ifdef MROUTING 380 return mrt_ioctl(req, data); 381 #else 382 return mrt_ioctl(req, data, p); 383 #endif 384 #else /* INET */ 385 return ENXIO; 386 #endif /* INET */ 387 } 388 389 struct ifaddr * 390 ifa_ifwithroute(flags, dst, gateway) 391 int flags; 392 struct sockaddr *dst, *gateway; 393 { 394 register struct ifaddr *ifa; 395 if ((flags & RTF_GATEWAY) == 0) { 396 /* 397 * If we are adding a route to an interface, 398 * and the interface is a pt to pt link 399 * we should search for the destination 400 * as our clue to the interface. Otherwise 401 * we can use the local address. 402 */ 403 ifa = 0; 404 if (flags & RTF_HOST) { 405 ifa = ifa_ifwithdstaddr(dst); 406 } 407 if (ifa == 0) 408 ifa = ifa_ifwithaddr(gateway); 409 } else { 410 /* 411 * If we are adding a route to a remote net 412 * or host, the gateway may still be on the 413 * other end of a pt to pt link. 414 */ 415 ifa = ifa_ifwithdstaddr(gateway); 416 } 417 if (ifa == 0) 418 ifa = ifa_ifwithnet(gateway); 419 if (ifa == 0) { 420 struct rtentry *rt = rtalloc1(dst, 0, 0UL); 421 if (rt == 0) 422 return (0); 423 rt->rt_refcnt--; 424 if ((ifa = rt->rt_ifa) == 0) 425 return (0); 426 } 427 if (ifa->ifa_addr->sa_family != dst->sa_family) { 428 struct ifaddr *oifa = ifa; 429 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 430 if (ifa == 0) 431 ifa = oifa; 432 } 433 return (ifa); 434 } 435 436 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 437 438 static int rt_fixdelete __P((struct radix_node *, void *)); 439 static int rt_fixchange __P((struct radix_node *, void *)); 440 441 struct rtfc_arg { 442 struct rtentry *rt0; 443 struct radix_node_head *rnh; 444 }; 445 446 /* 447 * Do appropriate manipulations of a routing tree given 448 * all the bits of info needed 449 */ 450 int 451 rtrequest(req, dst, gateway, netmask, flags, ret_nrt) 452 int req, flags; 453 struct sockaddr *dst, *gateway, *netmask; 454 struct rtentry **ret_nrt; 455 { 456 int s = splnet(); int error = 0; 457 register struct rtentry *rt; 458 register struct radix_node *rn; 459 register struct radix_node_head *rnh; 460 struct ifaddr *ifa; 461 struct sockaddr *ndst; 462 #define senderr(x) { error = x ; goto bad; } 463 464 /* 465 * Find the correct routing tree to use for this Address Family 466 */ 467 if ((rnh = rt_tables[dst->sa_family]) == 0) 468 senderr(ESRCH); 469 /* 470 * If we are adding a host route then we don't want to put 471 * a netmask in the tree 472 */ 473 if (flags & RTF_HOST) 474 netmask = 0; 475 switch (req) { 476 case RTM_DELETE: 477 /* 478 * Remove the item from the tree and return it. 479 * Complain if it is not there and do no more processing. 480 */ 481 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0) 482 senderr(ESRCH); 483 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 484 panic ("rtrequest delete"); 485 rt = (struct rtentry *)rn; 486 487 /* 488 * Now search what's left of the subtree for any cloned 489 * routes which might have been formed from this node. 490 */ 491 if ((rt->rt_flags & RTF_PRCLONING) && netmask) { 492 rnh->rnh_walktree_from(rnh, dst, netmask, 493 rt_fixdelete, rt); 494 } 495 496 /* 497 * Remove any external references we may have. 498 * This might result in another rtentry being freed if 499 * we held its last reference. 500 */ 501 if (rt->rt_gwroute) { 502 rt = rt->rt_gwroute; 503 RTFREE(rt); 504 (rt = (struct rtentry *)rn)->rt_gwroute = 0; 505 } 506 507 /* 508 * NB: RTF_UP must be set during the search above, 509 * because we might delete the last ref, causing 510 * rt to get freed prematurely. 511 * eh? then why not just add a reference? 512 * I'm not sure how RTF_UP helps matters. (JRE) 513 */ 514 rt->rt_flags &= ~RTF_UP; 515 516 /* 517 * give the protocol a chance to keep things in sync. 518 */ 519 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 520 ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 521 522 /* 523 * one more rtentry floating around that is not 524 * linked to the routing table. 525 */ 526 rttrash++; 527 528 /* 529 * If the caller wants it, then it can have it, 530 * but it's up to it to free the rtentry as we won't be 531 * doing it. 532 */ 533 if (ret_nrt) 534 *ret_nrt = rt; 535 else if (rt->rt_refcnt <= 0) { 536 rt->rt_refcnt++; /* make a 1->0 transition */ 537 rtfree(rt); 538 } 539 break; 540 541 case RTM_RESOLVE: 542 if (ret_nrt == 0 || (rt = *ret_nrt) == 0) 543 senderr(EINVAL); 544 ifa = rt->rt_ifa; 545 flags = rt->rt_flags & 546 ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC); 547 flags |= RTF_WASCLONED; 548 gateway = rt->rt_gateway; 549 if ((netmask = rt->rt_genmask) == 0) 550 flags |= RTF_HOST; 551 goto makeroute; 552 553 case RTM_ADD: 554 if ((flags & RTF_GATEWAY) && !gateway) 555 panic("rtrequest: GATEWAY but no gateway"); 556 557 if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0) 558 senderr(ENETUNREACH); 559 560 makeroute: 561 R_Malloc(rt, struct rtentry *, sizeof(*rt)); 562 if (rt == 0) 563 senderr(ENOBUFS); 564 Bzero(rt, sizeof(*rt)); 565 rt->rt_flags = RTF_UP | flags; 566 /* 567 * Add the gateway. Possibly re-malloc-ing the storage for it 568 * also add the rt_gwroute if possible. 569 */ 570 if ((error = rt_setgate(rt, dst, gateway)) != 0) { 571 Free(rt); 572 senderr(error); 573 } 574 575 /* 576 * point to the (possibly newly malloc'd) dest address. 577 */ 578 ndst = rt_key(rt); 579 580 /* 581 * make sure it contains the value we want (masked if needed). 582 */ 583 if (netmask) { 584 rt_maskedcopy(dst, ndst, netmask); 585 } else 586 Bcopy(dst, ndst, dst->sa_len); 587 588 /* 589 * Note that we now have a reference to the ifa. 590 * This moved from below so that rnh->rnh_addaddr() can 591 * examine the ifa and ifa->ifa_ifp if it so desires. 592 */ 593 ifa->ifa_refcnt++; 594 rt->rt_ifa = ifa; 595 rt->rt_ifp = ifa->ifa_ifp; 596 597 rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, 598 rnh, rt->rt_nodes); 599 if (rn == 0) { 600 struct rtentry *rt2; 601 /* 602 * Uh-oh, we already have one of these in the tree. 603 * We do a special hack: if the route that's already 604 * there was generated by the protocol-cloning 605 * mechanism, then we just blow it away and retry 606 * the insertion of the new one. 607 */ 608 rt2 = rtalloc1(dst, 0, RTF_PRCLONING); 609 if (rt2 && rt2->rt_parent) { 610 rtrequest(RTM_DELETE, 611 (struct sockaddr *)rt_key(rt2), 612 rt2->rt_gateway, 613 rt_mask(rt2), rt2->rt_flags, 0); 614 RTFREE(rt2); 615 rn = rnh->rnh_addaddr((caddr_t)ndst, 616 (caddr_t)netmask, 617 rnh, rt->rt_nodes); 618 } else if (rt2) { 619 /* undo the extra ref we got */ 620 RTFREE(rt2); 621 } 622 } 623 624 /* 625 * If it still failed to go into the tree, 626 * then un-make it (this should be a function) 627 */ 628 if (rn == 0) { 629 if (rt->rt_gwroute) 630 rtfree(rt->rt_gwroute); 631 if (rt->rt_ifa) { 632 IFAFREE(rt->rt_ifa); 633 } 634 Free(rt_key(rt)); 635 Free(rt); 636 senderr(EEXIST); 637 } 638 639 rt->rt_parent = 0; 640 641 /* 642 * If we got here from RESOLVE, then we are cloning 643 * so clone the rest, and note that we 644 * are a clone (and increment the parent's references) 645 */ 646 if (req == RTM_RESOLVE) { 647 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 648 if ((*ret_nrt)->rt_flags & RTF_PRCLONING) { 649 rt->rt_parent = (*ret_nrt); 650 (*ret_nrt)->rt_refcnt++; 651 } 652 } 653 654 /* 655 * if this protocol has something to add to this then 656 * allow it to do that as well. 657 */ 658 if (ifa->ifa_rtrequest) 659 ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0)); 660 661 /* 662 * We repeat the same procedure from rt_setgate() here because 663 * it doesn't fire when we call it there because the node 664 * hasn't been added to the tree yet. 665 */ 666 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { 667 struct rtfc_arg arg; 668 arg.rnh = rnh; 669 arg.rt0 = rt; 670 rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), 671 rt_fixchange, &arg); 672 } 673 674 /* 675 * actually return a resultant rtentry and 676 * give the caller a single reference. 677 */ 678 if (ret_nrt) { 679 *ret_nrt = rt; 680 rt->rt_refcnt++; 681 } 682 break; 683 } 684 bad: 685 splx(s); 686 return (error); 687 } 688 689 /* 690 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' 691 * (i.e., the routes related to it by the operation of cloning). This 692 * routine is iterated over all potential former-child-routes by way of 693 * rnh->rnh_walktree_from() above, and those that actually are children of 694 * the late parent (passed in as VP here) are themselves deleted. 695 */ 696 static int 697 rt_fixdelete(rn, vp) 698 struct radix_node *rn; 699 void *vp; 700 { 701 struct rtentry *rt = (struct rtentry *)rn; 702 struct rtentry *rt0 = vp; 703 704 if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) { 705 return rtrequest(RTM_DELETE, rt_key(rt), 706 (struct sockaddr *)0, rt_mask(rt), 707 rt->rt_flags, (struct rtentry **)0); 708 } 709 return 0; 710 } 711 712 /* 713 * This routine is called from rt_setgate() to do the analogous thing for 714 * adds and changes. There is the added complication in this case of a 715 * middle insert; i.e., insertion of a new network route between an older 716 * network route and (cloned) host routes. For this reason, a simple check 717 * of rt->rt_parent is insufficient; each candidate route must be tested 718 * against the (mask, value) of the new route (passed as before in vp) 719 * to see if the new route matches it. Unfortunately, this has the obnoxious 720 * property of also triggering for insertion /above/ a pre-existing network 721 * route and clones. Sigh. This may be fixed some day. 722 * 723 * XXX - it may be possible to do fixdelete() for changes and reserve this 724 * routine just for adds. I'm not sure why I thought it was necessary to do 725 * changes this way. 726 */ 727 #ifdef DEBUG 728 static int rtfcdebug = 0; 729 #endif 730 731 static int 732 rt_fixchange(rn, vp) 733 struct radix_node *rn; 734 void *vp; 735 { 736 struct rtentry *rt = (struct rtentry *)rn; 737 struct rtfc_arg *ap = vp; 738 struct rtentry *rt0 = ap->rt0; 739 struct radix_node_head *rnh = ap->rnh; 740 u_char *xk1, *xm1, *xk2; 741 int i, len; 742 743 #ifdef DEBUG 744 if (rtfcdebug) 745 printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0); 746 #endif 747 748 if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) { 749 #ifdef DEBUG 750 if(rtfcdebug) printf("no parent or pinned\n"); 751 #endif 752 return 0; 753 } 754 755 if (rt->rt_parent == rt0) { 756 #ifdef DEBUG 757 if(rtfcdebug) printf("parent match\n"); 758 #endif 759 return rtrequest(RTM_DELETE, rt_key(rt), 760 (struct sockaddr *)0, rt_mask(rt), 761 rt->rt_flags, (struct rtentry **)0); 762 } 763 764 /* 765 * There probably is a function somewhere which does this... 766 * if not, there should be. 767 */ 768 len = imin(((struct sockaddr *)rt_key(rt0))->sa_len, 769 ((struct sockaddr *)rt_key(rt))->sa_len); 770 771 xk1 = (u_char *)rt_key(rt0); 772 xm1 = (u_char *)rt_mask(rt0); 773 xk2 = (u_char *)rt_key(rt); 774 775 for (i = rnh->rnh_treetop->rn_off; i < len; i++) { 776 if ((xk2[i] & xm1[i]) != xk1[i]) { 777 #ifdef DEBUG 778 if(rtfcdebug) printf("no match\n"); 779 #endif 780 return 0; 781 } 782 } 783 784 /* 785 * OK, this node is a clone, and matches the node currently being 786 * changed/added under the node's mask. So, get rid of it. 787 */ 788 #ifdef DEBUG 789 if(rtfcdebug) printf("deleting\n"); 790 #endif 791 return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, 792 rt_mask(rt), rt->rt_flags, (struct rtentry **)0); 793 } 794 795 int 796 rt_setgate(rt0, dst, gate) 797 struct rtentry *rt0; 798 struct sockaddr *dst, *gate; 799 { 800 caddr_t new, old; 801 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 802 register struct rtentry *rt = rt0; 803 struct radix_node_head *rnh = rt_tables[dst->sa_family]; 804 805 /* 806 * A host route with the destination equal to the gateway 807 * will interfere with keeping LLINFO in the routing 808 * table, so disallow it. 809 */ 810 if (((rt0->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) == 811 (RTF_HOST|RTF_GATEWAY)) && 812 (dst->sa_len == gate->sa_len) && 813 (bcmp(dst, gate, dst->sa_len) == 0)) { 814 /* 815 * The route might already exist if this is an RTM_CHANGE 816 * or a routing redirect, so try to delete it. 817 */ 818 if (rt_key(rt0)) 819 rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt0), 820 rt0->rt_gateway, rt_mask(rt0), rt0->rt_flags, 0); 821 return EADDRNOTAVAIL; 822 } 823 824 /* 825 * Both dst and gateway are stored in the same malloc'd chunk 826 * (If I ever get my hands on....) 827 * if we need to malloc a new chunk, then keep the old one around 828 * till we don't need it any more. 829 */ 830 if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 831 old = (caddr_t)rt_key(rt); 832 R_Malloc(new, caddr_t, dlen + glen); 833 if (new == 0) 834 return ENOBUFS; 835 rt->rt_nodes->rn_key = new; 836 } else { 837 /* 838 * otherwise just overwrite the old one 839 */ 840 new = rt->rt_nodes->rn_key; 841 old = 0; 842 } 843 844 /* 845 * copy the new gateway value into the memory chunk 846 */ 847 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 848 849 /* 850 * if we are replacing the chunk (or it's new) we need to 851 * replace the dst as well 852 */ 853 if (old) { 854 Bcopy(dst, new, dlen); 855 Free(old); 856 } 857 858 /* 859 * If there is already a gwroute, it's now almost definitly wrong 860 * so drop it. 861 */ 862 if (rt->rt_gwroute) { 863 rt = rt->rt_gwroute; RTFREE(rt); 864 rt = rt0; rt->rt_gwroute = 0; 865 } 866 /* 867 * Cloning loop avoidance: 868 * In the presence of protocol-cloning and bad configuration, 869 * it is possible to get stuck in bottomless mutual recursion 870 * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing 871 * protocol-cloning to operate for gateways (which is probably the 872 * correct choice anyway), and avoid the resulting reference loops 873 * by disallowing any route to run through itself as a gateway. 874 * This is obviously mandatory when we get rt->rt_output(). 875 */ 876 if (rt->rt_flags & RTF_GATEWAY) { 877 rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING); 878 if (rt->rt_gwroute == rt) { 879 RTFREE(rt->rt_gwroute); 880 rt->rt_gwroute = 0; 881 return EDQUOT; /* failure */ 882 } 883 } 884 885 /* 886 * This isn't going to do anything useful for host routes, so 887 * don't bother. Also make sure we have a reasonable mask 888 * (we don't yet have one during adds). 889 */ 890 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) { 891 struct rtfc_arg arg; 892 arg.rnh = rnh; 893 arg.rt0 = rt; 894 rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), 895 rt_fixchange, &arg); 896 } 897 898 return 0; 899 } 900 901 static void 902 rt_maskedcopy(src, dst, netmask) 903 struct sockaddr *src, *dst, *netmask; 904 { 905 register u_char *cp1 = (u_char *)src; 906 register u_char *cp2 = (u_char *)dst; 907 register u_char *cp3 = (u_char *)netmask; 908 u_char *cplim = cp2 + *cp3; 909 u_char *cplim2 = cp2 + *cp1; 910 911 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 912 cp3 += 2; 913 if (cplim > cplim2) 914 cplim = cplim2; 915 while (cp2 < cplim) 916 *cp2++ = *cp1++ & *cp3++; 917 if (cp2 < cplim2) 918 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 919 } 920 921 /* 922 * Set up a routing table entry, normally 923 * for an interface. 924 */ 925 int 926 rtinit(ifa, cmd, flags) 927 register struct ifaddr *ifa; 928 int cmd, flags; 929 { 930 register struct rtentry *rt; 931 register struct sockaddr *dst; 932 register struct sockaddr *deldst; 933 struct mbuf *m = 0; 934 struct rtentry *nrt = 0; 935 int error; 936 937 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 938 /* 939 * If it's a delete, check that if it exists, it's on the correct 940 * interface or we might scrub a route to another ifa which would 941 * be confusing at best and possibly worse. 942 */ 943 if (cmd == RTM_DELETE) { 944 /* 945 * It's a delete, so it should already exist.. 946 * If it's a net, mask off the host bits 947 * (Assuming we have a mask) 948 */ 949 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 950 m = m_get(M_WAIT, MT_SONAME); 951 deldst = mtod(m, struct sockaddr *); 952 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 953 dst = deldst; 954 } 955 /* 956 * Get an rtentry that is in the routing tree and 957 * contains the correct info. (if this fails, can't get there). 958 * We set "report" to FALSE so that if it doesn't exist, 959 * it doesn't report an error or clone a route, etc. etc. 960 */ 961 rt = rtalloc1(dst, 0, 0UL); 962 if (rt) { 963 /* 964 * Ok so we found the rtentry. it has an extra reference 965 * for us at this stage. we won't need that so 966 * lop that off now. 967 */ 968 rt->rt_refcnt--; 969 if (rt->rt_ifa != ifa) { 970 /* 971 * If the interface in the rtentry doesn't match 972 * the interface we are using, then we don't 973 * want to delete it, so return an error. 974 * This seems to be the only point of 975 * this whole RTM_DELETE clause. 976 */ 977 if (m) 978 (void) m_free(m); 979 return (flags & RTF_HOST ? EHOSTUNREACH 980 : ENETUNREACH); 981 } 982 } 983 /* XXX */ 984 #if 0 985 else { 986 /* 987 * One would think that as we are deleting, and we know 988 * it doesn't exist, we could just return at this point 989 * with an "ELSE" clause, but apparently not.. 990 */ 991 return (flags & RTF_HOST ? EHOSTUNREACH 992 : ENETUNREACH); 993 } 994 #endif 995 } 996 /* 997 * Do the actual request 998 */ 999 error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask, 1000 flags | ifa->ifa_flags, &nrt); 1001 if (m) 1002 (void) m_free(m); 1003 /* 1004 * If we are deleting, and we found an entry, then 1005 * it's been removed from the tree.. now throw it away. 1006 */ 1007 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { 1008 /* 1009 * notify any listenning routing agents of the change 1010 */ 1011 rt_newaddrmsg(cmd, ifa, error, nrt); 1012 if (rt->rt_refcnt <= 0) { 1013 rt->rt_refcnt++; /* need a 1->0 transition to free */ 1014 rtfree(rt); 1015 } 1016 } 1017 1018 /* 1019 * We are adding, and we have a returned routing entry. 1020 * We need to sanity check the result. 1021 */ 1022 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { 1023 /* 1024 * We just wanted to add it.. we don't actually need a reference 1025 */ 1026 rt->rt_refcnt--; 1027 /* 1028 * If it came back with an unexpected interface, then it must 1029 * have already existed or something. (XXX) 1030 */ 1031 if (rt->rt_ifa != ifa) { 1032 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 1033 rt->rt_ifa); 1034 /* 1035 * Ask that the protocol in question 1036 * remove anything it has associated with 1037 * this route and ifaddr. 1038 */ 1039 if (rt->rt_ifa->ifa_rtrequest) 1040 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0)); 1041 /* 1042 * Remove the referenve to the it's ifaddr. 1043 */ 1044 IFAFREE(rt->rt_ifa); 1045 /* 1046 * And substitute in references to the ifaddr 1047 * we are adding. 1048 */ 1049 rt->rt_ifa = ifa; 1050 rt->rt_ifp = ifa->ifa_ifp; 1051 ifa->ifa_refcnt++; 1052 /* 1053 * Now ask the protocol to check if it needs 1054 * any special processing in its new form. 1055 */ 1056 if (ifa->ifa_rtrequest) 1057 ifa->ifa_rtrequest(RTM_ADD, rt, SA(0)); 1058 } 1059 /* 1060 * notify any listenning routing agents of the change 1061 */ 1062 rt_newaddrmsg(cmd, ifa, error, nrt); 1063 } 1064 return (error); 1065 } 1066 1067 SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, route_init, 0); 1068