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