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