1 /* $NetBSD: route.c,v 1.124 2011/02/01 01:39:20 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Kevin M. Lahey of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 35 * 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. Neither the name of the project nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 /* 63 * Copyright (c) 1980, 1986, 1991, 1993 64 * The Regents of the University of California. All rights reserved. 65 * 66 * Redistribution and use in source and binary forms, with or without 67 * modification, are permitted provided that the following conditions 68 * are met: 69 * 1. Redistributions of source code must retain the above copyright 70 * notice, this list of conditions and the following disclaimer. 71 * 2. Redistributions in binary form must reproduce the above copyright 72 * notice, this list of conditions and the following disclaimer in the 73 * documentation and/or other materials provided with the distribution. 74 * 3. Neither the name of the University nor the names of its contributors 75 * may be used to endorse or promote products derived from this software 76 * without specific prior written permission. 77 * 78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 88 * SUCH DAMAGE. 89 * 90 * @(#)route.c 8.3 (Berkeley) 1/9/95 91 */ 92 93 #include "opt_route.h" 94 95 #include <sys/cdefs.h> 96 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.124 2011/02/01 01:39:20 matt Exp $"); 97 98 #include <sys/param.h> 99 #include <sys/sysctl.h> 100 #include <sys/systm.h> 101 #include <sys/callout.h> 102 #include <sys/proc.h> 103 #include <sys/mbuf.h> 104 #include <sys/socket.h> 105 #include <sys/socketvar.h> 106 #include <sys/domain.h> 107 #include <sys/protosw.h> 108 #include <sys/kernel.h> 109 #include <sys/ioctl.h> 110 #include <sys/pool.h> 111 #include <sys/kauth.h> 112 113 #include <net/if.h> 114 #include <net/if_dl.h> 115 #include <net/route.h> 116 #include <net/raw_cb.h> 117 118 #include <netinet/in.h> 119 #include <netinet/in_var.h> 120 121 #ifdef RTFLUSH_DEBUG 122 #define rtcache_debug() __predict_false(_rtcache_debug) 123 #else /* RTFLUSH_DEBUG */ 124 #define rtcache_debug() 0 125 #endif /* RTFLUSH_DEBUG */ 126 127 struct rtstat rtstat; 128 struct radix_node_head *rt_tables[AF_MAX+1]; 129 130 int rttrash; /* routes not in table but not freed */ 131 132 struct pool rtentry_pool; 133 struct pool rttimer_pool; 134 135 struct callout rt_timer_ch; /* callout for rt_timer_timer() */ 136 137 #ifdef RTFLUSH_DEBUG 138 static int _rtcache_debug = 0; 139 #endif /* RTFLUSH_DEBUG */ 140 141 static kauth_listener_t route_listener; 142 143 static int rtdeletemsg(struct rtentry *); 144 static int rtflushclone1(struct rtentry *, void *); 145 static void rtflushclone(sa_family_t family, struct rtentry *); 146 147 #ifdef RTFLUSH_DEBUG 148 static void sysctl_net_rtcache_setup(struct sysctllog **); 149 static void 150 sysctl_net_rtcache_setup(struct sysctllog **clog) 151 { 152 const struct sysctlnode *rnode; 153 154 /* XXX do not duplicate */ 155 if (sysctl_createv(clog, 0, NULL, &rnode, CTLFLAG_PERMANENT, 156 CTLTYPE_NODE, "net", NULL, NULL, 0, NULL, 0, CTL_NET, CTL_EOL) != 0) 157 return; 158 if (sysctl_createv(clog, 0, &rnode, &rnode, CTLFLAG_PERMANENT, 159 CTLTYPE_NODE, 160 "rtcache", SYSCTL_DESCR("Route cache related settings"), 161 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL) != 0) 162 return; 163 if (sysctl_createv(clog, 0, &rnode, &rnode, 164 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 165 "debug", SYSCTL_DESCR("Debug route caches"), 166 NULL, 0, &_rtcache_debug, 0, CTL_CREATE, CTL_EOL) != 0) 167 return; 168 } 169 #endif /* RTFLUSH_DEBUG */ 170 171 struct ifaddr * 172 rt_get_ifa(struct rtentry *rt) 173 { 174 struct ifaddr *ifa; 175 176 if ((ifa = rt->rt_ifa) == NULL) 177 return ifa; 178 else if (ifa->ifa_getifa == NULL) 179 return ifa; 180 #if 0 181 else if (ifa->ifa_seqno != NULL && *ifa->ifa_seqno == rt->rt_ifa_seqno) 182 return ifa; 183 #endif 184 else { 185 ifa = (*ifa->ifa_getifa)(ifa, rt_getkey(rt)); 186 rt_replace_ifa(rt, ifa); 187 return ifa; 188 } 189 } 190 191 static void 192 rt_set_ifa1(struct rtentry *rt, struct ifaddr *ifa) 193 { 194 rt->rt_ifa = ifa; 195 if (ifa->ifa_seqno != NULL) 196 rt->rt_ifa_seqno = *ifa->ifa_seqno; 197 } 198 199 /* 200 * Is this route the connected route for the ifa? 201 */ 202 static int 203 rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa) 204 { 205 const struct sockaddr *key, *dst, *odst; 206 struct sockaddr_storage maskeddst; 207 208 key = rt_getkey(rt); 209 dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 210 if (dst == NULL || 211 dst->sa_family != key->sa_family || 212 dst->sa_len != key->sa_len) 213 return 0; 214 if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 215 odst = dst; 216 dst = (struct sockaddr *)&maskeddst; 217 rt_maskedcopy(odst, (struct sockaddr *)&maskeddst, 218 ifa->ifa_netmask); 219 } 220 return (memcmp(dst, key, dst->sa_len) == 0); 221 } 222 223 void 224 rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa) 225 { 226 if (rt->rt_ifa && 227 rt->rt_ifa != ifa && 228 rt->rt_ifa->ifa_flags & IFA_ROUTE && 229 rt_ifa_connected(rt, rt->rt_ifa)) 230 { 231 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, " 232 "replace deleted IFA_ROUTE\n", 233 (void *)rt->_rt_key, (void *)rt->rt_ifa); 234 rt->rt_ifa->ifa_flags &= ~IFA_ROUTE; 235 if (rt_ifa_connected(rt, ifa)) { 236 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, " 237 "replace added IFA_ROUTE\n", 238 (void *)rt->_rt_key, (void *)ifa); 239 ifa->ifa_flags |= IFA_ROUTE; 240 } 241 } 242 243 IFAREF(ifa); 244 IFAFREE(rt->rt_ifa); 245 rt_set_ifa1(rt, ifa); 246 } 247 248 static void 249 rt_set_ifa(struct rtentry *rt, struct ifaddr *ifa) 250 { 251 IFAREF(ifa); 252 rt_set_ifa1(rt, ifa); 253 } 254 255 void 256 rtable_init(void **table) 257 { 258 struct domain *dom; 259 DOMAIN_FOREACH(dom) 260 if (dom->dom_rtattach) 261 dom->dom_rtattach(&table[dom->dom_family], 262 dom->dom_rtoffset); 263 } 264 265 static int 266 route_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 267 void *arg0, void *arg1, void *arg2, void *arg3) 268 { 269 struct rt_msghdr *rtm; 270 int result; 271 272 result = KAUTH_RESULT_DEFER; 273 rtm = arg1; 274 275 if (action != KAUTH_NETWORK_ROUTE) 276 return result; 277 278 if (rtm->rtm_type == RTM_GET) 279 result = KAUTH_RESULT_ALLOW; 280 281 return result; 282 } 283 284 void 285 rt_init(void) 286 { 287 288 #ifdef RTFLUSH_DEBUG 289 sysctl_net_rtcache_setup(NULL); 290 #endif 291 292 pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", 293 NULL, IPL_SOFTNET); 294 pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", 295 NULL, IPL_SOFTNET); 296 297 rn_init(); /* initialize all zeroes, all ones, mask table */ 298 rtable_init((void **)rt_tables); 299 300 route_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 301 route_listener_cb, NULL); 302 } 303 304 void 305 rtflushall(int family) 306 { 307 struct domain *dom; 308 309 if (rtcache_debug()) 310 printf("%s: enter\n", __func__); 311 312 if ((dom = pffinddomain(family)) == NULL) 313 return; 314 315 rtcache_invalidate(&dom->dom_rtcache); 316 } 317 318 void 319 rtcache(struct route *ro) 320 { 321 struct domain *dom; 322 323 rtcache_invariants(ro); 324 KASSERT(ro->_ro_rt != NULL); 325 KASSERT(ro->ro_invalid == false); 326 KASSERT(rtcache_getdst(ro) != NULL); 327 328 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) == NULL) 329 return; 330 331 LIST_INSERT_HEAD(&dom->dom_rtcache, ro, ro_rtcache_next); 332 rtcache_invariants(ro); 333 } 334 335 /* 336 * Packet routing routines. 337 */ 338 struct rtentry * 339 rtalloc1(const struct sockaddr *dst, int report) 340 { 341 struct radix_node_head *rnh = rt_tables[dst->sa_family]; 342 struct rtentry *rt; 343 struct radix_node *rn; 344 struct rtentry *newrt = NULL; 345 struct rt_addrinfo info; 346 int s = splsoftnet(), err = 0, msgtype = RTM_MISS; 347 348 if (rnh && (rn = rnh->rnh_matchaddr(dst, rnh)) && 349 ((rn->rn_flags & RNF_ROOT) == 0)) { 350 newrt = rt = (struct rtentry *)rn; 351 if (report && (rt->rt_flags & RTF_CLONING)) { 352 err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0, 353 &newrt); 354 if (err) { 355 newrt = rt; 356 rt->rt_refcnt++; 357 goto miss; 358 } 359 KASSERT(newrt != NULL); 360 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 361 msgtype = RTM_RESOLVE; 362 goto miss; 363 } 364 /* Inform listeners of the new route */ 365 memset(&info, 0, sizeof(info)); 366 info.rti_info[RTAX_DST] = rt_getkey(rt); 367 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 368 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 369 if (rt->rt_ifp != NULL) { 370 info.rti_info[RTAX_IFP] = 371 rt->rt_ifp->if_dl->ifa_addr; 372 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 373 } 374 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0); 375 } else 376 rt->rt_refcnt++; 377 } else { 378 rtstat.rts_unreach++; 379 miss: if (report) { 380 memset((void *)&info, 0, sizeof(info)); 381 info.rti_info[RTAX_DST] = dst; 382 rt_missmsg(msgtype, &info, 0, err); 383 } 384 } 385 splx(s); 386 return newrt; 387 } 388 389 void 390 rtfree(struct rtentry *rt) 391 { 392 struct ifaddr *ifa; 393 394 if (rt == NULL) 395 panic("rtfree"); 396 rt->rt_refcnt--; 397 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 398 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 399 panic ("rtfree 2"); 400 rttrash--; 401 if (rt->rt_refcnt < 0) { 402 printf("rtfree: %p not freed (neg refs)\n", rt); 403 return; 404 } 405 rt_timer_remove_all(rt, 0); 406 ifa = rt->rt_ifa; 407 rt->rt_ifa = NULL; 408 IFAFREE(ifa); 409 rt->rt_ifp = NULL; 410 rt_destroy(rt); 411 pool_put(&rtentry_pool, rt); 412 } 413 } 414 415 void 416 ifafree(struct ifaddr *ifa) 417 { 418 419 #ifdef DIAGNOSTIC 420 if (ifa == NULL) 421 panic("ifafree: null ifa"); 422 if (ifa->ifa_refcnt != 0) 423 panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt); 424 #endif 425 #ifdef IFAREF_DEBUG 426 printf("ifafree: freeing ifaddr %p\n", ifa); 427 #endif 428 free(ifa, M_IFADDR); 429 } 430 431 /* 432 * Force a routing table entry to the specified 433 * destination to go through the given gateway. 434 * Normally called as a result of a routing redirect 435 * message from the network layer. 436 * 437 * N.B.: must be called at splsoftnet 438 */ 439 void 440 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway, 441 const struct sockaddr *netmask, int flags, const struct sockaddr *src, 442 struct rtentry **rtp) 443 { 444 struct rtentry *rt; 445 int error = 0; 446 uint64_t *stat = NULL; 447 struct rt_addrinfo info; 448 struct ifaddr *ifa; 449 450 /* verify the gateway is directly reachable */ 451 if ((ifa = ifa_ifwithnet(gateway)) == NULL) { 452 error = ENETUNREACH; 453 goto out; 454 } 455 rt = rtalloc1(dst, 0); 456 /* 457 * If the redirect isn't from our current router for this dst, 458 * it's either old or wrong. If it redirects us to ourselves, 459 * we have a routing loop, perhaps as a result of an interface 460 * going down recently. 461 */ 462 if (!(flags & RTF_DONE) && rt && 463 (sockaddr_cmp(src, rt->rt_gateway) != 0 || rt->rt_ifa != ifa)) 464 error = EINVAL; 465 else if (ifa_ifwithaddr(gateway)) 466 error = EHOSTUNREACH; 467 if (error) 468 goto done; 469 /* 470 * Create a new entry if we just got back a wildcard entry 471 * or the lookup failed. This is necessary for hosts 472 * which use routing redirects generated by smart gateways 473 * to dynamically build the routing tables. 474 */ 475 if (rt == NULL || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 476 goto create; 477 /* 478 * Don't listen to the redirect if it's 479 * for a route to an interface. 480 */ 481 if (rt->rt_flags & RTF_GATEWAY) { 482 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 483 /* 484 * Changing from route to net => route to host. 485 * Create new route, rather than smashing route to net. 486 */ 487 create: 488 if (rt != NULL) 489 rtfree(rt); 490 flags |= RTF_GATEWAY | RTF_DYNAMIC; 491 memset(&info, 0, sizeof(info)); 492 info.rti_info[RTAX_DST] = dst; 493 info.rti_info[RTAX_GATEWAY] = gateway; 494 info.rti_info[RTAX_NETMASK] = netmask; 495 info.rti_ifa = ifa; 496 info.rti_flags = flags; 497 rt = NULL; 498 error = rtrequest1(RTM_ADD, &info, &rt); 499 if (rt != NULL) 500 flags = rt->rt_flags; 501 stat = &rtstat.rts_dynamic; 502 } else { 503 /* 504 * Smash the current notion of the gateway to 505 * this destination. Should check about netmask!!! 506 */ 507 rt->rt_flags |= RTF_MODIFIED; 508 flags |= RTF_MODIFIED; 509 stat = &rtstat.rts_newgateway; 510 rt_setgate(rt, gateway); 511 } 512 } else 513 error = EHOSTUNREACH; 514 done: 515 if (rt) { 516 if (rtp != NULL && !error) 517 *rtp = rt; 518 else 519 rtfree(rt); 520 } 521 out: 522 if (error) 523 rtstat.rts_badredirect++; 524 else if (stat != NULL) 525 (*stat)++; 526 memset(&info, 0, sizeof(info)); 527 info.rti_info[RTAX_DST] = dst; 528 info.rti_info[RTAX_GATEWAY] = gateway; 529 info.rti_info[RTAX_NETMASK] = netmask; 530 info.rti_info[RTAX_AUTHOR] = src; 531 rt_missmsg(RTM_REDIRECT, &info, flags, error); 532 } 533 534 /* 535 * Delete a route and generate a message 536 */ 537 static int 538 rtdeletemsg(struct rtentry *rt) 539 { 540 int error; 541 struct rt_addrinfo info; 542 543 /* 544 * Request the new route so that the entry is not actually 545 * deleted. That will allow the information being reported to 546 * be accurate (and consistent with route_output()). 547 */ 548 memset(&info, 0, sizeof(info)); 549 info.rti_info[RTAX_DST] = rt_getkey(rt); 550 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 551 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 552 info.rti_flags = rt->rt_flags; 553 error = rtrequest1(RTM_DELETE, &info, &rt); 554 555 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); 556 557 /* Adjust the refcount */ 558 if (error == 0 && rt->rt_refcnt <= 0) { 559 rt->rt_refcnt++; 560 rtfree(rt); 561 } 562 return error; 563 } 564 565 static int 566 rtflushclone1(struct rtentry *rt, void *arg) 567 { 568 struct rtentry *parent; 569 570 parent = (struct rtentry *)arg; 571 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) 572 rtdeletemsg(rt); 573 return 0; 574 } 575 576 static void 577 rtflushclone(sa_family_t family, struct rtentry *parent) 578 { 579 580 #ifdef DIAGNOSTIC 581 if (!parent || (parent->rt_flags & RTF_CLONING) == 0) 582 panic("rtflushclone: called with a non-cloning route"); 583 #endif 584 rt_walktree(family, rtflushclone1, (void *)parent); 585 } 586 587 /* 588 * Routing table ioctl interface. 589 */ 590 int 591 rtioctl(u_long req, void *data, struct lwp *l) 592 { 593 return EOPNOTSUPP; 594 } 595 596 struct ifaddr * 597 ifa_ifwithroute(int flags, const struct sockaddr *dst, 598 const struct sockaddr *gateway) 599 { 600 struct ifaddr *ifa; 601 if ((flags & RTF_GATEWAY) == 0) { 602 /* 603 * If we are adding a route to an interface, 604 * and the interface is a pt to pt link 605 * we should search for the destination 606 * as our clue to the interface. Otherwise 607 * we can use the local address. 608 */ 609 ifa = NULL; 610 if (flags & RTF_HOST) 611 ifa = ifa_ifwithdstaddr(dst); 612 if (ifa == NULL) 613 ifa = ifa_ifwithaddr(gateway); 614 } else { 615 /* 616 * If we are adding a route to a remote net 617 * or host, the gateway may still be on the 618 * other end of a pt to pt link. 619 */ 620 ifa = ifa_ifwithdstaddr(gateway); 621 } 622 if (ifa == NULL) 623 ifa = ifa_ifwithnet(gateway); 624 if (ifa == NULL) { 625 struct rtentry *rt = rtalloc1(dst, 0); 626 if (rt == NULL) 627 return NULL; 628 rt->rt_refcnt--; 629 if ((ifa = rt->rt_ifa) == NULL) 630 return NULL; 631 } 632 if (ifa->ifa_addr->sa_family != dst->sa_family) { 633 struct ifaddr *oifa = ifa; 634 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 635 if (ifa == 0) 636 ifa = oifa; 637 } 638 return ifa; 639 } 640 641 int 642 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway, 643 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) 644 { 645 struct rt_addrinfo info; 646 647 memset(&info, 0, sizeof(info)); 648 info.rti_flags = flags; 649 info.rti_info[RTAX_DST] = dst; 650 info.rti_info[RTAX_GATEWAY] = gateway; 651 info.rti_info[RTAX_NETMASK] = netmask; 652 return rtrequest1(req, &info, ret_nrt); 653 } 654 655 int 656 rt_getifa(struct rt_addrinfo *info) 657 { 658 struct ifaddr *ifa; 659 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 660 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 661 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA]; 662 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP]; 663 int flags = info->rti_flags; 664 665 /* 666 * ifp may be specified by sockaddr_dl when protocol address 667 * is ambiguous 668 */ 669 if (info->rti_ifp == NULL && ifpaddr != NULL 670 && ifpaddr->sa_family == AF_LINK && 671 (ifa = ifa_ifwithnet(ifpaddr)) != NULL) 672 info->rti_ifp = ifa->ifa_ifp; 673 if (info->rti_ifa == NULL && ifaaddr != NULL) 674 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 675 if (info->rti_ifa == NULL) { 676 const struct sockaddr *sa; 677 678 sa = ifaaddr != NULL ? ifaaddr : 679 (gateway != NULL ? gateway : dst); 680 if (sa != NULL && info->rti_ifp != NULL) 681 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 682 else if (dst != NULL && gateway != NULL) 683 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 684 else if (sa != NULL) 685 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 686 } 687 if ((ifa = info->rti_ifa) == NULL) 688 return ENETUNREACH; 689 if (ifa->ifa_getifa != NULL) 690 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst); 691 if (info->rti_ifp == NULL) 692 info->rti_ifp = ifa->ifa_ifp; 693 return 0; 694 } 695 696 int 697 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) 698 { 699 int s = splsoftnet(); 700 int error = 0; 701 struct rtentry *rt, *crt; 702 struct radix_node *rn; 703 struct radix_node_head *rnh; 704 struct ifaddr *ifa, *ifa2; 705 struct sockaddr_storage maskeddst; 706 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 707 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 708 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK]; 709 int flags = info->rti_flags; 710 #define senderr(x) { error = x ; goto bad; } 711 712 if ((rnh = rt_tables[dst->sa_family]) == NULL) 713 senderr(ESRCH); 714 if (flags & RTF_HOST) 715 netmask = NULL; 716 switch (req) { 717 case RTM_DELETE: 718 if (netmask) { 719 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 720 netmask); 721 dst = (struct sockaddr *)&maskeddst; 722 } 723 if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL) 724 senderr(ESRCH); 725 rt = (struct rtentry *)rn; 726 if ((rt->rt_flags & RTF_CLONING) != 0) { 727 /* clean up any cloned children */ 728 rtflushclone(dst->sa_family, rt); 729 } 730 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL) 731 senderr(ESRCH); 732 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 733 panic ("rtrequest delete"); 734 rt = (struct rtentry *)rn; 735 if (rt->rt_gwroute) { 736 RTFREE(rt->rt_gwroute); 737 rt->rt_gwroute = NULL; 738 } 739 if (rt->rt_parent) { 740 rt->rt_parent->rt_refcnt--; 741 rt->rt_parent = NULL; 742 } 743 rt->rt_flags &= ~RTF_UP; 744 if ((ifa = rt->rt_ifa)) { 745 if (ifa->ifa_flags & IFA_ROUTE && 746 rt_ifa_connected(rt, ifa)) { 747 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, " 748 "deleted IFA_ROUTE\n", 749 (void *)rt->_rt_key, (void *)ifa); 750 ifa->ifa_flags &= ~IFA_ROUTE; 751 } 752 if (ifa->ifa_rtrequest) 753 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 754 } 755 rttrash++; 756 if (ret_nrt) 757 *ret_nrt = rt; 758 else if (rt->rt_refcnt <= 0) { 759 rt->rt_refcnt++; 760 rtfree(rt); 761 } 762 break; 763 764 case RTM_RESOLVE: 765 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) 766 senderr(EINVAL); 767 if ((rt->rt_flags & RTF_CLONING) == 0) 768 senderr(EINVAL); 769 ifa = rt->rt_ifa; 770 flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); 771 flags |= RTF_CLONED; 772 gateway = rt->rt_gateway; 773 flags |= RTF_HOST; 774 goto makeroute; 775 776 case RTM_ADD: 777 if (info->rti_ifa == NULL && (error = rt_getifa(info))) 778 senderr(error); 779 ifa = info->rti_ifa; 780 makeroute: 781 /* Already at splsoftnet() so pool_get/pool_put are safe */ 782 rt = pool_get(&rtentry_pool, PR_NOWAIT); 783 if (rt == NULL) 784 senderr(ENOBUFS); 785 memset(rt, 0, sizeof(*rt)); 786 rt->rt_flags = RTF_UP | flags; 787 LIST_INIT(&rt->rt_timer); 788 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 789 if (rt_setkey(rt, dst, M_NOWAIT) == NULL || 790 rt_setgate(rt, gateway) != 0) { 791 pool_put(&rtentry_pool, rt); 792 senderr(ENOBUFS); 793 } 794 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 795 if (netmask) { 796 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 797 netmask); 798 rt_setkey(rt, (struct sockaddr *)&maskeddst, M_NOWAIT); 799 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 800 } else { 801 rt_setkey(rt, dst, M_NOWAIT); 802 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 803 } 804 rt_set_ifa(rt, ifa); 805 if (info->rti_info[RTAX_TAG] != NULL) 806 rt_settag(rt, info->rti_info[RTAX_TAG]); 807 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 808 if (info->rti_info[RTAX_IFP] != NULL && 809 (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL && 810 ifa2->ifa_ifp != NULL) 811 rt->rt_ifp = ifa2->ifa_ifp; 812 else 813 rt->rt_ifp = ifa->ifa_ifp; 814 if (req == RTM_RESOLVE) { 815 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 816 rt->rt_parent = *ret_nrt; 817 rt->rt_parent->rt_refcnt++; 818 } 819 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 820 rn = rnh->rnh_addaddr(rt_getkey(rt), netmask, rnh, 821 rt->rt_nodes); 822 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 823 if (rn == NULL && (crt = rtalloc1(rt_getkey(rt), 0)) != NULL) { 824 /* overwrite cloned route */ 825 if ((crt->rt_flags & RTF_CLONED) != 0) { 826 rtdeletemsg(crt); 827 rn = rnh->rnh_addaddr(rt_getkey(rt), 828 netmask, rnh, rt->rt_nodes); 829 } 830 RTFREE(crt); 831 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 832 } 833 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 834 if (rn == NULL) { 835 IFAFREE(ifa); 836 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent) 837 rtfree(rt->rt_parent); 838 if (rt->rt_gwroute) 839 rtfree(rt->rt_gwroute); 840 rt_destroy(rt); 841 pool_put(&rtentry_pool, rt); 842 senderr(EEXIST); 843 } 844 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 845 if (ifa->ifa_rtrequest) 846 ifa->ifa_rtrequest(req, rt, info); 847 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 848 if (ret_nrt) { 849 *ret_nrt = rt; 850 rt->rt_refcnt++; 851 } 852 if ((rt->rt_flags & RTF_CLONING) != 0) { 853 /* clean up any cloned children */ 854 rtflushclone(dst->sa_family, rt); 855 } 856 rtflushall(dst->sa_family); 857 break; 858 case RTM_GET: 859 if (netmask != NULL) { 860 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 861 netmask); 862 dst = (struct sockaddr *)&maskeddst; 863 } 864 rn = rnh->rnh_lookup(dst, netmask, rnh); 865 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) 866 senderr(ESRCH); 867 if (ret_nrt != NULL) { 868 rt = (struct rtentry *)rn; 869 *ret_nrt = rt; 870 rt->rt_refcnt++; 871 } 872 break; 873 } 874 bad: 875 splx(s); 876 return error; 877 } 878 879 int 880 rt_setgate(struct rtentry *rt, const struct sockaddr *gate) 881 { 882 KASSERT(rt != rt->rt_gwroute); 883 884 KASSERT(rt->_rt_key != NULL); 885 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 886 887 if (rt->rt_gwroute) { 888 RTFREE(rt->rt_gwroute); 889 rt->rt_gwroute = NULL; 890 } 891 KASSERT(rt->_rt_key != NULL); 892 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 893 if (rt->rt_gateway != NULL) 894 sockaddr_free(rt->rt_gateway); 895 KASSERT(rt->_rt_key != NULL); 896 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 897 if ((rt->rt_gateway = sockaddr_dup(gate, M_NOWAIT)) == NULL) 898 return ENOMEM; 899 KASSERT(rt->_rt_key != NULL); 900 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 901 902 if (rt->rt_flags & RTF_GATEWAY) { 903 KASSERT(rt->_rt_key != NULL); 904 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 905 rt->rt_gwroute = rtalloc1(gate, 1); 906 /* 907 * If we switched gateways, grab the MTU from the new 908 * gateway route if the current MTU, if the current MTU is 909 * greater than the MTU of gateway. 910 * Note that, if the MTU of gateway is 0, we will reset the 911 * MTU of the route to run PMTUD again from scratch. XXX 912 */ 913 KASSERT(rt->_rt_key != NULL); 914 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 915 if (rt->rt_gwroute 916 && !(rt->rt_rmx.rmx_locks & RTV_MTU) 917 && rt->rt_rmx.rmx_mtu 918 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) { 919 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu; 920 } 921 } 922 KASSERT(rt->_rt_key != NULL); 923 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 924 return 0; 925 } 926 927 void 928 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst, 929 const struct sockaddr *netmask) 930 { 931 const char *netmaskp = &netmask->sa_data[0], 932 *srcp = &src->sa_data[0]; 933 char *dstp = &dst->sa_data[0]; 934 const char *maskend = dstp + MIN(netmask->sa_len, src->sa_len); 935 const char *srcend = dstp + src->sa_len; 936 937 dst->sa_len = src->sa_len; 938 dst->sa_family = src->sa_family; 939 940 while (dstp < maskend) 941 *dstp++ = *srcp++ & *netmaskp++; 942 if (dstp < srcend) 943 memset(dstp, 0, (size_t)(srcend - dstp)); 944 } 945 946 /* 947 * Set up or tear down a routing table entry, normally 948 * for an interface. 949 */ 950 int 951 rtinit(struct ifaddr *ifa, int cmd, int flags) 952 { 953 struct rtentry *rt; 954 struct sockaddr *dst, *odst; 955 struct sockaddr_storage maskeddst; 956 struct rtentry *nrt = NULL; 957 int error; 958 struct rt_addrinfo info; 959 struct sockaddr_dl *sdl; 960 const struct sockaddr_dl *ifsdl; 961 962 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 963 if (cmd == RTM_DELETE) { 964 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 965 /* Delete subnet route for this interface */ 966 odst = dst; 967 dst = (struct sockaddr *)&maskeddst; 968 rt_maskedcopy(odst, dst, ifa->ifa_netmask); 969 } 970 if ((rt = rtalloc1(dst, 0)) != NULL) { 971 rt->rt_refcnt--; 972 if (rt->rt_ifa != ifa) 973 return (flags & RTF_HOST) ? EHOSTUNREACH 974 : ENETUNREACH; 975 } 976 } 977 memset(&info, 0, sizeof(info)); 978 info.rti_ifa = ifa; 979 info.rti_flags = flags | ifa->ifa_flags; 980 info.rti_info[RTAX_DST] = dst; 981 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 982 /* 983 * XXX here, it seems that we are assuming that ifa_netmask is NULL 984 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate 985 * variable) when RTF_HOST is 1. still not sure if i can safely 986 * change it to meet bsdi4 behavior. 987 */ 988 if (cmd != RTM_LLINFO_UPD) 989 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 990 error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info, 991 &nrt); 992 if (error != 0 || (rt = nrt) == NULL) 993 ; 994 else switch (cmd) { 995 case RTM_DELETE: 996 rt_newaddrmsg(cmd, ifa, error, nrt); 997 if (rt->rt_refcnt <= 0) { 998 rt->rt_refcnt++; 999 rtfree(rt); 1000 } 1001 break; 1002 case RTM_LLINFO_UPD: 1003 rt->rt_refcnt--; 1004 RT_DPRINTF("%s: updating%s\n", __func__, 1005 ((rt->rt_flags & RTF_LLINFO) == 0) ? " (no llinfo)" : ""); 1006 1007 ifsdl = ifa->ifa_ifp->if_sadl; 1008 1009 if ((rt->rt_flags & RTF_LLINFO) != 0 && 1010 (sdl = satosdl(rt->rt_gateway)) != NULL && 1011 sdl->sdl_family == AF_LINK && 1012 sockaddr_dl_setaddr(sdl, sdl->sdl_len, CLLADDR(ifsdl), 1013 ifa->ifa_ifp->if_addrlen) == NULL) { 1014 error = EINVAL; 1015 break; 1016 } 1017 1018 if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL) 1019 ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info); 1020 rt_newaddrmsg(RTM_CHANGE, ifa, error, nrt); 1021 break; 1022 case RTM_ADD: 1023 rt->rt_refcnt--; 1024 if (rt->rt_ifa != ifa) { 1025 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 1026 rt->rt_ifa); 1027 if (rt->rt_ifa->ifa_rtrequest != NULL) { 1028 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, 1029 &info); 1030 } 1031 rt_replace_ifa(rt, ifa); 1032 rt->rt_ifp = ifa->ifa_ifp; 1033 if (ifa->ifa_rtrequest != NULL) 1034 ifa->ifa_rtrequest(RTM_ADD, rt, &info); 1035 } 1036 rt_newaddrmsg(cmd, ifa, error, nrt); 1037 break; 1038 } 1039 return error; 1040 } 1041 1042 /* 1043 * Route timer routines. These routes allow functions to be called 1044 * for various routes at any time. This is useful in supporting 1045 * path MTU discovery and redirect route deletion. 1046 * 1047 * This is similar to some BSDI internal functions, but it provides 1048 * for multiple queues for efficiency's sake... 1049 */ 1050 1051 LIST_HEAD(, rttimer_queue) rttimer_queue_head; 1052 static int rt_init_done = 0; 1053 1054 #define RTTIMER_CALLOUT(r) do { \ 1055 if (r->rtt_func != NULL) { \ 1056 (*r->rtt_func)(r->rtt_rt, r); \ 1057 } else { \ 1058 rtrequest((int) RTM_DELETE, \ 1059 rt_getkey(r->rtt_rt), \ 1060 0, 0, 0, 0); \ 1061 } \ 1062 } while (/*CONSTCOND*/0) 1063 1064 /* 1065 * Some subtle order problems with domain initialization mean that 1066 * we cannot count on this being run from rt_init before various 1067 * protocol initializations are done. Therefore, we make sure 1068 * that this is run when the first queue is added... 1069 */ 1070 1071 void 1072 rt_timer_init(void) 1073 { 1074 assert(rt_init_done == 0); 1075 1076 LIST_INIT(&rttimer_queue_head); 1077 callout_init(&rt_timer_ch, 0); 1078 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1079 rt_init_done = 1; 1080 } 1081 1082 struct rttimer_queue * 1083 rt_timer_queue_create(u_int timeout) 1084 { 1085 struct rttimer_queue *rtq; 1086 1087 if (rt_init_done == 0) 1088 rt_timer_init(); 1089 1090 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); 1091 if (rtq == NULL) 1092 return NULL; 1093 memset(rtq, 0, sizeof(*rtq)); 1094 1095 rtq->rtq_timeout = timeout; 1096 TAILQ_INIT(&rtq->rtq_head); 1097 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); 1098 1099 return rtq; 1100 } 1101 1102 void 1103 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) 1104 { 1105 1106 rtq->rtq_timeout = timeout; 1107 } 1108 1109 void 1110 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy) 1111 { 1112 struct rttimer *r; 1113 1114 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { 1115 LIST_REMOVE(r, rtt_link); 1116 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1117 if (destroy) 1118 RTTIMER_CALLOUT(r); 1119 /* we are already at splsoftnet */ 1120 pool_put(&rttimer_pool, r); 1121 if (rtq->rtq_count > 0) 1122 rtq->rtq_count--; 1123 else 1124 printf("rt_timer_queue_remove_all: " 1125 "rtq_count reached 0\n"); 1126 } 1127 } 1128 1129 void 1130 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) 1131 { 1132 1133 rt_timer_queue_remove_all(rtq, destroy); 1134 1135 LIST_REMOVE(rtq, rtq_link); 1136 1137 /* 1138 * Caller is responsible for freeing the rttimer_queue structure. 1139 */ 1140 } 1141 1142 unsigned long 1143 rt_timer_count(struct rttimer_queue *rtq) 1144 { 1145 return rtq->rtq_count; 1146 } 1147 1148 void 1149 rt_timer_remove_all(struct rtentry *rt, int destroy) 1150 { 1151 struct rttimer *r; 1152 1153 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 1154 LIST_REMOVE(r, rtt_link); 1155 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1156 if (destroy) 1157 RTTIMER_CALLOUT(r); 1158 if (r->rtt_queue->rtq_count > 0) 1159 r->rtt_queue->rtq_count--; 1160 else 1161 printf("rt_timer_remove_all: rtq_count reached 0\n"); 1162 /* we are already at splsoftnet */ 1163 pool_put(&rttimer_pool, r); 1164 } 1165 } 1166 1167 int 1168 rt_timer_add(struct rtentry *rt, 1169 void (*func)(struct rtentry *, struct rttimer *), 1170 struct rttimer_queue *queue) 1171 { 1172 struct rttimer *r; 1173 int s; 1174 1175 /* 1176 * If there's already a timer with this action, destroy it before 1177 * we add a new one. 1178 */ 1179 LIST_FOREACH(r, &rt->rt_timer, rtt_link) { 1180 if (r->rtt_func == func) 1181 break; 1182 } 1183 if (r != NULL) { 1184 LIST_REMOVE(r, rtt_link); 1185 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1186 if (r->rtt_queue->rtq_count > 0) 1187 r->rtt_queue->rtq_count--; 1188 else 1189 printf("rt_timer_add: rtq_count reached 0\n"); 1190 } else { 1191 s = splsoftnet(); 1192 r = pool_get(&rttimer_pool, PR_NOWAIT); 1193 splx(s); 1194 if (r == NULL) 1195 return ENOBUFS; 1196 } 1197 1198 memset(r, 0, sizeof(*r)); 1199 1200 r->rtt_rt = rt; 1201 r->rtt_time = time_uptime; 1202 r->rtt_func = func; 1203 r->rtt_queue = queue; 1204 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); 1205 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); 1206 r->rtt_queue->rtq_count++; 1207 1208 return 0; 1209 } 1210 1211 /* ARGSUSED */ 1212 void 1213 rt_timer_timer(void *arg) 1214 { 1215 struct rttimer_queue *rtq; 1216 struct rttimer *r; 1217 int s; 1218 1219 s = splsoftnet(); 1220 LIST_FOREACH(rtq, &rttimer_queue_head, rtq_link) { 1221 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && 1222 (r->rtt_time + rtq->rtq_timeout) < time_uptime) { 1223 LIST_REMOVE(r, rtt_link); 1224 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1225 RTTIMER_CALLOUT(r); 1226 pool_put(&rttimer_pool, r); 1227 if (rtq->rtq_count > 0) 1228 rtq->rtq_count--; 1229 else 1230 printf("rt_timer_timer: rtq_count reached 0\n"); 1231 } 1232 } 1233 splx(s); 1234 1235 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1236 } 1237 1238 static struct rtentry * 1239 _rtcache_init(struct route *ro, int flag) 1240 { 1241 rtcache_invariants(ro); 1242 KASSERT(ro->_ro_rt == NULL); 1243 1244 if (rtcache_getdst(ro) == NULL) 1245 return NULL; 1246 ro->ro_invalid = false; 1247 if ((ro->_ro_rt = rtalloc1(rtcache_getdst(ro), flag)) != NULL) 1248 rtcache(ro); 1249 1250 rtcache_invariants(ro); 1251 return ro->_ro_rt; 1252 } 1253 1254 struct rtentry * 1255 rtcache_init(struct route *ro) 1256 { 1257 return _rtcache_init(ro, 1); 1258 } 1259 1260 struct rtentry * 1261 rtcache_init_noclone(struct route *ro) 1262 { 1263 return _rtcache_init(ro, 0); 1264 } 1265 1266 struct rtentry * 1267 rtcache_update(struct route *ro, int clone) 1268 { 1269 rtcache_clear(ro); 1270 return _rtcache_init(ro, clone); 1271 } 1272 1273 void 1274 rtcache_copy(struct route *new_ro, const struct route *old_ro) 1275 { 1276 struct rtentry *rt; 1277 1278 KASSERT(new_ro != old_ro); 1279 rtcache_invariants(new_ro); 1280 rtcache_invariants(old_ro); 1281 1282 if ((rt = rtcache_validate(old_ro)) != NULL) 1283 rt->rt_refcnt++; 1284 1285 if (rtcache_getdst(old_ro) == NULL || 1286 rtcache_setdst(new_ro, rtcache_getdst(old_ro)) != 0) 1287 return; 1288 1289 new_ro->ro_invalid = false; 1290 if ((new_ro->_ro_rt = rt) != NULL) 1291 rtcache(new_ro); 1292 rtcache_invariants(new_ro); 1293 } 1294 1295 static struct dom_rtlist invalid_routes = LIST_HEAD_INITIALIZER(dom_rtlist); 1296 1297 void 1298 rtcache_invalidate(struct dom_rtlist *rtlist) 1299 { 1300 struct route *ro; 1301 1302 while ((ro = LIST_FIRST(rtlist)) != NULL) { 1303 rtcache_invariants(ro); 1304 KASSERT(ro->_ro_rt != NULL); 1305 ro->ro_invalid = true; 1306 LIST_REMOVE(ro, ro_rtcache_next); 1307 LIST_INSERT_HEAD(&invalid_routes, ro, ro_rtcache_next); 1308 rtcache_invariants(ro); 1309 } 1310 } 1311 1312 void 1313 rtcache_clear(struct route *ro) 1314 { 1315 rtcache_invariants(ro); 1316 if (ro->_ro_rt == NULL) 1317 return; 1318 1319 LIST_REMOVE(ro, ro_rtcache_next); 1320 1321 RTFREE(ro->_ro_rt); 1322 ro->_ro_rt = NULL; 1323 ro->ro_invalid = false; 1324 rtcache_invariants(ro); 1325 } 1326 1327 struct rtentry * 1328 rtcache_lookup2(struct route *ro, const struct sockaddr *dst, int clone, 1329 int *hitp) 1330 { 1331 const struct sockaddr *odst; 1332 struct rtentry *rt = NULL; 1333 1334 rtcache_invariants(ro); 1335 1336 odst = rtcache_getdst(ro); 1337 1338 if (odst == NULL) 1339 ; 1340 else if (sockaddr_cmp(odst, dst) != 0) 1341 rtcache_free(ro); 1342 else if ((rt = rtcache_validate(ro)) == NULL) 1343 rtcache_clear(ro); 1344 1345 if (rt == NULL) { 1346 *hitp = 0; 1347 if (rtcache_setdst(ro, dst) == 0) 1348 rt = _rtcache_init(ro, clone); 1349 } else 1350 *hitp = 1; 1351 1352 rtcache_invariants(ro); 1353 1354 return rt; 1355 } 1356 1357 void 1358 rtcache_free(struct route *ro) 1359 { 1360 rtcache_clear(ro); 1361 if (ro->ro_sa != NULL) { 1362 sockaddr_free(ro->ro_sa); 1363 ro->ro_sa = NULL; 1364 } 1365 rtcache_invariants(ro); 1366 } 1367 1368 int 1369 rtcache_setdst(struct route *ro, const struct sockaddr *sa) 1370 { 1371 KASSERT(sa != NULL); 1372 1373 rtcache_invariants(ro); 1374 if (ro->ro_sa != NULL && ro->ro_sa->sa_family == sa->sa_family) { 1375 rtcache_clear(ro); 1376 if (sockaddr_copy(ro->ro_sa, ro->ro_sa->sa_len, sa) != NULL) { 1377 rtcache_invariants(ro); 1378 return 0; 1379 } 1380 sockaddr_free(ro->ro_sa); 1381 } else if (ro->ro_sa != NULL) 1382 rtcache_free(ro); /* free ro_sa, wrong family */ 1383 1384 KASSERT(ro->_ro_rt == NULL); 1385 1386 if ((ro->ro_sa = sockaddr_dup(sa, M_NOWAIT)) == NULL) { 1387 rtcache_invariants(ro); 1388 return ENOMEM; 1389 } 1390 rtcache_invariants(ro); 1391 return 0; 1392 } 1393 1394 static int 1395 rt_walktree_visitor(struct radix_node *rn, void *v) 1396 { 1397 struct rtwalk *rw = (struct rtwalk *)v; 1398 1399 return (*rw->rw_f)((struct rtentry *)rn, rw->rw_v); 1400 } 1401 1402 int 1403 rt_walktree(sa_family_t family, int (*f)(struct rtentry *, void *), void *v) 1404 { 1405 struct radix_node_head *rnh = rt_tables[family]; 1406 struct rtwalk rw; 1407 1408 if (rnh == NULL) 1409 return 0; 1410 1411 rw.rw_f = f; 1412 rw.rw_v = v; 1413 1414 return rn_walktree(rnh, rt_walktree_visitor, &rw); 1415 } 1416 1417 const struct sockaddr * 1418 rt_settag(struct rtentry *rt, const struct sockaddr *tag) 1419 { 1420 if (rt->rt_tag != tag) { 1421 if (rt->rt_tag != NULL) 1422 sockaddr_free(rt->rt_tag); 1423 rt->rt_tag = sockaddr_dup(tag, M_NOWAIT); 1424 } 1425 return rt->rt_tag; 1426 } 1427 1428 struct sockaddr * 1429 rt_gettag(struct rtentry *rt) 1430 { 1431 return rt->rt_tag; 1432 } 1433