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