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