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