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