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) 1980, 1986, 1991, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)route.c 8.3 (Berkeley) 1/9/95 66 * $FreeBSD: src/sys/net/route.c,v 1.59.2.10 2003/01/17 08:04:00 ru Exp $ 67 * $DragonFly: src/sys/net/route.c,v 1.33 2007/12/05 20:46:34 swildner Exp $ 68 */ 69 70 #include "opt_inet.h" 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/malloc.h> 75 #include <sys/mbuf.h> 76 #include <sys/socket.h> 77 #include <sys/domain.h> 78 #include <sys/kernel.h> 79 #include <sys/sysctl.h> 80 #include <sys/globaldata.h> 81 #include <sys/thread.h> 82 83 #include <net/if.h> 84 #include <net/route.h> 85 #include <net/netisr.h> 86 87 #include <netinet/in.h> 88 #include <net/ip_mroute/ip_mroute.h> 89 90 #include <sys/thread2.h> 91 #include <sys/msgport2.h> 92 #include <net/netmsg2.h> 93 94 static struct rtstatistics rtstatistics_percpu[MAXCPU]; 95 #ifdef SMP 96 #define rtstat rtstatistics_percpu[mycpuid] 97 #else 98 #define rtstat rtstatistics_percpu[0] 99 #endif 100 101 struct radix_node_head *rt_tables[MAXCPU][AF_MAX+1]; 102 struct lwkt_port *rt_ports[MAXCPU]; 103 104 static void rt_maskedcopy (struct sockaddr *, struct sockaddr *, 105 struct sockaddr *); 106 static void rtable_init(void); 107 static void rtable_service_loop(void *dummy); 108 static void rtinit_rtrequest_callback(int, int, struct rt_addrinfo *, 109 struct rtentry *, void *); 110 111 #ifdef SMP 112 static void rtredirect_msghandler(struct netmsg *netmsg); 113 static void rtrequest1_msghandler(struct netmsg *netmsg); 114 #endif 115 116 SYSCTL_NODE(_net, OID_AUTO, route, CTLFLAG_RW, 0, "Routing"); 117 118 #ifdef ROUTE_DEBUG 119 static int route_debug = 1; 120 SYSCTL_INT(_net_route, OID_AUTO, route_debug, CTLFLAG_RW, 121 &route_debug, 0, ""); 122 #endif 123 124 /* 125 * Initialize the route table(s) for protocol domains and 126 * create a helper thread which will be responsible for updating 127 * route table entries on each cpu. 128 */ 129 void 130 route_init(void) 131 { 132 int cpu, origcpu; 133 thread_t rtd; 134 135 for (cpu = 0; cpu < ncpus; ++cpu) 136 bzero(&rtstatistics_percpu[cpu], sizeof(struct rtstatistics)); 137 rn_init(); /* initialize all zeroes, all ones, mask table */ 138 origcpu = mycpuid; 139 for (cpu = 0; cpu < ncpus; cpu++) { 140 lwkt_migratecpu(cpu); 141 rtable_init(); 142 lwkt_create(rtable_service_loop, NULL, &rtd, NULL, 143 TDF_STOPREQ, cpu, "rtable_cpu %d", cpu); 144 rt_ports[cpu] = &rtd->td_msgport; 145 lwkt_schedule(rtd); 146 } 147 lwkt_migratecpu(origcpu); 148 } 149 150 static void 151 rtable_init(void) 152 { 153 struct domain *dom; 154 155 SLIST_FOREACH(dom, &domains, dom_next) { 156 if (dom->dom_rtattach) { 157 dom->dom_rtattach( 158 (void **)&rt_tables[mycpuid][dom->dom_family], 159 dom->dom_rtoffset); 160 } 161 } 162 } 163 164 /* 165 * Our per-cpu table management protocol thread. All route table operations 166 * are sequentially chained through all cpus starting at cpu #0 in order to 167 * maintain duplicate route tables on each cpu. Having a spearate route 168 * table management thread allows the protocol and interrupt threads to 169 * issue route table changes. 170 */ 171 static void 172 rtable_service_loop(void *dummy __unused) 173 { 174 struct netmsg *netmsg; 175 thread_t td = curthread; 176 177 while ((netmsg = lwkt_waitport(&td->td_msgport, 0)) != NULL) { 178 netmsg->nm_dispatch(netmsg); 179 } 180 } 181 182 /* 183 * Routing statistics. 184 */ 185 #ifdef SMP 186 static int 187 sysctl_rtstatistics(SYSCTL_HANDLER_ARGS) 188 { 189 int cpu, error = 0; 190 191 for (cpu = 0; cpu < ncpus; ++cpu) { 192 if ((error = SYSCTL_OUT(req, &rtstatistics_percpu[cpu], 193 sizeof(struct rtstatistics)))) 194 break; 195 if ((error = SYSCTL_IN(req, &rtstatistics_percpu[cpu], 196 sizeof(struct rtstatistics)))) 197 break; 198 } 199 200 return (error); 201 } 202 SYSCTL_PROC(_net_route, OID_AUTO, stats, (CTLTYPE_OPAQUE|CTLFLAG_RW), 203 0, 0, sysctl_rtstatistics, "S,rtstatistics", "Routing statistics"); 204 #else 205 SYSCTL_STRUCT(_net_route, OID_AUTO, stats, CTLFLAG_RW, &rtstat, rtstatistics, 206 "Routing statistics"); 207 #endif 208 209 /* 210 * Packet routing routines. 211 */ 212 213 /* 214 * Look up and fill in the "ro_rt" rtentry field in a route structure given 215 * an address in the "ro_dst" field. Always send a report on a miss and 216 * always clone routes. 217 */ 218 void 219 rtalloc(struct route *ro) 220 { 221 rtalloc_ign(ro, 0UL); 222 } 223 224 /* 225 * Look up and fill in the "ro_rt" rtentry field in a route structure given 226 * an address in the "ro_dst" field. Always send a report on a miss and 227 * optionally clone routes when RTF_CLONING or RTF_PRCLONING are not being 228 * ignored. 229 */ 230 void 231 rtalloc_ign(struct route *ro, u_long ignoreflags) 232 { 233 if (ro->ro_rt != NULL) { 234 if (ro->ro_rt->rt_ifp != NULL && ro->ro_rt->rt_flags & RTF_UP) 235 return; 236 rtfree(ro->ro_rt); 237 ro->ro_rt = NULL; 238 } 239 ro->ro_rt = _rtlookup(&ro->ro_dst, RTL_REPORTMSG, ignoreflags); 240 } 241 242 /* 243 * Look up the route that matches the given "dst" address. 244 * 245 * Route lookup can have the side-effect of creating and returning 246 * a cloned route instead when "dst" matches a cloning route and the 247 * RTF_CLONING and RTF_PRCLONING flags are not being ignored. 248 * 249 * Any route returned has its reference count incremented. 250 */ 251 struct rtentry * 252 _rtlookup(struct sockaddr *dst, boolean_t generate_report, u_long ignore) 253 { 254 struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family]; 255 struct rtentry *rt; 256 257 if (rnh == NULL) 258 goto unreach; 259 260 /* 261 * Look up route in the radix tree. 262 */ 263 rt = (struct rtentry *) rnh->rnh_matchaddr((char *)dst, rnh); 264 if (rt == NULL) 265 goto unreach; 266 267 /* 268 * Handle cloning routes. 269 */ 270 if ((rt->rt_flags & ~ignore & (RTF_CLONING | RTF_PRCLONING)) != 0) { 271 struct rtentry *clonedroute; 272 int error; 273 274 clonedroute = rt; /* copy in/copy out parameter */ 275 error = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0, 276 &clonedroute); /* clone the route */ 277 if (error != 0) { /* cloning failed */ 278 if (generate_report) 279 rt_dstmsg(RTM_MISS, dst, error); 280 rt->rt_refcnt++; 281 return (rt); /* return the uncloned route */ 282 } 283 if (generate_report) { 284 if (clonedroute->rt_flags & RTF_XRESOLVE) 285 rt_dstmsg(RTM_RESOLVE, dst, 0); 286 else 287 rt_rtmsg(RTM_ADD, clonedroute, 288 clonedroute->rt_ifp, 0); 289 } 290 return (clonedroute); /* return cloned route */ 291 } 292 293 /* 294 * Increment the reference count of the matched route and return. 295 */ 296 rt->rt_refcnt++; 297 return (rt); 298 299 unreach: 300 rtstat.rts_unreach++; 301 if (generate_report) 302 rt_dstmsg(RTM_MISS, dst, 0); 303 return (NULL); 304 } 305 306 void 307 rtfree(struct rtentry *rt) 308 { 309 KASSERT(rt->rt_refcnt > 0, ("rtfree: rt_refcnt %ld", rt->rt_refcnt)); 310 311 --rt->rt_refcnt; 312 if (rt->rt_refcnt == 0) { 313 struct radix_node_head *rnh = 314 rt_tables[mycpuid][rt_key(rt)->sa_family]; 315 316 if (rnh->rnh_close) 317 rnh->rnh_close((struct radix_node *)rt, rnh); 318 if (!(rt->rt_flags & RTF_UP)) { 319 /* deallocate route */ 320 if (rt->rt_ifa != NULL) 321 IFAFREE(rt->rt_ifa); 322 if (rt->rt_parent != NULL) 323 RTFREE(rt->rt_parent); /* recursive call! */ 324 Free(rt_key(rt)); 325 Free(rt); 326 } 327 } 328 } 329 330 static int 331 rtredirect_oncpu(struct sockaddr *dst, struct sockaddr *gateway, 332 struct sockaddr *netmask, int flags, struct sockaddr *src) 333 { 334 struct rtentry *rt = NULL; 335 struct rt_addrinfo rtinfo; 336 struct ifaddr *ifa; 337 u_long *stat = NULL; 338 int error; 339 340 /* verify the gateway is directly reachable */ 341 if ((ifa = ifa_ifwithnet(gateway)) == NULL) { 342 error = ENETUNREACH; 343 goto out; 344 } 345 346 /* 347 * If the redirect isn't from our current router for this destination, 348 * it's either old or wrong. 349 */ 350 if (!(flags & RTF_DONE) && /* XXX JH */ 351 (rt = rtpurelookup(dst)) != NULL && 352 (!sa_equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) { 353 error = EINVAL; 354 goto done; 355 } 356 357 /* 358 * If it redirects us to ourselves, we have a routing loop, 359 * perhaps as a result of an interface going down recently. 360 */ 361 if (ifa_ifwithaddr(gateway)) { 362 error = EHOSTUNREACH; 363 goto done; 364 } 365 366 /* 367 * Create a new entry if the lookup failed or if we got back 368 * a wildcard entry for the default route. This is necessary 369 * for hosts which use routing redirects generated by smart 370 * gateways to dynamically build the routing tables. 371 */ 372 if (rt == NULL) 373 goto create; 374 if ((rt_mask(rt) != NULL && rt_mask(rt)->sa_len < 2)) { 375 rtfree(rt); 376 goto create; 377 } 378 379 /* Ignore redirects for directly connected hosts. */ 380 if (!(rt->rt_flags & RTF_GATEWAY)) { 381 error = EHOSTUNREACH; 382 goto done; 383 } 384 385 if (!(rt->rt_flags & RTF_HOST) && (flags & RTF_HOST)) { 386 /* 387 * Changing from a network route to a host route. 388 * Create a new host route rather than smashing the 389 * network route. 390 */ 391 create: 392 flags |= RTF_GATEWAY | RTF_DYNAMIC; 393 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 394 rtinfo.rti_info[RTAX_DST] = dst; 395 rtinfo.rti_info[RTAX_GATEWAY] = gateway; 396 rtinfo.rti_info[RTAX_NETMASK] = netmask; 397 rtinfo.rti_flags = flags; 398 rtinfo.rti_ifa = ifa; 399 rt = NULL; /* copy-in/copy-out parameter */ 400 error = rtrequest1(RTM_ADD, &rtinfo, &rt); 401 if (rt != NULL) 402 flags = rt->rt_flags; 403 stat = &rtstat.rts_dynamic; 404 } else { 405 /* 406 * Smash the current notion of the gateway to this destination. 407 * Should check about netmask!!! 408 */ 409 rt->rt_flags |= RTF_MODIFIED; 410 flags |= RTF_MODIFIED; 411 rt_setgate(rt, rt_key(rt), gateway); 412 error = 0; 413 stat = &rtstat.rts_newgateway; 414 } 415 416 done: 417 if (rt != NULL) 418 rtfree(rt); 419 out: 420 if (error != 0) 421 rtstat.rts_badredirect++; 422 else if (stat != NULL) 423 (*stat)++; 424 425 return error; 426 } 427 428 #ifdef SMP 429 430 struct netmsg_rtredirect { 431 struct netmsg netmsg; 432 struct sockaddr *dst; 433 struct sockaddr *gateway; 434 struct sockaddr *netmask; 435 int flags; 436 struct sockaddr *src; 437 }; 438 439 #endif 440 441 /* 442 * Force a routing table entry to the specified 443 * destination to go through the given gateway. 444 * Normally called as a result of a routing redirect 445 * message from the network layer. 446 * 447 * N.B.: must be called at splnet 448 */ 449 void 450 rtredirect(struct sockaddr *dst, struct sockaddr *gateway, 451 struct sockaddr *netmask, int flags, struct sockaddr *src) 452 { 453 struct rt_addrinfo rtinfo; 454 int error; 455 #ifdef SMP 456 struct netmsg_rtredirect msg; 457 458 netmsg_init(&msg.netmsg, &curthread->td_msgport, 0, 459 rtredirect_msghandler); 460 msg.dst = dst; 461 msg.gateway = gateway; 462 msg.netmask = netmask; 463 msg.flags = flags; 464 msg.src = src; 465 error = lwkt_domsg(rtable_portfn(0), &msg.netmsg.nm_lmsg, 0); 466 #else 467 error = rtredirect_oncpu(dst, gateway, netmask, flags, src); 468 #endif 469 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 470 rtinfo.rti_info[RTAX_DST] = dst; 471 rtinfo.rti_info[RTAX_GATEWAY] = gateway; 472 rtinfo.rti_info[RTAX_NETMASK] = netmask; 473 rtinfo.rti_info[RTAX_AUTHOR] = src; 474 rt_missmsg(RTM_REDIRECT, &rtinfo, flags, error); 475 } 476 477 #ifdef SMP 478 479 static void 480 rtredirect_msghandler(struct netmsg *netmsg) 481 { 482 struct netmsg_rtredirect *msg = (void *)netmsg; 483 int nextcpu; 484 485 rtredirect_oncpu(msg->dst, msg->gateway, msg->netmask, 486 msg->flags, msg->src); 487 nextcpu = mycpuid + 1; 488 if (nextcpu < ncpus) 489 lwkt_forwardmsg(rtable_portfn(nextcpu), &netmsg->nm_lmsg); 490 else 491 lwkt_replymsg(&netmsg->nm_lmsg, 0); 492 } 493 494 #endif 495 496 /* 497 * Routing table ioctl interface. 498 */ 499 int 500 rtioctl(u_long req, caddr_t data, struct ucred *cred) 501 { 502 #ifdef INET 503 /* Multicast goop, grrr... */ 504 return mrt_ioctl ? mrt_ioctl(req, data) : EOPNOTSUPP; 505 #else 506 return ENXIO; 507 #endif 508 } 509 510 struct ifaddr * 511 ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway) 512 { 513 struct ifaddr *ifa; 514 515 if (!(flags & RTF_GATEWAY)) { 516 /* 517 * If we are adding a route to an interface, 518 * and the interface is a point-to-point link, 519 * we should search for the destination 520 * as our clue to the interface. Otherwise 521 * we can use the local address. 522 */ 523 ifa = NULL; 524 if (flags & RTF_HOST) { 525 ifa = ifa_ifwithdstaddr(dst); 526 } 527 if (ifa == NULL) 528 ifa = ifa_ifwithaddr(gateway); 529 } else { 530 /* 531 * If we are adding a route to a remote net 532 * or host, the gateway may still be on the 533 * other end of a pt to pt link. 534 */ 535 ifa = ifa_ifwithdstaddr(gateway); 536 } 537 if (ifa == NULL) 538 ifa = ifa_ifwithnet(gateway); 539 if (ifa == NULL) { 540 struct rtentry *rt; 541 542 rt = rtpurelookup(gateway); 543 if (rt == NULL) 544 return (NULL); 545 rt->rt_refcnt--; 546 if ((ifa = rt->rt_ifa) == NULL) 547 return (NULL); 548 } 549 if (ifa->ifa_addr->sa_family != dst->sa_family) { 550 struct ifaddr *oldifa = ifa; 551 552 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 553 if (ifa == NULL) 554 ifa = oldifa; 555 } 556 return (ifa); 557 } 558 559 static int rt_fixdelete (struct radix_node *, void *); 560 static int rt_fixchange (struct radix_node *, void *); 561 562 struct rtfc_arg { 563 struct rtentry *rt0; 564 struct radix_node_head *rnh; 565 }; 566 567 /* 568 * Set rtinfo->rti_ifa and rtinfo->rti_ifp. 569 */ 570 int 571 rt_getifa(struct rt_addrinfo *rtinfo) 572 { 573 struct sockaddr *gateway = rtinfo->rti_info[RTAX_GATEWAY]; 574 struct sockaddr *dst = rtinfo->rti_info[RTAX_DST]; 575 struct sockaddr *ifaaddr = rtinfo->rti_info[RTAX_IFA]; 576 int flags = rtinfo->rti_flags; 577 578 /* 579 * ifp may be specified by sockaddr_dl 580 * when protocol address is ambiguous. 581 */ 582 if (rtinfo->rti_ifp == NULL) { 583 struct sockaddr *ifpaddr; 584 585 ifpaddr = rtinfo->rti_info[RTAX_IFP]; 586 if (ifpaddr != NULL && ifpaddr->sa_family == AF_LINK) { 587 struct ifaddr *ifa; 588 589 ifa = ifa_ifwithnet(ifpaddr); 590 if (ifa != NULL) 591 rtinfo->rti_ifp = ifa->ifa_ifp; 592 } 593 } 594 595 if (rtinfo->rti_ifa == NULL && ifaaddr != NULL) 596 rtinfo->rti_ifa = ifa_ifwithaddr(ifaaddr); 597 if (rtinfo->rti_ifa == NULL) { 598 struct sockaddr *sa; 599 600 sa = ifaaddr != NULL ? ifaaddr : 601 (gateway != NULL ? gateway : dst); 602 if (sa != NULL && rtinfo->rti_ifp != NULL) 603 rtinfo->rti_ifa = ifaof_ifpforaddr(sa, rtinfo->rti_ifp); 604 else if (dst != NULL && gateway != NULL) 605 rtinfo->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 606 else if (sa != NULL) 607 rtinfo->rti_ifa = ifa_ifwithroute(flags, sa, sa); 608 } 609 if (rtinfo->rti_ifa == NULL) 610 return (ENETUNREACH); 611 612 if (rtinfo->rti_ifp == NULL) 613 rtinfo->rti_ifp = rtinfo->rti_ifa->ifa_ifp; 614 return (0); 615 } 616 617 /* 618 * Do appropriate manipulations of a routing tree given 619 * all the bits of info needed 620 */ 621 int 622 rtrequest( 623 int req, 624 struct sockaddr *dst, 625 struct sockaddr *gateway, 626 struct sockaddr *netmask, 627 int flags, 628 struct rtentry **ret_nrt) 629 { 630 struct rt_addrinfo rtinfo; 631 632 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 633 rtinfo.rti_info[RTAX_DST] = dst; 634 rtinfo.rti_info[RTAX_GATEWAY] = gateway; 635 rtinfo.rti_info[RTAX_NETMASK] = netmask; 636 rtinfo.rti_flags = flags; 637 return rtrequest1(req, &rtinfo, ret_nrt); 638 } 639 640 int 641 rtrequest_global( 642 int req, 643 struct sockaddr *dst, 644 struct sockaddr *gateway, 645 struct sockaddr *netmask, 646 int flags) 647 { 648 struct rt_addrinfo rtinfo; 649 650 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 651 rtinfo.rti_info[RTAX_DST] = dst; 652 rtinfo.rti_info[RTAX_GATEWAY] = gateway; 653 rtinfo.rti_info[RTAX_NETMASK] = netmask; 654 rtinfo.rti_flags = flags; 655 return rtrequest1_global(req, &rtinfo, NULL, NULL); 656 } 657 658 #ifdef SMP 659 660 struct netmsg_rtq { 661 struct netmsg netmsg; 662 int req; 663 struct rt_addrinfo *rtinfo; 664 rtrequest1_callback_func_t callback; 665 void *arg; 666 }; 667 668 #endif 669 670 int 671 rtrequest1_global(int req, struct rt_addrinfo *rtinfo, 672 rtrequest1_callback_func_t callback, void *arg) 673 { 674 int error; 675 #ifdef SMP 676 struct netmsg_rtq msg; 677 678 netmsg_init(&msg.netmsg, &curthread->td_msgport, 0, 679 rtrequest1_msghandler); 680 msg.netmsg.nm_lmsg.ms_error = -1; 681 msg.req = req; 682 msg.rtinfo = rtinfo; 683 msg.callback = callback; 684 msg.arg = arg; 685 error = lwkt_domsg(rtable_portfn(0), &msg.netmsg.nm_lmsg, 0); 686 #else 687 struct rtentry *rt = NULL; 688 689 error = rtrequest1(req, rtinfo, &rt); 690 if (rt) 691 --rt->rt_refcnt; 692 if (callback) 693 callback(req, error, rtinfo, rt, arg); 694 #endif 695 return (error); 696 } 697 698 /* 699 * Handle a route table request on the current cpu. Since the route table's 700 * are supposed to be identical on each cpu, an error occuring later in the 701 * message chain is considered system-fatal. 702 */ 703 #ifdef SMP 704 705 static void 706 rtrequest1_msghandler(struct netmsg *netmsg) 707 { 708 struct netmsg_rtq *msg = (void *)netmsg; 709 struct rtentry *rt = NULL; 710 int nextcpu; 711 int error; 712 713 error = rtrequest1(msg->req, msg->rtinfo, &rt); 714 if (rt) 715 --rt->rt_refcnt; 716 if (msg->callback) 717 msg->callback(msg->req, error, msg->rtinfo, rt, msg->arg); 718 719 /* 720 * RTM_DELETE's are propogated even if an error occurs, since a 721 * cloned route might be undergoing deletion and cloned routes 722 * are not necessarily replicated. An overall error is returned 723 * only if no cpus have the route in question. 724 */ 725 if (msg->netmsg.nm_lmsg.ms_error < 0 || error == 0) 726 msg->netmsg.nm_lmsg.ms_error = error; 727 728 nextcpu = mycpuid + 1; 729 if (error && msg->req != RTM_DELETE) { 730 if (mycpuid != 0) { 731 panic("rtrequest1_msghandler: rtrequest table " 732 "error was not on cpu #0: %p", msg->rtinfo); 733 } 734 lwkt_replymsg(&msg->netmsg.nm_lmsg, error); 735 } else if (nextcpu < ncpus) { 736 lwkt_forwardmsg(rtable_portfn(nextcpu), &msg->netmsg.nm_lmsg); 737 } else { 738 lwkt_replymsg(&msg->netmsg.nm_lmsg, 739 msg->netmsg.nm_lmsg.ms_error); 740 } 741 } 742 743 #endif 744 745 int 746 rtrequest1(int req, struct rt_addrinfo *rtinfo, struct rtentry **ret_nrt) 747 { 748 struct sockaddr *dst = rtinfo->rti_info[RTAX_DST]; 749 struct rtentry *rt; 750 struct radix_node *rn; 751 struct radix_node_head *rnh; 752 struct ifaddr *ifa; 753 struct sockaddr *ndst; 754 int error = 0; 755 756 #define gotoerr(x) { error = x ; goto bad; } 757 758 #ifdef ROUTE_DEBUG 759 if (route_debug) 760 rt_addrinfo_print(req, rtinfo); 761 #endif 762 763 crit_enter(); 764 /* 765 * Find the correct routing tree to use for this Address Family 766 */ 767 if ((rnh = rt_tables[mycpuid][dst->sa_family]) == NULL) 768 gotoerr(EAFNOSUPPORT); 769 770 /* 771 * If we are adding a host route then we don't want to put 772 * a netmask in the tree, nor do we want to clone it. 773 */ 774 if (rtinfo->rti_flags & RTF_HOST) { 775 rtinfo->rti_info[RTAX_NETMASK] = NULL; 776 rtinfo->rti_flags &= ~(RTF_CLONING | RTF_PRCLONING); 777 } 778 779 switch (req) { 780 case RTM_DELETE: 781 /* Remove the item from the tree. */ 782 rn = rnh->rnh_deladdr((char *)rtinfo->rti_info[RTAX_DST], 783 (char *)rtinfo->rti_info[RTAX_NETMASK], 784 rnh); 785 if (rn == NULL) 786 gotoerr(ESRCH); 787 KASSERT(!(rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)), 788 ("rnh_deladdr returned flags 0x%x", rn->rn_flags)); 789 rt = (struct rtentry *)rn; 790 791 /* ref to prevent a deletion race */ 792 ++rt->rt_refcnt; 793 794 /* Free any routes cloned from this one. */ 795 if ((rt->rt_flags & (RTF_CLONING | RTF_PRCLONING)) && 796 rt_mask(rt) != NULL) { 797 rnh->rnh_walktree_from(rnh, (char *)rt_key(rt), 798 (char *)rt_mask(rt), 799 rt_fixdelete, rt); 800 } 801 802 if (rt->rt_gwroute != NULL) { 803 RTFREE(rt->rt_gwroute); 804 rt->rt_gwroute = NULL; 805 } 806 807 /* 808 * NB: RTF_UP must be set during the search above, 809 * because we might delete the last ref, causing 810 * rt to get freed prematurely. 811 */ 812 rt->rt_flags &= ~RTF_UP; 813 814 #ifdef ROUTE_DEBUG 815 if (route_debug) 816 rt_print(rtinfo, rt); 817 #endif 818 819 /* Give the protocol a chance to keep things in sync. */ 820 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 821 ifa->ifa_rtrequest(RTM_DELETE, rt, rtinfo); 822 823 /* 824 * If the caller wants it, then it can have it, 825 * but it's up to it to free the rtentry as we won't be 826 * doing it. 827 */ 828 KASSERT(rt->rt_refcnt >= 0, 829 ("rtrequest1(DELETE): refcnt %ld", rt->rt_refcnt)); 830 if (ret_nrt != NULL) { 831 /* leave ref intact for return */ 832 *ret_nrt = rt; 833 } else { 834 /* deref / attempt to destroy */ 835 rtfree(rt); 836 } 837 break; 838 839 case RTM_RESOLVE: 840 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) 841 gotoerr(EINVAL); 842 ifa = rt->rt_ifa; 843 rtinfo->rti_flags = 844 rt->rt_flags & ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC); 845 rtinfo->rti_flags |= RTF_WASCLONED; 846 rtinfo->rti_info[RTAX_GATEWAY] = rt->rt_gateway; 847 if ((rtinfo->rti_info[RTAX_NETMASK] = rt->rt_genmask) == NULL) 848 rtinfo->rti_flags |= RTF_HOST; 849 goto makeroute; 850 851 case RTM_ADD: 852 KASSERT(!(rtinfo->rti_flags & RTF_GATEWAY) || 853 rtinfo->rti_info[RTAX_GATEWAY] != NULL, 854 ("rtrequest: GATEWAY but no gateway")); 855 856 if (rtinfo->rti_ifa == NULL && (error = rt_getifa(rtinfo))) 857 gotoerr(error); 858 ifa = rtinfo->rti_ifa; 859 makeroute: 860 R_Malloc(rt, struct rtentry *, sizeof(struct rtentry)); 861 if (rt == NULL) 862 gotoerr(ENOBUFS); 863 bzero(rt, sizeof(struct rtentry)); 864 rt->rt_flags = RTF_UP | rtinfo->rti_flags; 865 error = rt_setgate(rt, dst, rtinfo->rti_info[RTAX_GATEWAY]); 866 if (error != 0) { 867 Free(rt); 868 gotoerr(error); 869 } 870 871 ndst = rt_key(rt); 872 if (rtinfo->rti_info[RTAX_NETMASK] != NULL) 873 rt_maskedcopy(dst, ndst, 874 rtinfo->rti_info[RTAX_NETMASK]); 875 else 876 bcopy(dst, ndst, dst->sa_len); 877 878 /* 879 * Note that we now have a reference to the ifa. 880 * This moved from below so that rnh->rnh_addaddr() can 881 * examine the ifa and ifa->ifa_ifp if it so desires. 882 */ 883 IFAREF(ifa); 884 rt->rt_ifa = ifa; 885 rt->rt_ifp = ifa->ifa_ifp; 886 /* XXX mtu manipulation will be done in rnh_addaddr -- itojun */ 887 888 rn = rnh->rnh_addaddr((char *)ndst, 889 (char *)rtinfo->rti_info[RTAX_NETMASK], 890 rnh, rt->rt_nodes); 891 if (rn == NULL) { 892 struct rtentry *oldrt; 893 894 /* 895 * We already have one of these in the tree. 896 * We do a special hack: if the old route was 897 * cloned, then we blow it away and try 898 * re-inserting the new one. 899 */ 900 oldrt = rtpurelookup(ndst); 901 if (oldrt != NULL) { 902 --oldrt->rt_refcnt; 903 if (oldrt->rt_flags & RTF_WASCLONED) { 904 rtrequest(RTM_DELETE, rt_key(oldrt), 905 oldrt->rt_gateway, 906 rt_mask(oldrt), 907 oldrt->rt_flags, NULL); 908 rn = rnh->rnh_addaddr((char *)ndst, 909 (char *) 910 rtinfo->rti_info[RTAX_NETMASK], 911 rnh, rt->rt_nodes); 912 } 913 } 914 } 915 916 /* 917 * If it still failed to go into the tree, 918 * then un-make it (this should be a function). 919 */ 920 if (rn == NULL) { 921 if (rt->rt_gwroute != NULL) 922 rtfree(rt->rt_gwroute); 923 IFAFREE(ifa); 924 Free(rt_key(rt)); 925 Free(rt); 926 gotoerr(EEXIST); 927 } 928 929 /* 930 * If we got here from RESOLVE, then we are cloning 931 * so clone the rest, and note that we 932 * are a clone (and increment the parent's references) 933 */ 934 if (req == RTM_RESOLVE) { 935 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 936 rt->rt_rmx.rmx_pksent = 0; /* reset packet counter */ 937 if ((*ret_nrt)->rt_flags & 938 (RTF_CLONING | RTF_PRCLONING)) { 939 rt->rt_parent = *ret_nrt; 940 (*ret_nrt)->rt_refcnt++; 941 } 942 } 943 944 /* 945 * if this protocol has something to add to this then 946 * allow it to do that as well. 947 */ 948 if (ifa->ifa_rtrequest != NULL) 949 ifa->ifa_rtrequest(req, rt, rtinfo); 950 951 /* 952 * We repeat the same procedure from rt_setgate() here because 953 * it doesn't fire when we call it there because the node 954 * hasn't been added to the tree yet. 955 */ 956 if (req == RTM_ADD && !(rt->rt_flags & RTF_HOST) && 957 rt_mask(rt) != NULL) { 958 struct rtfc_arg arg = { rt, rnh }; 959 960 rnh->rnh_walktree_from(rnh, (char *)rt_key(rt), 961 (char *)rt_mask(rt), 962 rt_fixchange, &arg); 963 } 964 965 #ifdef ROUTE_DEBUG 966 if (route_debug) 967 rt_print(rtinfo, rt); 968 #endif 969 /* 970 * Return the resulting rtentry, 971 * increasing the number of references by one. 972 */ 973 if (ret_nrt != NULL) { 974 rt->rt_refcnt++; 975 *ret_nrt = rt; 976 } 977 break; 978 default: 979 error = EOPNOTSUPP; 980 } 981 bad: 982 #ifdef ROUTE_DEBUG 983 if (route_debug) { 984 if (error) 985 kprintf("rti %p failed error %d\n", rtinfo, error); 986 else 987 kprintf("rti %p succeeded\n", rtinfo); 988 } 989 #endif 990 crit_exit(); 991 return (error); 992 } 993 994 /* 995 * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family'' 996 * (i.e., the routes related to it by the operation of cloning). This 997 * routine is iterated over all potential former-child-routes by way of 998 * rnh->rnh_walktree_from() above, and those that actually are children of 999 * the late parent (passed in as VP here) are themselves deleted. 1000 */ 1001 static int 1002 rt_fixdelete(struct radix_node *rn, void *vp) 1003 { 1004 struct rtentry *rt = (struct rtentry *)rn; 1005 struct rtentry *rt0 = vp; 1006 1007 if (rt->rt_parent == rt0 && 1008 !(rt->rt_flags & (RTF_PINNED | RTF_CLONING | RTF_PRCLONING))) { 1009 return rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 1010 rt->rt_flags, NULL); 1011 } 1012 return 0; 1013 } 1014 1015 /* 1016 * This routine is called from rt_setgate() to do the analogous thing for 1017 * adds and changes. There is the added complication in this case of a 1018 * middle insert; i.e., insertion of a new network route between an older 1019 * network route and (cloned) host routes. For this reason, a simple check 1020 * of rt->rt_parent is insufficient; each candidate route must be tested 1021 * against the (mask, value) of the new route (passed as before in vp) 1022 * to see if the new route matches it. 1023 * 1024 * XXX - it may be possible to do fixdelete() for changes and reserve this 1025 * routine just for adds. I'm not sure why I thought it was necessary to do 1026 * changes this way. 1027 */ 1028 #ifdef DEBUG 1029 static int rtfcdebug = 0; 1030 #endif 1031 1032 static int 1033 rt_fixchange(struct radix_node *rn, void *vp) 1034 { 1035 struct rtentry *rt = (struct rtentry *)rn; 1036 struct rtfc_arg *ap = vp; 1037 struct rtentry *rt0 = ap->rt0; 1038 struct radix_node_head *rnh = ap->rnh; 1039 u_char *xk1, *xm1, *xk2, *xmp; 1040 int i, len, mlen; 1041 1042 #ifdef DEBUG 1043 if (rtfcdebug) 1044 kprintf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0); 1045 #endif 1046 1047 if (rt->rt_parent == NULL || 1048 (rt->rt_flags & (RTF_PINNED | RTF_CLONING | RTF_PRCLONING))) { 1049 #ifdef DEBUG 1050 if (rtfcdebug) kprintf("no parent, pinned or cloning\n"); 1051 #endif 1052 return 0; 1053 } 1054 1055 if (rt->rt_parent == rt0) { 1056 #ifdef DEBUG 1057 if (rtfcdebug) kprintf("parent match\n"); 1058 #endif 1059 return rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 1060 rt->rt_flags, NULL); 1061 } 1062 1063 /* 1064 * There probably is a function somewhere which does this... 1065 * if not, there should be. 1066 */ 1067 len = imin(rt_key(rt0)->sa_len, rt_key(rt)->sa_len); 1068 1069 xk1 = (u_char *)rt_key(rt0); 1070 xm1 = (u_char *)rt_mask(rt0); 1071 xk2 = (u_char *)rt_key(rt); 1072 1073 /* avoid applying a less specific route */ 1074 xmp = (u_char *)rt_mask(rt->rt_parent); 1075 mlen = rt_key(rt->rt_parent)->sa_len; 1076 if (mlen > rt_key(rt0)->sa_len) { 1077 #ifdef DEBUG 1078 if (rtfcdebug) 1079 kprintf("rt_fixchange: inserting a less " 1080 "specific route\n"); 1081 #endif 1082 return 0; 1083 } 1084 for (i = rnh->rnh_treetop->rn_offset; i < mlen; i++) { 1085 if ((xmp[i] & ~(xmp[i] ^ xm1[i])) != xmp[i]) { 1086 #ifdef DEBUG 1087 if (rtfcdebug) 1088 kprintf("rt_fixchange: inserting a less " 1089 "specific route\n"); 1090 #endif 1091 return 0; 1092 } 1093 } 1094 1095 for (i = rnh->rnh_treetop->rn_offset; i < len; i++) { 1096 if ((xk2[i] & xm1[i]) != xk1[i]) { 1097 #ifdef DEBUG 1098 if (rtfcdebug) kprintf("no match\n"); 1099 #endif 1100 return 0; 1101 } 1102 } 1103 1104 /* 1105 * OK, this node is a clone, and matches the node currently being 1106 * changed/added under the node's mask. So, get rid of it. 1107 */ 1108 #ifdef DEBUG 1109 if (rtfcdebug) kprintf("deleting\n"); 1110 #endif 1111 return rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 1112 rt->rt_flags, NULL); 1113 } 1114 1115 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1116 1117 int 1118 rt_setgate(struct rtentry *rt0, struct sockaddr *dst, struct sockaddr *gate) 1119 { 1120 char *space, *oldspace; 1121 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 1122 struct rtentry *rt = rt0; 1123 struct radix_node_head *rnh = rt_tables[mycpuid][dst->sa_family]; 1124 1125 /* 1126 * A host route with the destination equal to the gateway 1127 * will interfere with keeping LLINFO in the routing 1128 * table, so disallow it. 1129 */ 1130 if (((rt0->rt_flags & (RTF_HOST | RTF_GATEWAY | RTF_LLINFO)) == 1131 (RTF_HOST | RTF_GATEWAY)) && 1132 dst->sa_len == gate->sa_len && 1133 sa_equal(dst, gate)) { 1134 /* 1135 * The route might already exist if this is an RTM_CHANGE 1136 * or a routing redirect, so try to delete it. 1137 */ 1138 if (rt_key(rt0) != NULL) 1139 rtrequest(RTM_DELETE, rt_key(rt0), rt0->rt_gateway, 1140 rt_mask(rt0), rt0->rt_flags, NULL); 1141 return EADDRNOTAVAIL; 1142 } 1143 1144 /* 1145 * Both dst and gateway are stored in the same malloc'ed chunk 1146 * (If I ever get my hands on....) 1147 * if we need to malloc a new chunk, then keep the old one around 1148 * till we don't need it any more. 1149 */ 1150 if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 1151 oldspace = (char *)rt_key(rt); 1152 R_Malloc(space, char *, dlen + glen); 1153 if (space == NULL) 1154 return ENOBUFS; 1155 rt->rt_nodes->rn_key = space; 1156 } else { 1157 space = (char *)rt_key(rt); /* Just use the old space. */ 1158 oldspace = NULL; 1159 } 1160 1161 /* Set the gateway value. */ 1162 rt->rt_gateway = (struct sockaddr *)(space + dlen); 1163 bcopy(gate, rt->rt_gateway, glen); 1164 1165 if (oldspace != NULL) { 1166 /* 1167 * If we allocated a new chunk, preserve the original dst. 1168 * This way, rt_setgate() really just sets the gate 1169 * and leaves the dst field alone. 1170 */ 1171 bcopy(dst, space, dlen); 1172 Free(oldspace); 1173 } 1174 1175 /* 1176 * If there is already a gwroute, it's now almost definitely wrong 1177 * so drop it. 1178 */ 1179 if (rt->rt_gwroute != NULL) { 1180 RTFREE(rt->rt_gwroute); 1181 rt->rt_gwroute = NULL; 1182 } 1183 if (rt->rt_flags & RTF_GATEWAY) { 1184 /* 1185 * Cloning loop avoidance: In the presence of 1186 * protocol-cloning and bad configuration, it is 1187 * possible to get stuck in bottomless mutual recursion 1188 * (rtrequest rt_setgate rtlookup). We avoid this 1189 * by not allowing protocol-cloning to operate for 1190 * gateways (which is probably the correct choice 1191 * anyway), and avoid the resulting reference loops 1192 * by disallowing any route to run through itself as 1193 * a gateway. This is obviously mandatory when we 1194 * get rt->rt_output(). 1195 * 1196 * This breaks TTCP for hosts outside the gateway! XXX JH 1197 */ 1198 rt->rt_gwroute = _rtlookup(gate, RTL_REPORTMSG, RTF_PRCLONING); 1199 if (rt->rt_gwroute == rt) { 1200 rt->rt_gwroute = NULL; 1201 --rt->rt_refcnt; 1202 return EDQUOT; /* failure */ 1203 } 1204 } 1205 1206 /* 1207 * This isn't going to do anything useful for host routes, so 1208 * don't bother. Also make sure we have a reasonable mask 1209 * (we don't yet have one during adds). 1210 */ 1211 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != NULL) { 1212 struct rtfc_arg arg = { rt, rnh }; 1213 1214 rnh->rnh_walktree_from(rnh, (char *)rt_key(rt), 1215 (char *)rt_mask(rt), 1216 rt_fixchange, &arg); 1217 } 1218 1219 return 0; 1220 } 1221 1222 static void 1223 rt_maskedcopy( 1224 struct sockaddr *src, 1225 struct sockaddr *dst, 1226 struct sockaddr *netmask) 1227 { 1228 u_char *cp1 = (u_char *)src; 1229 u_char *cp2 = (u_char *)dst; 1230 u_char *cp3 = (u_char *)netmask; 1231 u_char *cplim = cp2 + *cp3; 1232 u_char *cplim2 = cp2 + *cp1; 1233 1234 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 1235 cp3 += 2; 1236 if (cplim > cplim2) 1237 cplim = cplim2; 1238 while (cp2 < cplim) 1239 *cp2++ = *cp1++ & *cp3++; 1240 if (cp2 < cplim2) 1241 bzero(cp2, cplim2 - cp2); 1242 } 1243 1244 int 1245 rt_llroute(struct sockaddr *dst, struct rtentry *rt0, struct rtentry **drt) 1246 { 1247 struct rtentry *up_rt, *rt; 1248 1249 if (!(rt0->rt_flags & RTF_UP)) { 1250 up_rt = rtlookup(dst); 1251 if (up_rt == NULL) 1252 return (EHOSTUNREACH); 1253 up_rt->rt_refcnt--; 1254 } else 1255 up_rt = rt0; 1256 if (up_rt->rt_flags & RTF_GATEWAY) { 1257 if (up_rt->rt_gwroute == NULL) { 1258 up_rt->rt_gwroute = rtlookup(up_rt->rt_gateway); 1259 if (up_rt->rt_gwroute == NULL) 1260 return (EHOSTUNREACH); 1261 } else if (!(up_rt->rt_gwroute->rt_flags & RTF_UP)) { 1262 rtfree(up_rt->rt_gwroute); 1263 up_rt->rt_gwroute = rtlookup(up_rt->rt_gateway); 1264 if (up_rt->rt_gwroute == NULL) 1265 return (EHOSTUNREACH); 1266 } 1267 rt = up_rt->rt_gwroute; 1268 } else 1269 rt = up_rt; 1270 if (rt->rt_flags & RTF_REJECT && 1271 (rt->rt_rmx.rmx_expire == 0 || /* rt doesn't expire */ 1272 time_second < rt->rt_rmx.rmx_expire)) /* rt not expired */ 1273 return (rt->rt_flags & RTF_HOST ? EHOSTDOWN : EHOSTUNREACH); 1274 *drt = rt; 1275 return 0; 1276 } 1277 1278 #ifdef ROUTE_DEBUG 1279 1280 /* 1281 * Print out a route table entry 1282 */ 1283 void 1284 rt_print(struct rt_addrinfo *rtinfo, struct rtentry *rn) 1285 { 1286 kprintf("rti %p cpu %d route %p flags %08lx: ", 1287 rtinfo, mycpuid, rn, rn->rt_flags); 1288 sockaddr_print(rt_key(rn)); 1289 kprintf(" mask "); 1290 sockaddr_print(rt_mask(rn)); 1291 kprintf(" gw "); 1292 sockaddr_print(rn->rt_gateway); 1293 kprintf(" ifc \"%s\"", rn->rt_ifp ? rn->rt_ifp->if_dname : "?"); 1294 kprintf(" ifa %p\n", rn->rt_ifa); 1295 } 1296 1297 void 1298 rt_addrinfo_print(int cmd, struct rt_addrinfo *rti) 1299 { 1300 int didit = 0; 1301 int i; 1302 1303 #ifdef ROUTE_DEBUG 1304 if (cmd == RTM_DELETE && route_debug > 1) 1305 db_print_backtrace(); 1306 #endif 1307 1308 switch(cmd) { 1309 case RTM_ADD: 1310 kprintf("ADD "); 1311 break; 1312 case RTM_RESOLVE: 1313 kprintf("RES "); 1314 break; 1315 case RTM_DELETE: 1316 kprintf("DEL "); 1317 break; 1318 default: 1319 kprintf("C%02d ", cmd); 1320 break; 1321 } 1322 kprintf("rti %p cpu %d ", rti, mycpuid); 1323 for (i = 0; i < rti->rti_addrs; ++i) { 1324 if (rti->rti_info[i] == NULL) 1325 continue; 1326 if (didit) 1327 kprintf(" ,"); 1328 switch(i) { 1329 case RTAX_DST: 1330 kprintf("(DST "); 1331 break; 1332 case RTAX_GATEWAY: 1333 kprintf("(GWY "); 1334 break; 1335 case RTAX_NETMASK: 1336 kprintf("(MSK "); 1337 break; 1338 case RTAX_GENMASK: 1339 kprintf("(GEN "); 1340 break; 1341 case RTAX_IFP: 1342 kprintf("(IFP "); 1343 break; 1344 case RTAX_IFA: 1345 kprintf("(IFA "); 1346 break; 1347 case RTAX_AUTHOR: 1348 kprintf("(AUT "); 1349 break; 1350 case RTAX_BRD: 1351 kprintf("(BRD "); 1352 break; 1353 default: 1354 kprintf("(?%02d ", i); 1355 break; 1356 } 1357 sockaddr_print(rti->rti_info[i]); 1358 kprintf(")"); 1359 didit = 1; 1360 } 1361 kprintf("\n"); 1362 } 1363 1364 void 1365 sockaddr_print(struct sockaddr *sa) 1366 { 1367 struct sockaddr_in *sa4; 1368 struct sockaddr_in6 *sa6; 1369 int len; 1370 int i; 1371 1372 if (sa == NULL) { 1373 kprintf("NULL"); 1374 return; 1375 } 1376 1377 len = sa->sa_len - offsetof(struct sockaddr, sa_data[0]); 1378 1379 switch(sa->sa_family) { 1380 case AF_INET: 1381 case AF_INET6: 1382 default: 1383 switch(sa->sa_family) { 1384 case AF_INET: 1385 sa4 = (struct sockaddr_in *)sa; 1386 kprintf("INET %d %d.%d.%d.%d", 1387 ntohs(sa4->sin_port), 1388 (ntohl(sa4->sin_addr.s_addr) >> 24) & 255, 1389 (ntohl(sa4->sin_addr.s_addr) >> 16) & 255, 1390 (ntohl(sa4->sin_addr.s_addr) >> 8) & 255, 1391 (ntohl(sa4->sin_addr.s_addr) >> 0) & 255 1392 ); 1393 break; 1394 case AF_INET6: 1395 sa6 = (struct sockaddr_in6 *)sa; 1396 kprintf("INET6 %d %04x:%04x%04x:%04x:%04x:%04x:%04x:%04x", 1397 ntohs(sa6->sin6_port), 1398 sa6->sin6_addr.s6_addr16[0], 1399 sa6->sin6_addr.s6_addr16[1], 1400 sa6->sin6_addr.s6_addr16[2], 1401 sa6->sin6_addr.s6_addr16[3], 1402 sa6->sin6_addr.s6_addr16[4], 1403 sa6->sin6_addr.s6_addr16[5], 1404 sa6->sin6_addr.s6_addr16[6], 1405 sa6->sin6_addr.s6_addr16[7] 1406 ); 1407 break; 1408 default: 1409 kprintf("AF%d ", sa->sa_family); 1410 while (len > 0 && sa->sa_data[len-1] == 0) 1411 --len; 1412 1413 for (i = 0; i < len; ++i) { 1414 if (i) 1415 kprintf("."); 1416 kprintf("%d", (unsigned char)sa->sa_data[i]); 1417 } 1418 break; 1419 } 1420 } 1421 } 1422 1423 #endif 1424 1425 /* 1426 * Set up a routing table entry, normally for an interface. 1427 */ 1428 int 1429 rtinit(struct ifaddr *ifa, int cmd, int flags) 1430 { 1431 struct sockaddr *dst, *deldst, *netmask; 1432 struct mbuf *m = NULL; 1433 struct radix_node_head *rnh; 1434 struct radix_node *rn; 1435 struct rt_addrinfo rtinfo; 1436 int error; 1437 1438 if (flags & RTF_HOST) { 1439 dst = ifa->ifa_dstaddr; 1440 netmask = NULL; 1441 } else { 1442 dst = ifa->ifa_addr; 1443 netmask = ifa->ifa_netmask; 1444 } 1445 /* 1446 * If it's a delete, check that if it exists, it's on the correct 1447 * interface or we might scrub a route to another ifa which would 1448 * be confusing at best and possibly worse. 1449 */ 1450 if (cmd == RTM_DELETE) { 1451 /* 1452 * It's a delete, so it should already exist.. 1453 * If it's a net, mask off the host bits 1454 * (Assuming we have a mask) 1455 */ 1456 if (netmask != NULL) { 1457 m = m_get(MB_DONTWAIT, MT_SONAME); 1458 if (m == NULL) 1459 return (ENOBUFS); 1460 mbuftrackid(m, 34); 1461 deldst = mtod(m, struct sockaddr *); 1462 rt_maskedcopy(dst, deldst, netmask); 1463 dst = deldst; 1464 } 1465 /* 1466 * Look up an rtentry that is in the routing tree and 1467 * contains the correct info. 1468 */ 1469 if ((rnh = rt_tables[mycpuid][dst->sa_family]) == NULL || 1470 (rn = rnh->rnh_lookup((char *)dst, 1471 (char *)netmask, rnh)) == NULL || 1472 ((struct rtentry *)rn)->rt_ifa != ifa || 1473 !sa_equal((struct sockaddr *)rn->rn_key, dst)) { 1474 if (m != NULL) 1475 m_free(m); 1476 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1477 } 1478 /* XXX */ 1479 #if 0 1480 else { 1481 /* 1482 * One would think that as we are deleting, and we know 1483 * it doesn't exist, we could just return at this point 1484 * with an "ELSE" clause, but apparently not.. 1485 */ 1486 return (flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 1487 } 1488 #endif 1489 } 1490 /* 1491 * Do the actual request 1492 */ 1493 bzero(&rtinfo, sizeof(struct rt_addrinfo)); 1494 rtinfo.rti_info[RTAX_DST] = dst; 1495 rtinfo.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 1496 rtinfo.rti_info[RTAX_NETMASK] = netmask; 1497 rtinfo.rti_flags = flags | ifa->ifa_flags; 1498 rtinfo.rti_ifa = ifa; 1499 error = rtrequest1_global(cmd, &rtinfo, rtinit_rtrequest_callback, ifa); 1500 if (m != NULL) 1501 m_free(m); 1502 return (error); 1503 } 1504 1505 static void 1506 rtinit_rtrequest_callback(int cmd, int error, 1507 struct rt_addrinfo *rtinfo, struct rtentry *rt, 1508 void *arg) 1509 { 1510 struct ifaddr *ifa = arg; 1511 1512 if (error == 0 && rt) { 1513 if (mycpuid == 0) { 1514 ++rt->rt_refcnt; 1515 rt_newaddrmsg(cmd, ifa, error, rt); 1516 --rt->rt_refcnt; 1517 } 1518 if (cmd == RTM_DELETE) { 1519 if (rt->rt_refcnt == 0) { 1520 ++rt->rt_refcnt; 1521 rtfree(rt); 1522 } 1523 } 1524 } 1525 } 1526 1527 /* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */ 1528 SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0); 1529