1 /* $NetBSD: route.c,v 1.127 2013/06/08 02:42:56 christos 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.127 2013/06/08 02:42:56 christos Exp $"); 97 98 #include <sys/param.h> 99 #include <sys/kmem.h> 100 #include <sys/sysctl.h> 101 #include <sys/systm.h> 102 #include <sys/callout.h> 103 #include <sys/proc.h> 104 #include <sys/mbuf.h> 105 #include <sys/socket.h> 106 #include <sys/socketvar.h> 107 #include <sys/domain.h> 108 #include <sys/protosw.h> 109 #include <sys/kernel.h> 110 #include <sys/ioctl.h> 111 #include <sys/pool.h> 112 #include <sys/kauth.h> 113 114 #include <net/if.h> 115 #include <net/if_dl.h> 116 #include <net/route.h> 117 #include <net/raw_cb.h> 118 119 #include <netinet/in.h> 120 #include <netinet/in_var.h> 121 122 #ifdef RTFLUSH_DEBUG 123 #define rtcache_debug() __predict_false(_rtcache_debug) 124 #else /* RTFLUSH_DEBUG */ 125 #define rtcache_debug() 0 126 #endif /* RTFLUSH_DEBUG */ 127 128 struct rtstat rtstat; 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 static int 256 route_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 257 void *arg0, void *arg1, void *arg2, void *arg3) 258 { 259 struct rt_msghdr *rtm; 260 int result; 261 262 result = KAUTH_RESULT_DEFER; 263 rtm = arg1; 264 265 if (action != KAUTH_NETWORK_ROUTE) 266 return result; 267 268 if (rtm->rtm_type == RTM_GET) 269 result = KAUTH_RESULT_ALLOW; 270 271 return result; 272 } 273 274 void 275 rt_init(void) 276 { 277 278 #ifdef RTFLUSH_DEBUG 279 sysctl_net_rtcache_setup(NULL); 280 #endif 281 282 pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", 283 NULL, IPL_SOFTNET); 284 pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", 285 NULL, IPL_SOFTNET); 286 287 rn_init(); /* initialize all zeroes, all ones, mask table */ 288 rtbl_init(); 289 290 route_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 291 route_listener_cb, NULL); 292 } 293 294 void 295 rtflushall(int family) 296 { 297 struct domain *dom; 298 299 if (rtcache_debug()) 300 printf("%s: enter\n", __func__); 301 302 if ((dom = pffinddomain(family)) == NULL) 303 return; 304 305 rtcache_invalidate(&dom->dom_rtcache); 306 } 307 308 void 309 rtcache(struct route *ro) 310 { 311 struct domain *dom; 312 313 rtcache_invariants(ro); 314 KASSERT(ro->_ro_rt != NULL); 315 KASSERT(ro->ro_invalid == false); 316 KASSERT(rtcache_getdst(ro) != NULL); 317 318 if ((dom = pffinddomain(rtcache_getdst(ro)->sa_family)) == NULL) 319 return; 320 321 LIST_INSERT_HEAD(&dom->dom_rtcache, ro, ro_rtcache_next); 322 rtcache_invariants(ro); 323 } 324 325 /* 326 * Packet routing routines. 327 */ 328 struct rtentry * 329 rtalloc1(const struct sockaddr *dst, int report) 330 { 331 rtbl_t *rtbl = rt_gettable(dst->sa_family); 332 struct rtentry *rt; 333 struct rtentry *newrt = NULL; 334 struct rt_addrinfo info; 335 int s = splsoftnet(), err = 0, msgtype = RTM_MISS; 336 337 if (rtbl != NULL && (rt = rt_matchaddr(rtbl, dst)) != NULL) { 338 newrt = rt; 339 if (report && (rt->rt_flags & RTF_CLONING)) { 340 err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0, 341 &newrt); 342 if (err) { 343 newrt = rt; 344 rt->rt_refcnt++; 345 goto miss; 346 } 347 KASSERT(newrt != NULL); 348 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 349 msgtype = RTM_RESOLVE; 350 goto miss; 351 } 352 /* Inform listeners of the new route */ 353 memset(&info, 0, sizeof(info)); 354 info.rti_info[RTAX_DST] = rt_getkey(rt); 355 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 356 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 357 if (rt->rt_ifp != NULL) { 358 info.rti_info[RTAX_IFP] = 359 rt->rt_ifp->if_dl->ifa_addr; 360 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 361 } 362 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0); 363 } else 364 rt->rt_refcnt++; 365 } else { 366 rtstat.rts_unreach++; 367 miss: if (report) { 368 memset((void *)&info, 0, sizeof(info)); 369 info.rti_info[RTAX_DST] = dst; 370 rt_missmsg(msgtype, &info, 0, err); 371 } 372 } 373 splx(s); 374 return newrt; 375 } 376 377 void 378 rtfree(struct rtentry *rt) 379 { 380 struct ifaddr *ifa; 381 382 if (rt == NULL) 383 panic("rtfree"); 384 rt->rt_refcnt--; 385 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 386 rt_assert_inactive(rt); 387 rttrash--; 388 if (rt->rt_refcnt < 0) { 389 printf("rtfree: %p not freed (neg refs)\n", rt); 390 return; 391 } 392 rt_timer_remove_all(rt, 0); 393 ifa = rt->rt_ifa; 394 rt->rt_ifa = NULL; 395 IFAFREE(ifa); 396 rt->rt_ifp = NULL; 397 rt_destroy(rt); 398 pool_put(&rtentry_pool, rt); 399 } 400 } 401 402 void 403 ifafree(struct ifaddr *ifa) 404 { 405 406 #ifdef DIAGNOSTIC 407 if (ifa == NULL) 408 panic("ifafree: null ifa"); 409 if (ifa->ifa_refcnt != 0) 410 panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt); 411 #endif 412 #ifdef IFAREF_DEBUG 413 printf("ifafree: freeing ifaddr %p\n", ifa); 414 #endif 415 free(ifa, M_IFADDR); 416 } 417 418 /* 419 * Force a routing table entry to the specified 420 * destination to go through the given gateway. 421 * Normally called as a result of a routing redirect 422 * message from the network layer. 423 * 424 * N.B.: must be called at splsoftnet 425 */ 426 void 427 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway, 428 const struct sockaddr *netmask, int flags, const struct sockaddr *src, 429 struct rtentry **rtp) 430 { 431 struct rtentry *rt; 432 int error = 0; 433 uint64_t *stat = NULL; 434 struct rt_addrinfo info; 435 struct ifaddr *ifa; 436 437 /* verify the gateway is directly reachable */ 438 if ((ifa = ifa_ifwithnet(gateway)) == NULL) { 439 error = ENETUNREACH; 440 goto out; 441 } 442 rt = rtalloc1(dst, 0); 443 /* 444 * If the redirect isn't from our current router for this dst, 445 * it's either old or wrong. If it redirects us to ourselves, 446 * we have a routing loop, perhaps as a result of an interface 447 * going down recently. 448 */ 449 if (!(flags & RTF_DONE) && rt && 450 (sockaddr_cmp(src, rt->rt_gateway) != 0 || rt->rt_ifa != ifa)) 451 error = EINVAL; 452 else if (ifa_ifwithaddr(gateway)) 453 error = EHOSTUNREACH; 454 if (error) 455 goto done; 456 /* 457 * Create a new entry if we just got back a wildcard entry 458 * or the lookup failed. This is necessary for hosts 459 * which use routing redirects generated by smart gateways 460 * to dynamically build the routing tables. 461 */ 462 if (rt == NULL || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 463 goto create; 464 /* 465 * Don't listen to the redirect if it's 466 * for a route to an interface. 467 */ 468 if (rt->rt_flags & RTF_GATEWAY) { 469 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 470 /* 471 * Changing from route to net => route to host. 472 * Create new route, rather than smashing route to net. 473 */ 474 create: 475 if (rt != NULL) 476 rtfree(rt); 477 flags |= RTF_GATEWAY | RTF_DYNAMIC; 478 memset(&info, 0, sizeof(info)); 479 info.rti_info[RTAX_DST] = dst; 480 info.rti_info[RTAX_GATEWAY] = gateway; 481 info.rti_info[RTAX_NETMASK] = netmask; 482 info.rti_ifa = ifa; 483 info.rti_flags = flags; 484 rt = NULL; 485 error = rtrequest1(RTM_ADD, &info, &rt); 486 if (rt != NULL) 487 flags = rt->rt_flags; 488 stat = &rtstat.rts_dynamic; 489 } else { 490 /* 491 * Smash the current notion of the gateway to 492 * this destination. Should check about netmask!!! 493 */ 494 rt->rt_flags |= RTF_MODIFIED; 495 flags |= RTF_MODIFIED; 496 stat = &rtstat.rts_newgateway; 497 rt_setgate(rt, gateway); 498 } 499 } else 500 error = EHOSTUNREACH; 501 done: 502 if (rt) { 503 if (rtp != NULL && !error) 504 *rtp = rt; 505 else 506 rtfree(rt); 507 } 508 out: 509 if (error) 510 rtstat.rts_badredirect++; 511 else if (stat != NULL) 512 (*stat)++; 513 memset(&info, 0, sizeof(info)); 514 info.rti_info[RTAX_DST] = dst; 515 info.rti_info[RTAX_GATEWAY] = gateway; 516 info.rti_info[RTAX_NETMASK] = netmask; 517 info.rti_info[RTAX_AUTHOR] = src; 518 rt_missmsg(RTM_REDIRECT, &info, flags, error); 519 } 520 521 /* 522 * Delete a route and generate a message 523 */ 524 static int 525 rtdeletemsg(struct rtentry *rt) 526 { 527 int error; 528 struct rt_addrinfo info; 529 530 /* 531 * Request the new route so that the entry is not actually 532 * deleted. That will allow the information being reported to 533 * be accurate (and consistent with route_output()). 534 */ 535 memset(&info, 0, sizeof(info)); 536 info.rti_info[RTAX_DST] = rt_getkey(rt); 537 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 538 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 539 info.rti_flags = rt->rt_flags; 540 error = rtrequest1(RTM_DELETE, &info, &rt); 541 542 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); 543 544 /* Adjust the refcount */ 545 if (error == 0 && rt->rt_refcnt <= 0) { 546 rt->rt_refcnt++; 547 rtfree(rt); 548 } 549 return error; 550 } 551 552 static int 553 rtflushclone1(struct rtentry *rt, void *arg) 554 { 555 struct rtentry *parent; 556 557 parent = (struct rtentry *)arg; 558 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) 559 rtdeletemsg(rt); 560 return 0; 561 } 562 563 static void 564 rtflushclone(sa_family_t family, struct rtentry *parent) 565 { 566 567 #ifdef DIAGNOSTIC 568 if (!parent || (parent->rt_flags & RTF_CLONING) == 0) 569 panic("rtflushclone: called with a non-cloning route"); 570 #endif 571 rt_walktree(family, rtflushclone1, (void *)parent); 572 } 573 574 /* 575 * Routing table ioctl interface. 576 */ 577 int 578 rtioctl(u_long req, void *data, struct lwp *l) 579 { 580 return EOPNOTSUPP; 581 } 582 583 struct ifaddr * 584 ifa_ifwithroute(int flags, const struct sockaddr *dst, 585 const struct sockaddr *gateway) 586 { 587 struct ifaddr *ifa; 588 if ((flags & RTF_GATEWAY) == 0) { 589 /* 590 * If we are adding a route to an interface, 591 * and the interface is a pt to pt link 592 * we should search for the destination 593 * as our clue to the interface. Otherwise 594 * we can use the local address. 595 */ 596 ifa = NULL; 597 if ((flags & RTF_HOST) && gateway->sa_family != AF_LINK) 598 ifa = ifa_ifwithdstaddr(dst); 599 if (ifa == NULL) 600 ifa = ifa_ifwithaddr(gateway); 601 } else { 602 /* 603 * If we are adding a route to a remote net 604 * or host, the gateway may still be on the 605 * other end of a pt to pt link. 606 */ 607 ifa = ifa_ifwithdstaddr(gateway); 608 } 609 if (ifa == NULL) 610 ifa = ifa_ifwithnet(gateway); 611 if (ifa == NULL) { 612 struct rtentry *rt = rtalloc1(dst, 0); 613 if (rt == NULL) 614 return NULL; 615 rt->rt_refcnt--; 616 if ((ifa = rt->rt_ifa) == NULL) 617 return NULL; 618 } 619 if (ifa->ifa_addr->sa_family != dst->sa_family) { 620 struct ifaddr *oifa = ifa; 621 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 622 if (ifa == NULL) 623 ifa = oifa; 624 } 625 return ifa; 626 } 627 628 int 629 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway, 630 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) 631 { 632 struct rt_addrinfo info; 633 634 memset(&info, 0, sizeof(info)); 635 info.rti_flags = flags; 636 info.rti_info[RTAX_DST] = dst; 637 info.rti_info[RTAX_GATEWAY] = gateway; 638 info.rti_info[RTAX_NETMASK] = netmask; 639 return rtrequest1(req, &info, ret_nrt); 640 } 641 642 int 643 rt_getifa(struct rt_addrinfo *info) 644 { 645 struct ifaddr *ifa; 646 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 647 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 648 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA]; 649 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP]; 650 int flags = info->rti_flags; 651 652 /* 653 * ifp may be specified by sockaddr_dl when protocol address 654 * is ambiguous 655 */ 656 if (info->rti_ifp == NULL && ifpaddr != NULL 657 && ifpaddr->sa_family == AF_LINK && 658 (ifa = ifa_ifwithnet(ifpaddr)) != NULL) 659 info->rti_ifp = ifa->ifa_ifp; 660 if (info->rti_ifa == NULL && ifaaddr != NULL) 661 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 662 if (info->rti_ifa == NULL) { 663 const struct sockaddr *sa; 664 665 sa = ifaaddr != NULL ? ifaaddr : 666 (gateway != NULL ? gateway : dst); 667 if (sa != NULL && info->rti_ifp != NULL) 668 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 669 else if (dst != NULL && gateway != NULL) 670 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 671 else if (sa != NULL) 672 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 673 } 674 if ((ifa = info->rti_ifa) == NULL) 675 return ENETUNREACH; 676 if (ifa->ifa_getifa != NULL) 677 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst); 678 if (info->rti_ifp == NULL) 679 info->rti_ifp = ifa->ifa_ifp; 680 return 0; 681 } 682 683 int 684 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) 685 { 686 int s = splsoftnet(); 687 int error = 0, rc; 688 struct rtentry *rt, *crt; 689 rtbl_t *rtbl; 690 struct ifaddr *ifa, *ifa2; 691 struct sockaddr_storage maskeddst; 692 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 693 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 694 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK]; 695 int flags = info->rti_flags; 696 #define senderr(x) { error = x ; goto bad; } 697 698 if ((rtbl = rt_gettable(dst->sa_family)) == NULL) 699 senderr(ESRCH); 700 if (flags & RTF_HOST) 701 netmask = NULL; 702 switch (req) { 703 case RTM_DELETE: 704 if (netmask) { 705 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 706 netmask); 707 dst = (struct sockaddr *)&maskeddst; 708 } 709 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL) 710 senderr(ESRCH); 711 if ((rt->rt_flags & RTF_CLONING) != 0) { 712 /* clean up any cloned children */ 713 rtflushclone(dst->sa_family, rt); 714 } 715 if ((rt = rt_deladdr(rtbl, dst, netmask)) == NULL) 716 senderr(ESRCH); 717 if (rt->rt_gwroute) { 718 RTFREE(rt->rt_gwroute); 719 rt->rt_gwroute = NULL; 720 } 721 if (rt->rt_parent) { 722 rt->rt_parent->rt_refcnt--; 723 rt->rt_parent = NULL; 724 } 725 rt->rt_flags &= ~RTF_UP; 726 if ((ifa = rt->rt_ifa)) { 727 if (ifa->ifa_flags & IFA_ROUTE && 728 rt_ifa_connected(rt, ifa)) { 729 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, " 730 "deleted IFA_ROUTE\n", 731 (void *)rt->_rt_key, (void *)ifa); 732 ifa->ifa_flags &= ~IFA_ROUTE; 733 } 734 if (ifa->ifa_rtrequest) 735 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 736 } 737 rttrash++; 738 if (ret_nrt) 739 *ret_nrt = rt; 740 else if (rt->rt_refcnt <= 0) { 741 rt->rt_refcnt++; 742 rtfree(rt); 743 } 744 break; 745 746 case RTM_RESOLVE: 747 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) 748 senderr(EINVAL); 749 if ((rt->rt_flags & RTF_CLONING) == 0) 750 senderr(EINVAL); 751 ifa = rt->rt_ifa; 752 flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); 753 flags |= RTF_CLONED; 754 gateway = rt->rt_gateway; 755 flags |= RTF_HOST; 756 goto makeroute; 757 758 case RTM_ADD: 759 if (info->rti_ifa == NULL && (error = rt_getifa(info))) 760 senderr(error); 761 ifa = info->rti_ifa; 762 makeroute: 763 /* Already at splsoftnet() so pool_get/pool_put are safe */ 764 rt = pool_get(&rtentry_pool, PR_NOWAIT); 765 if (rt == NULL) 766 senderr(ENOBUFS); 767 memset(rt, 0, sizeof(*rt)); 768 rt->rt_flags = RTF_UP | flags; 769 LIST_INIT(&rt->rt_timer); 770 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 771 if (rt_setkey(rt, dst, M_NOWAIT) == NULL || 772 rt_setgate(rt, gateway) != 0) { 773 pool_put(&rtentry_pool, rt); 774 senderr(ENOBUFS); 775 } 776 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 777 if (netmask) { 778 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 779 netmask); 780 rt_setkey(rt, (struct sockaddr *)&maskeddst, M_NOWAIT); 781 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 782 } else { 783 rt_setkey(rt, dst, M_NOWAIT); 784 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 785 } 786 rt_set_ifa(rt, ifa); 787 if (info->rti_info[RTAX_TAG] != NULL) 788 rt_settag(rt, info->rti_info[RTAX_TAG]); 789 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 790 if (info->rti_info[RTAX_IFP] != NULL && 791 (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL && 792 ifa2->ifa_ifp != NULL) 793 rt->rt_ifp = ifa2->ifa_ifp; 794 else 795 rt->rt_ifp = ifa->ifa_ifp; 796 if (req == RTM_RESOLVE) { 797 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 798 rt->rt_parent = *ret_nrt; 799 rt->rt_parent->rt_refcnt++; 800 } 801 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 802 rc = rt_addaddr(rtbl, rt, netmask); 803 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 804 if (rc != 0 && (crt = rtalloc1(rt_getkey(rt), 0)) != NULL) { 805 /* overwrite cloned route */ 806 if ((crt->rt_flags & RTF_CLONED) != 0) { 807 rtdeletemsg(crt); 808 rc = rt_addaddr(rtbl, rt, netmask); 809 } 810 RTFREE(crt); 811 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 812 } 813 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 814 if (rc != 0) { 815 IFAFREE(ifa); 816 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent) 817 rtfree(rt->rt_parent); 818 if (rt->rt_gwroute) 819 rtfree(rt->rt_gwroute); 820 rt_destroy(rt); 821 pool_put(&rtentry_pool, rt); 822 senderr(rc); 823 } 824 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 825 if (ifa->ifa_rtrequest) 826 ifa->ifa_rtrequest(req, rt, info); 827 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 828 if (ret_nrt) { 829 *ret_nrt = rt; 830 rt->rt_refcnt++; 831 } 832 if ((rt->rt_flags & RTF_CLONING) != 0) { 833 /* clean up any cloned children */ 834 rtflushclone(dst->sa_family, rt); 835 } 836 rtflushall(dst->sa_family); 837 break; 838 case RTM_GET: 839 if (netmask != NULL) { 840 rt_maskedcopy(dst, (struct sockaddr *)&maskeddst, 841 netmask); 842 dst = (struct sockaddr *)&maskeddst; 843 } 844 if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL) 845 senderr(ESRCH); 846 if (ret_nrt != NULL) { 847 *ret_nrt = rt; 848 rt->rt_refcnt++; 849 } 850 break; 851 } 852 bad: 853 splx(s); 854 return error; 855 } 856 857 int 858 rt_setgate(struct rtentry *rt, const struct sockaddr *gate) 859 { 860 KASSERT(rt != rt->rt_gwroute); 861 862 KASSERT(rt->_rt_key != NULL); 863 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 864 865 if (rt->rt_gwroute) { 866 RTFREE(rt->rt_gwroute); 867 rt->rt_gwroute = NULL; 868 } 869 KASSERT(rt->_rt_key != NULL); 870 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 871 if (rt->rt_gateway != NULL) 872 sockaddr_free(rt->rt_gateway); 873 KASSERT(rt->_rt_key != NULL); 874 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 875 if ((rt->rt_gateway = sockaddr_dup(gate, M_NOWAIT)) == NULL) 876 return ENOMEM; 877 KASSERT(rt->_rt_key != NULL); 878 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 879 880 if (rt->rt_flags & RTF_GATEWAY) { 881 KASSERT(rt->_rt_key != NULL); 882 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 883 rt->rt_gwroute = rtalloc1(gate, 1); 884 /* 885 * If we switched gateways, grab the MTU from the new 886 * gateway route if the current MTU, if the current MTU is 887 * greater than the MTU of gateway. 888 * Note that, if the MTU of gateway is 0, we will reset the 889 * MTU of the route to run PMTUD again from scratch. XXX 890 */ 891 KASSERT(rt->_rt_key != NULL); 892 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 893 if (rt->rt_gwroute 894 && !(rt->rt_rmx.rmx_locks & RTV_MTU) 895 && rt->rt_rmx.rmx_mtu 896 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) { 897 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu; 898 } 899 } 900 KASSERT(rt->_rt_key != NULL); 901 RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); 902 return 0; 903 } 904 905 void 906 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst, 907 const struct sockaddr *netmask) 908 { 909 const char *netmaskp = &netmask->sa_data[0], 910 *srcp = &src->sa_data[0]; 911 char *dstp = &dst->sa_data[0]; 912 const char *maskend = (char *)dst + MIN(netmask->sa_len, src->sa_len); 913 const char *srcend = (char *)dst + src->sa_len; 914 915 dst->sa_len = src->sa_len; 916 dst->sa_family = src->sa_family; 917 918 while (dstp < maskend) 919 *dstp++ = *srcp++ & *netmaskp++; 920 if (dstp < srcend) 921 memset(dstp, 0, (size_t)(srcend - dstp)); 922 } 923 924 /* 925 * Set up or tear down a routing table entry, normally 926 * for an interface. 927 */ 928 int 929 rtinit(struct ifaddr *ifa, int cmd, int flags) 930 { 931 struct rtentry *rt; 932 struct sockaddr *dst, *odst; 933 struct sockaddr_storage maskeddst; 934 struct rtentry *nrt = NULL; 935 int error; 936 struct rt_addrinfo info; 937 struct sockaddr_dl *sdl; 938 const struct sockaddr_dl *ifsdl; 939 940 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 941 if (cmd == RTM_DELETE) { 942 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 943 /* Delete subnet route for this interface */ 944 odst = dst; 945 dst = (struct sockaddr *)&maskeddst; 946 rt_maskedcopy(odst, dst, ifa->ifa_netmask); 947 } 948 if ((rt = rtalloc1(dst, 0)) != NULL) { 949 rt->rt_refcnt--; 950 if (rt->rt_ifa != ifa) 951 return (flags & RTF_HOST) ? EHOSTUNREACH 952 : ENETUNREACH; 953 } 954 } 955 memset(&info, 0, sizeof(info)); 956 info.rti_ifa = ifa; 957 info.rti_flags = flags | ifa->ifa_flags; 958 info.rti_info[RTAX_DST] = dst; 959 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 960 /* 961 * XXX here, it seems that we are assuming that ifa_netmask is NULL 962 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate 963 * variable) when RTF_HOST is 1. still not sure if i can safely 964 * change it to meet bsdi4 behavior. 965 */ 966 if (cmd != RTM_LLINFO_UPD) 967 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 968 error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info, 969 &nrt); 970 if (error != 0 || (rt = nrt) == NULL) 971 ; 972 else switch (cmd) { 973 case RTM_DELETE: 974 rt_newaddrmsg(cmd, ifa, error, nrt); 975 if (rt->rt_refcnt <= 0) { 976 rt->rt_refcnt++; 977 rtfree(rt); 978 } 979 break; 980 case RTM_LLINFO_UPD: 981 rt->rt_refcnt--; 982 RT_DPRINTF("%s: updating%s\n", __func__, 983 ((rt->rt_flags & RTF_LLINFO) == 0) ? " (no llinfo)" : ""); 984 985 ifsdl = ifa->ifa_ifp->if_sadl; 986 987 if ((rt->rt_flags & RTF_LLINFO) != 0 && 988 (sdl = satosdl(rt->rt_gateway)) != NULL && 989 sdl->sdl_family == AF_LINK && 990 sockaddr_dl_setaddr(sdl, sdl->sdl_len, CLLADDR(ifsdl), 991 ifa->ifa_ifp->if_addrlen) == NULL) { 992 error = EINVAL; 993 break; 994 } 995 996 if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL) 997 ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info); 998 rt_newaddrmsg(RTM_CHANGE, ifa, error, nrt); 999 break; 1000 case RTM_ADD: 1001 rt->rt_refcnt--; 1002 if (rt->rt_ifa != ifa) { 1003 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 1004 rt->rt_ifa); 1005 if (rt->rt_ifa->ifa_rtrequest != NULL) { 1006 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, 1007 &info); 1008 } 1009 rt_replace_ifa(rt, ifa); 1010 rt->rt_ifp = ifa->ifa_ifp; 1011 if (ifa->ifa_rtrequest != NULL) 1012 ifa->ifa_rtrequest(RTM_ADD, rt, &info); 1013 } 1014 rt_newaddrmsg(cmd, ifa, error, nrt); 1015 break; 1016 } 1017 return error; 1018 } 1019 1020 /* 1021 * Route timer routines. These routes allow functions to be called 1022 * for various routes at any time. This is useful in supporting 1023 * path MTU discovery and redirect route deletion. 1024 * 1025 * This is similar to some BSDI internal functions, but it provides 1026 * for multiple queues for efficiency's sake... 1027 */ 1028 1029 LIST_HEAD(, rttimer_queue) rttimer_queue_head; 1030 static int rt_init_done = 0; 1031 1032 #define RTTIMER_CALLOUT(r) do { \ 1033 if (r->rtt_func != NULL) { \ 1034 (*r->rtt_func)(r->rtt_rt, r); \ 1035 } else { \ 1036 rtrequest((int) RTM_DELETE, \ 1037 rt_getkey(r->rtt_rt), \ 1038 0, 0, 0, 0); \ 1039 } \ 1040 } while (/*CONSTCOND*/0) 1041 1042 /* 1043 * Some subtle order problems with domain initialization mean that 1044 * we cannot count on this being run from rt_init before various 1045 * protocol initializations are done. Therefore, we make sure 1046 * that this is run when the first queue is added... 1047 */ 1048 1049 void 1050 rt_timer_init(void) 1051 { 1052 assert(rt_init_done == 0); 1053 1054 LIST_INIT(&rttimer_queue_head); 1055 callout_init(&rt_timer_ch, 0); 1056 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1057 rt_init_done = 1; 1058 } 1059 1060 struct rttimer_queue * 1061 rt_timer_queue_create(u_int timeout) 1062 { 1063 struct rttimer_queue *rtq; 1064 1065 if (rt_init_done == 0) 1066 rt_timer_init(); 1067 1068 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); 1069 if (rtq == NULL) 1070 return NULL; 1071 memset(rtq, 0, sizeof(*rtq)); 1072 1073 rtq->rtq_timeout = timeout; 1074 TAILQ_INIT(&rtq->rtq_head); 1075 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); 1076 1077 return rtq; 1078 } 1079 1080 void 1081 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) 1082 { 1083 1084 rtq->rtq_timeout = timeout; 1085 } 1086 1087 void 1088 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy) 1089 { 1090 struct rttimer *r; 1091 1092 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { 1093 LIST_REMOVE(r, rtt_link); 1094 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1095 if (destroy) 1096 RTTIMER_CALLOUT(r); 1097 /* we are already at splsoftnet */ 1098 pool_put(&rttimer_pool, r); 1099 if (rtq->rtq_count > 0) 1100 rtq->rtq_count--; 1101 else 1102 printf("rt_timer_queue_remove_all: " 1103 "rtq_count reached 0\n"); 1104 } 1105 } 1106 1107 void 1108 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) 1109 { 1110 1111 rt_timer_queue_remove_all(rtq, destroy); 1112 1113 LIST_REMOVE(rtq, rtq_link); 1114 1115 /* 1116 * Caller is responsible for freeing the rttimer_queue structure. 1117 */ 1118 } 1119 1120 unsigned long 1121 rt_timer_count(struct rttimer_queue *rtq) 1122 { 1123 return rtq->rtq_count; 1124 } 1125 1126 void 1127 rt_timer_remove_all(struct rtentry *rt, int destroy) 1128 { 1129 struct rttimer *r; 1130 1131 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 1132 LIST_REMOVE(r, rtt_link); 1133 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1134 if (destroy) 1135 RTTIMER_CALLOUT(r); 1136 if (r->rtt_queue->rtq_count > 0) 1137 r->rtt_queue->rtq_count--; 1138 else 1139 printf("rt_timer_remove_all: rtq_count reached 0\n"); 1140 /* we are already at splsoftnet */ 1141 pool_put(&rttimer_pool, r); 1142 } 1143 } 1144 1145 int 1146 rt_timer_add(struct rtentry *rt, 1147 void (*func)(struct rtentry *, struct rttimer *), 1148 struct rttimer_queue *queue) 1149 { 1150 struct rttimer *r; 1151 int s; 1152 1153 /* 1154 * If there's already a timer with this action, destroy it before 1155 * we add a new one. 1156 */ 1157 LIST_FOREACH(r, &rt->rt_timer, rtt_link) { 1158 if (r->rtt_func == func) 1159 break; 1160 } 1161 if (r != NULL) { 1162 LIST_REMOVE(r, rtt_link); 1163 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1164 if (r->rtt_queue->rtq_count > 0) 1165 r->rtt_queue->rtq_count--; 1166 else 1167 printf("rt_timer_add: rtq_count reached 0\n"); 1168 } else { 1169 s = splsoftnet(); 1170 r = pool_get(&rttimer_pool, PR_NOWAIT); 1171 splx(s); 1172 if (r == NULL) 1173 return ENOBUFS; 1174 } 1175 1176 memset(r, 0, sizeof(*r)); 1177 1178 r->rtt_rt = rt; 1179 r->rtt_time = time_uptime; 1180 r->rtt_func = func; 1181 r->rtt_queue = queue; 1182 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); 1183 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); 1184 r->rtt_queue->rtq_count++; 1185 1186 return 0; 1187 } 1188 1189 /* ARGSUSED */ 1190 void 1191 rt_timer_timer(void *arg) 1192 { 1193 struct rttimer_queue *rtq; 1194 struct rttimer *r; 1195 int s; 1196 1197 s = splsoftnet(); 1198 LIST_FOREACH(rtq, &rttimer_queue_head, rtq_link) { 1199 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && 1200 (r->rtt_time + rtq->rtq_timeout) < time_uptime) { 1201 LIST_REMOVE(r, rtt_link); 1202 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1203 RTTIMER_CALLOUT(r); 1204 pool_put(&rttimer_pool, r); 1205 if (rtq->rtq_count > 0) 1206 rtq->rtq_count--; 1207 else 1208 printf("rt_timer_timer: rtq_count reached 0\n"); 1209 } 1210 } 1211 splx(s); 1212 1213 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1214 } 1215 1216 static struct rtentry * 1217 _rtcache_init(struct route *ro, int flag) 1218 { 1219 rtcache_invariants(ro); 1220 KASSERT(ro->_ro_rt == NULL); 1221 1222 if (rtcache_getdst(ro) == NULL) 1223 return NULL; 1224 ro->ro_invalid = false; 1225 if ((ro->_ro_rt = rtalloc1(rtcache_getdst(ro), flag)) != NULL) 1226 rtcache(ro); 1227 1228 rtcache_invariants(ro); 1229 return ro->_ro_rt; 1230 } 1231 1232 struct rtentry * 1233 rtcache_init(struct route *ro) 1234 { 1235 return _rtcache_init(ro, 1); 1236 } 1237 1238 struct rtentry * 1239 rtcache_init_noclone(struct route *ro) 1240 { 1241 return _rtcache_init(ro, 0); 1242 } 1243 1244 struct rtentry * 1245 rtcache_update(struct route *ro, int clone) 1246 { 1247 rtcache_clear(ro); 1248 return _rtcache_init(ro, clone); 1249 } 1250 1251 void 1252 rtcache_copy(struct route *new_ro, const struct route *old_ro) 1253 { 1254 struct rtentry *rt; 1255 1256 KASSERT(new_ro != old_ro); 1257 rtcache_invariants(new_ro); 1258 rtcache_invariants(old_ro); 1259 1260 if ((rt = rtcache_validate(old_ro)) != NULL) 1261 rt->rt_refcnt++; 1262 1263 if (rtcache_getdst(old_ro) == NULL || 1264 rtcache_setdst(new_ro, rtcache_getdst(old_ro)) != 0) 1265 return; 1266 1267 new_ro->ro_invalid = false; 1268 if ((new_ro->_ro_rt = rt) != NULL) 1269 rtcache(new_ro); 1270 rtcache_invariants(new_ro); 1271 } 1272 1273 static struct dom_rtlist invalid_routes = LIST_HEAD_INITIALIZER(dom_rtlist); 1274 1275 void 1276 rtcache_invalidate(struct dom_rtlist *rtlist) 1277 { 1278 struct route *ro; 1279 1280 while ((ro = LIST_FIRST(rtlist)) != NULL) { 1281 rtcache_invariants(ro); 1282 KASSERT(ro->_ro_rt != NULL); 1283 ro->ro_invalid = true; 1284 LIST_REMOVE(ro, ro_rtcache_next); 1285 LIST_INSERT_HEAD(&invalid_routes, ro, ro_rtcache_next); 1286 rtcache_invariants(ro); 1287 } 1288 } 1289 1290 void 1291 rtcache_clear(struct route *ro) 1292 { 1293 rtcache_invariants(ro); 1294 if (ro->_ro_rt == NULL) 1295 return; 1296 1297 LIST_REMOVE(ro, ro_rtcache_next); 1298 1299 RTFREE(ro->_ro_rt); 1300 ro->_ro_rt = NULL; 1301 ro->ro_invalid = false; 1302 rtcache_invariants(ro); 1303 } 1304 1305 struct rtentry * 1306 rtcache_lookup2(struct route *ro, const struct sockaddr *dst, int clone, 1307 int *hitp) 1308 { 1309 const struct sockaddr *odst; 1310 struct rtentry *rt = NULL; 1311 1312 rtcache_invariants(ro); 1313 1314 odst = rtcache_getdst(ro); 1315 1316 if (odst == NULL) 1317 ; 1318 else if (sockaddr_cmp(odst, dst) != 0) 1319 rtcache_free(ro); 1320 else if ((rt = rtcache_validate(ro)) == NULL) 1321 rtcache_clear(ro); 1322 1323 if (rt == NULL) { 1324 *hitp = 0; 1325 if (rtcache_setdst(ro, dst) == 0) 1326 rt = _rtcache_init(ro, clone); 1327 } else 1328 *hitp = 1; 1329 1330 rtcache_invariants(ro); 1331 1332 return rt; 1333 } 1334 1335 void 1336 rtcache_free(struct route *ro) 1337 { 1338 rtcache_clear(ro); 1339 if (ro->ro_sa != NULL) { 1340 sockaddr_free(ro->ro_sa); 1341 ro->ro_sa = NULL; 1342 } 1343 rtcache_invariants(ro); 1344 } 1345 1346 int 1347 rtcache_setdst(struct route *ro, const struct sockaddr *sa) 1348 { 1349 KASSERT(sa != NULL); 1350 1351 rtcache_invariants(ro); 1352 if (ro->ro_sa != NULL && ro->ro_sa->sa_family == sa->sa_family) { 1353 rtcache_clear(ro); 1354 if (sockaddr_copy(ro->ro_sa, ro->ro_sa->sa_len, sa) != NULL) { 1355 rtcache_invariants(ro); 1356 return 0; 1357 } 1358 sockaddr_free(ro->ro_sa); 1359 } else if (ro->ro_sa != NULL) 1360 rtcache_free(ro); /* free ro_sa, wrong family */ 1361 1362 KASSERT(ro->_ro_rt == NULL); 1363 1364 if ((ro->ro_sa = sockaddr_dup(sa, M_NOWAIT)) == NULL) { 1365 rtcache_invariants(ro); 1366 return ENOMEM; 1367 } 1368 rtcache_invariants(ro); 1369 return 0; 1370 } 1371 1372 const struct sockaddr * 1373 rt_settag(struct rtentry *rt, const struct sockaddr *tag) 1374 { 1375 if (rt->rt_tag != tag) { 1376 if (rt->rt_tag != NULL) 1377 sockaddr_free(rt->rt_tag); 1378 rt->rt_tag = sockaddr_dup(tag, M_NOWAIT); 1379 } 1380 return rt->rt_tag; 1381 } 1382 1383 struct sockaddr * 1384 rt_gettag(struct rtentry *rt) 1385 { 1386 return rt->rt_tag; 1387 } 1388