1 /* $NetBSD: route.c,v 1.70 2006/06/07 22:33:43 kardel Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 42 * All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the project nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 */ 68 69 /* 70 * Copyright (c) 1980, 1986, 1991, 1993 71 * The Regents of the University of California. All rights reserved. 72 * 73 * Redistribution and use in source and binary forms, with or without 74 * modification, are permitted provided that the following conditions 75 * are met: 76 * 1. Redistributions of source code must retain the above copyright 77 * notice, this list of conditions and the following disclaimer. 78 * 2. Redistributions in binary form must reproduce the above copyright 79 * notice, this list of conditions and the following disclaimer in the 80 * documentation and/or other materials provided with the distribution. 81 * 3. Neither the name of the University nor the names of its contributors 82 * may be used to endorse or promote products derived from this software 83 * without specific prior written permission. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 * SUCH DAMAGE. 96 * 97 * @(#)route.c 8.3 (Berkeley) 1/9/95 98 */ 99 100 #include <sys/cdefs.h> 101 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.70 2006/06/07 22:33:43 kardel Exp $"); 102 103 #include "opt_ns.h" 104 105 #include <sys/param.h> 106 #include <sys/systm.h> 107 #include <sys/callout.h> 108 #include <sys/proc.h> 109 #include <sys/mbuf.h> 110 #include <sys/socket.h> 111 #include <sys/socketvar.h> 112 #include <sys/domain.h> 113 #include <sys/protosw.h> 114 #include <sys/kernel.h> 115 #include <sys/ioctl.h> 116 #include <sys/pool.h> 117 118 #include <net/if.h> 119 #include <net/route.h> 120 #include <net/raw_cb.h> 121 122 #include <netinet/in.h> 123 #include <netinet/in_var.h> 124 125 #ifdef NS 126 #include <netns/ns.h> 127 #endif 128 129 struct route_cb route_cb; 130 struct rtstat rtstat; 131 struct radix_node_head *rt_tables[AF_MAX+1]; 132 133 int rttrash; /* routes not in table but not freed */ 134 struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ 135 136 POOL_INIT(rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", NULL); 137 POOL_INIT(rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", NULL); 138 139 struct callout rt_timer_ch; /* callout for rt_timer_timer() */ 140 141 static int rtdeletemsg(struct rtentry *); 142 static int rtflushclone1(struct radix_node *, void *); 143 static void rtflushclone(struct radix_node_head *, struct rtentry *); 144 145 void 146 rtable_init(void **table) 147 { 148 struct domain *dom; 149 DOMAIN_FOREACH(dom) 150 if (dom->dom_rtattach) 151 dom->dom_rtattach(&table[dom->dom_family], 152 dom->dom_rtoffset); 153 } 154 155 void 156 route_init(void) 157 { 158 159 rn_init(); /* initialize all zeroes, all ones, mask table */ 160 rtable_init((void **)rt_tables); 161 } 162 163 /* 164 * Packet routing routines. 165 */ 166 void 167 rtalloc(struct route *ro) 168 { 169 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 170 return; /* XXX */ 171 ro->ro_rt = rtalloc1(&ro->ro_dst, 1); 172 } 173 174 struct rtentry * 175 rtalloc1(const struct sockaddr *dst, int report) 176 { 177 struct radix_node_head *rnh = rt_tables[dst->sa_family]; 178 struct rtentry *rt; 179 struct radix_node *rn; 180 struct rtentry *newrt = NULL; 181 struct rt_addrinfo info; 182 int s = splsoftnet(), err = 0, msgtype = RTM_MISS; 183 184 if (rnh && (rn = rnh->rnh_matchaddr(dst, rnh)) && 185 ((rn->rn_flags & RNF_ROOT) == 0)) { 186 newrt = rt = (struct rtentry *)rn; 187 if (report && (rt->rt_flags & RTF_CLONING)) { 188 err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0, 189 &newrt); 190 if (err) { 191 newrt = rt; 192 rt->rt_refcnt++; 193 goto miss; 194 } 195 KASSERT(newrt != NULL); 196 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 197 msgtype = RTM_RESOLVE; 198 goto miss; 199 } 200 /* Inform listeners of the new route */ 201 memset(&info, 0, sizeof(info)); 202 info.rti_info[RTAX_DST] = rt_key(rt); 203 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 204 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 205 if (rt->rt_ifp != NULL) { 206 info.rti_info[RTAX_IFP] = 207 TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr; 208 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 209 } 210 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 0); 211 } else 212 rt->rt_refcnt++; 213 } else { 214 rtstat.rts_unreach++; 215 miss: if (report) { 216 memset((caddr_t)&info, 0, sizeof(info)); 217 info.rti_info[RTAX_DST] = dst; 218 rt_missmsg(msgtype, &info, 0, err); 219 } 220 } 221 splx(s); 222 return (newrt); 223 } 224 225 void 226 rtfree(struct rtentry *rt) 227 { 228 struct ifaddr *ifa; 229 230 if (rt == NULL) 231 panic("rtfree"); 232 rt->rt_refcnt--; 233 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 234 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 235 panic ("rtfree 2"); 236 rttrash--; 237 if (rt->rt_refcnt < 0) { 238 printf("rtfree: %p not freed (neg refs)\n", rt); 239 return; 240 } 241 rt_timer_remove_all(rt, 0); 242 ifa = rt->rt_ifa; 243 IFAFREE(ifa); 244 Free(rt_key(rt)); 245 pool_put(&rtentry_pool, rt); 246 } 247 } 248 249 void 250 ifafree(struct ifaddr *ifa) 251 { 252 253 #ifdef DIAGNOSTIC 254 if (ifa == NULL) 255 panic("ifafree: null ifa"); 256 if (ifa->ifa_refcnt != 0) 257 panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt); 258 #endif 259 #ifdef IFAREF_DEBUG 260 printf("ifafree: freeing ifaddr %p\n", ifa); 261 #endif 262 free(ifa, M_IFADDR); 263 } 264 265 /* 266 * Force a routing table entry to the specified 267 * destination to go through the given gateway. 268 * Normally called as a result of a routing redirect 269 * message from the network layer. 270 * 271 * N.B.: must be called at splsoftnet 272 */ 273 void 274 rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway, 275 const struct sockaddr *netmask, int flags, const struct sockaddr *src, 276 struct rtentry **rtp) 277 { 278 struct rtentry *rt; 279 int error = 0; 280 u_quad_t *stat = NULL; 281 struct rt_addrinfo info; 282 struct ifaddr *ifa; 283 284 /* verify the gateway is directly reachable */ 285 if ((ifa = ifa_ifwithnet(gateway)) == NULL) { 286 error = ENETUNREACH; 287 goto out; 288 } 289 rt = rtalloc1(dst, 0); 290 /* 291 * If the redirect isn't from our current router for this dst, 292 * it's either old or wrong. If it redirects us to ourselves, 293 * we have a routing loop, perhaps as a result of an interface 294 * going down recently. 295 */ 296 #define equal(a1, a2) \ 297 ((a1)->sa_len == (a2)->sa_len && \ 298 memcmp((a1), (a2), (a1)->sa_len) == 0) 299 if (!(flags & RTF_DONE) && rt && 300 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 301 error = EINVAL; 302 else if (ifa_ifwithaddr(gateway)) 303 error = EHOSTUNREACH; 304 if (error) 305 goto done; 306 /* 307 * Create a new entry if we just got back a wildcard entry 308 * or the lookup failed. This is necessary for hosts 309 * which use routing redirects generated by smart gateways 310 * to dynamically build the routing tables. 311 */ 312 if ((rt == NULL) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 313 goto create; 314 /* 315 * Don't listen to the redirect if it's 316 * for a route to an interface. 317 */ 318 if (rt->rt_flags & RTF_GATEWAY) { 319 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 320 /* 321 * Changing from route to net => route to host. 322 * Create new route, rather than smashing route to net. 323 */ 324 create: 325 if (rt) 326 rtfree(rt); 327 flags |= RTF_GATEWAY | RTF_DYNAMIC; 328 info.rti_info[RTAX_DST] = dst; 329 info.rti_info[RTAX_GATEWAY] = gateway; 330 info.rti_info[RTAX_NETMASK] = netmask; 331 info.rti_ifa = ifa; 332 info.rti_flags = flags; 333 rt = NULL; 334 error = rtrequest1(RTM_ADD, &info, &rt); 335 if (rt != NULL) 336 flags = rt->rt_flags; 337 stat = &rtstat.rts_dynamic; 338 } else { 339 /* 340 * Smash the current notion of the gateway to 341 * this destination. Should check about netmask!!! 342 */ 343 rt->rt_flags |= RTF_MODIFIED; 344 flags |= RTF_MODIFIED; 345 stat = &rtstat.rts_newgateway; 346 rt_setgate(rt, rt_key(rt), gateway); 347 } 348 } else 349 error = EHOSTUNREACH; 350 done: 351 if (rt) { 352 if (rtp && !error) 353 *rtp = rt; 354 else 355 rtfree(rt); 356 } 357 out: 358 if (error) 359 rtstat.rts_badredirect++; 360 else if (stat != NULL) 361 (*stat)++; 362 memset((caddr_t)&info, 0, sizeof(info)); 363 info.rti_info[RTAX_DST] = dst; 364 info.rti_info[RTAX_GATEWAY] = gateway; 365 info.rti_info[RTAX_NETMASK] = netmask; 366 info.rti_info[RTAX_AUTHOR] = src; 367 rt_missmsg(RTM_REDIRECT, &info, flags, error); 368 } 369 370 /* 371 * Delete a route and generate a message 372 */ 373 static int 374 rtdeletemsg(struct rtentry *rt) 375 { 376 int error; 377 struct rt_addrinfo info; 378 379 /* 380 * Request the new route so that the entry is not actually 381 * deleted. That will allow the information being reported to 382 * be accurate (and consistent with route_output()). 383 */ 384 memset((caddr_t)&info, 0, sizeof(info)); 385 info.rti_info[RTAX_DST] = rt_key(rt); 386 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 387 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 388 info.rti_flags = rt->rt_flags; 389 error = rtrequest1(RTM_DELETE, &info, &rt); 390 391 rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); 392 393 /* Adjust the refcount */ 394 if (error == 0 && rt->rt_refcnt <= 0) { 395 rt->rt_refcnt++; 396 rtfree(rt); 397 } 398 return (error); 399 } 400 401 static int 402 rtflushclone1(struct radix_node *rn, void *arg) 403 { 404 struct rtentry *rt, *parent; 405 406 rt = (struct rtentry *)rn; 407 parent = (struct rtentry *)arg; 408 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) 409 rtdeletemsg(rt); 410 return 0; 411 } 412 413 static void 414 rtflushclone(struct radix_node_head *rnh, struct rtentry *parent) 415 { 416 417 #ifdef DIAGNOSTIC 418 if (!parent || (parent->rt_flags & RTF_CLONING) == 0) 419 panic("rtflushclone: called with a non-cloning route"); 420 if (!rnh->rnh_walktree) 421 panic("rtflushclone: no rnh_walktree"); 422 #endif 423 rnh->rnh_walktree(rnh, rtflushclone1, (void *)parent); 424 } 425 426 /* 427 * Routing table ioctl interface. 428 */ 429 int 430 rtioctl(u_long req, caddr_t data, struct lwp *l) 431 { 432 return (EOPNOTSUPP); 433 } 434 435 struct ifaddr * 436 ifa_ifwithroute(int flags, const struct sockaddr *dst, 437 const struct sockaddr *gateway) 438 { 439 struct ifaddr *ifa; 440 if ((flags & RTF_GATEWAY) == 0) { 441 /* 442 * If we are adding a route to an interface, 443 * and the interface is a pt to pt link 444 * we should search for the destination 445 * as our clue to the interface. Otherwise 446 * we can use the local address. 447 */ 448 ifa = NULL; 449 if (flags & RTF_HOST) 450 ifa = ifa_ifwithdstaddr(dst); 451 if (ifa == NULL) 452 ifa = ifa_ifwithaddr(gateway); 453 } else { 454 /* 455 * If we are adding a route to a remote net 456 * or host, the gateway may still be on the 457 * other end of a pt to pt link. 458 */ 459 ifa = ifa_ifwithdstaddr(gateway); 460 } 461 if (ifa == NULL) 462 ifa = ifa_ifwithnet(gateway); 463 if (ifa == NULL) { 464 struct rtentry *rt = rtalloc1(dst, 0); 465 if (rt == NULL) 466 return NULL; 467 rt->rt_refcnt--; 468 if ((ifa = rt->rt_ifa) == NULL) 469 return NULL; 470 } 471 if (ifa->ifa_addr->sa_family != dst->sa_family) { 472 struct ifaddr *oifa = ifa; 473 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 474 if (ifa == 0) 475 ifa = oifa; 476 } 477 return (ifa); 478 } 479 480 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 481 482 int 483 rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway, 484 const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) 485 { 486 struct rt_addrinfo info; 487 488 memset(&info, 0, sizeof(info)); 489 info.rti_flags = flags; 490 info.rti_info[RTAX_DST] = dst; 491 info.rti_info[RTAX_GATEWAY] = gateway; 492 info.rti_info[RTAX_NETMASK] = netmask; 493 return rtrequest1(req, &info, ret_nrt); 494 } 495 496 int 497 rt_getifa(struct rt_addrinfo *info) 498 { 499 struct ifaddr *ifa; 500 int error = 0; 501 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 502 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 503 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA]; 504 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP]; 505 int flags = info->rti_flags; 506 507 /* 508 * ifp may be specified by sockaddr_dl when protocol address 509 * is ambiguous 510 */ 511 if (info->rti_ifp == NULL && ifpaddr != NULL 512 && ifpaddr->sa_family == AF_LINK && 513 (ifa = ifa_ifwithnet((const struct sockaddr *)ifpaddr)) != NULL) 514 info->rti_ifp = ifa->ifa_ifp; 515 if (info->rti_ifa == NULL && ifaaddr != NULL) 516 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 517 if (info->rti_ifa == NULL) { 518 const struct sockaddr *sa; 519 520 sa = ifaaddr != NULL ? ifaaddr : 521 (gateway != NULL ? gateway : dst); 522 if (sa != NULL && info->rti_ifp != NULL) 523 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 524 else if (dst != NULL && gateway != NULL) 525 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 526 else if (sa != NULL) 527 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 528 } 529 if ((ifa = info->rti_ifa) != NULL) { 530 if (info->rti_ifp == NULL) 531 info->rti_ifp = ifa->ifa_ifp; 532 } else 533 error = ENETUNREACH; 534 return (error); 535 } 536 537 int 538 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) 539 { 540 int s = splsoftnet(); 541 int error = 0; 542 struct rtentry *rt, *crt; 543 struct radix_node *rn; 544 struct radix_node_head *rnh; 545 struct ifaddr *ifa; 546 struct sockaddr *ndst; 547 struct sockaddr_storage deldst; 548 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 549 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 550 const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK]; 551 int flags = info->rti_flags; 552 #define senderr(x) { error = x ; goto bad; } 553 554 if ((rnh = rt_tables[dst->sa_family]) == NULL) 555 senderr(ESRCH); 556 if (flags & RTF_HOST) 557 netmask = NULL; 558 switch (req) { 559 case RTM_DELETE: 560 if (netmask) { 561 rt_maskedcopy(dst, (struct sockaddr *)&deldst, netmask); 562 dst = (struct sockaddr *)&deldst; 563 } 564 if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL) 565 senderr(ESRCH); 566 rt = (struct rtentry *)rn; 567 if ((rt->rt_flags & RTF_CLONING) != 0) { 568 /* clean up any cloned children */ 569 rtflushclone(rnh, rt); 570 } 571 if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL) 572 senderr(ESRCH); 573 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 574 panic ("rtrequest delete"); 575 rt = (struct rtentry *)rn; 576 if (rt->rt_gwroute) { 577 RTFREE(rt->rt_gwroute); 578 rt->rt_gwroute = NULL; 579 } 580 if (rt->rt_parent) { 581 rt->rt_parent->rt_refcnt--; 582 rt->rt_parent = NULL; 583 } 584 rt->rt_flags &= ~RTF_UP; 585 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 586 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 587 rttrash++; 588 if (ret_nrt) 589 *ret_nrt = rt; 590 else if (rt->rt_refcnt <= 0) { 591 rt->rt_refcnt++; 592 rtfree(rt); 593 } 594 break; 595 596 case RTM_RESOLVE: 597 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) 598 senderr(EINVAL); 599 if ((rt->rt_flags & RTF_CLONING) == 0) 600 senderr(EINVAL); 601 ifa = rt->rt_ifa; 602 flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); 603 flags |= RTF_CLONED; 604 gateway = rt->rt_gateway; 605 if ((netmask = rt->rt_genmask) == NULL) 606 flags |= RTF_HOST; 607 goto makeroute; 608 609 case RTM_ADD: 610 if (info->rti_ifa == NULL && (error = rt_getifa(info))) 611 senderr(error); 612 ifa = info->rti_ifa; 613 makeroute: 614 rt = pool_get(&rtentry_pool, PR_NOWAIT); 615 if (rt == NULL) 616 senderr(ENOBUFS); 617 Bzero(rt, sizeof(*rt)); 618 rt->rt_flags = RTF_UP | flags; 619 LIST_INIT(&rt->rt_timer); 620 if (rt_setgate(rt, dst, gateway)) { 621 pool_put(&rtentry_pool, rt); 622 senderr(ENOBUFS); 623 } 624 ndst = rt_key(rt); 625 if (netmask) { 626 rt_maskedcopy(dst, ndst, netmask); 627 } else 628 Bcopy(dst, ndst, dst->sa_len); 629 IFAREF(ifa); 630 rt->rt_ifa = ifa; 631 rt->rt_ifp = ifa->ifa_ifp; 632 if (req == RTM_RESOLVE) { 633 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 634 rt->rt_parent = *ret_nrt; 635 rt->rt_parent->rt_refcnt++; 636 } 637 rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes); 638 if (rn == NULL && (crt = rtalloc1(ndst, 0)) != NULL) { 639 /* overwrite cloned route */ 640 if ((crt->rt_flags & RTF_CLONED) != 0) { 641 rtdeletemsg(crt); 642 rn = rnh->rnh_addaddr(ndst, 643 netmask, rnh, rt->rt_nodes); 644 } 645 RTFREE(crt); 646 } 647 if (rn == NULL) { 648 IFAFREE(ifa); 649 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent) 650 rtfree(rt->rt_parent); 651 if (rt->rt_gwroute) 652 rtfree(rt->rt_gwroute); 653 Free(rt_key(rt)); 654 pool_put(&rtentry_pool, rt); 655 senderr(EEXIST); 656 } 657 if (ifa->ifa_rtrequest) 658 ifa->ifa_rtrequest(req, rt, info); 659 if (ret_nrt) { 660 *ret_nrt = rt; 661 rt->rt_refcnt++; 662 } 663 if ((rt->rt_flags & RTF_CLONING) != 0) { 664 /* clean up any cloned children */ 665 rtflushclone(rnh, rt); 666 } 667 break; 668 } 669 bad: 670 splx(s); 671 return (error); 672 } 673 674 int 675 rt_setgate( struct rtentry *rt0, const struct sockaddr *dst, 676 const struct sockaddr *gate) 677 { 678 char *new, *old; 679 u_int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 680 struct rtentry *rt = rt0; 681 682 if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 683 old = (caddr_t)rt_key(rt); 684 R_Malloc(new, caddr_t, dlen + glen); 685 if (new == NULL) 686 return 1; 687 Bzero(new, dlen + glen); 688 rt->rt_nodes->rn_key = new; 689 } else { 690 new = __UNCONST(rt->rt_nodes->rn_key); /*XXXUNCONST*/ 691 old = NULL; 692 } 693 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 694 if (old) { 695 Bcopy(dst, new, dlen); 696 Free(old); 697 } 698 if (rt->rt_gwroute) { 699 RTFREE(rt->rt_gwroute); 700 rt->rt_gwroute = NULL; 701 } 702 if (rt->rt_flags & RTF_GATEWAY) { 703 rt->rt_gwroute = rtalloc1(gate, 1); 704 /* 705 * If we switched gateways, grab the MTU from the new 706 * gateway route if the current MTU, if the current MTU is 707 * greater than the MTU of gateway. 708 * Note that, if the MTU of gateway is 0, we will reset the 709 * MTU of the route to run PMTUD again from scratch. XXX 710 */ 711 if (rt->rt_gwroute 712 && !(rt->rt_rmx.rmx_locks & RTV_MTU) 713 && rt->rt_rmx.rmx_mtu 714 && rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) { 715 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu; 716 } 717 } 718 return 0; 719 } 720 721 void 722 rt_maskedcopy(const struct sockaddr *src, struct sockaddr *dst, 723 const struct sockaddr *netmask) 724 { 725 const u_char *cp1 = (const u_char *)src; 726 u_char *cp2 = (u_char *)dst; 727 const u_char *cp3 = (const u_char *)netmask; 728 u_char *cplim = cp2 + *cp3; 729 u_char *cplim2 = cp2 + *cp1; 730 731 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 732 cp3 += 2; 733 if (cplim > cplim2) 734 cplim = cplim2; 735 while (cp2 < cplim) 736 *cp2++ = *cp1++ & *cp3++; 737 if (cp2 < cplim2) 738 memset(cp2, 0, (unsigned)(cplim2 - cp2)); 739 } 740 741 /* 742 * Set up or tear down a routing table entry, normally 743 * for an interface. 744 */ 745 int 746 rtinit(struct ifaddr *ifa, int cmd, int flags) 747 { 748 struct rtentry *rt; 749 struct sockaddr *dst, *odst; 750 struct sockaddr_storage deldst; 751 struct rtentry *nrt = NULL; 752 int error; 753 struct rt_addrinfo info; 754 755 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 756 if (cmd == RTM_DELETE) { 757 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 758 /* Delete subnet route for this interface */ 759 odst = dst; 760 dst = (struct sockaddr *)&deldst; 761 rt_maskedcopy(odst, dst, ifa->ifa_netmask); 762 } 763 if ((rt = rtalloc1(dst, 0)) != NULL) { 764 rt->rt_refcnt--; 765 if (rt->rt_ifa != ifa) 766 return (flags & RTF_HOST ? EHOSTUNREACH 767 : ENETUNREACH); 768 } 769 } 770 memset(&info, 0, sizeof(info)); 771 info.rti_ifa = ifa; 772 info.rti_flags = flags | ifa->ifa_flags; 773 info.rti_info[RTAX_DST] = dst; 774 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 775 /* 776 * XXX here, it seems that we are assuming that ifa_netmask is NULL 777 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate 778 * variable) when RTF_HOST is 1. still not sure if i can safely 779 * change it to meet bsdi4 behavior. 780 */ 781 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 782 error = rtrequest1(cmd, &info, &nrt); 783 if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) { 784 rt_newaddrmsg(cmd, ifa, error, nrt); 785 if (rt->rt_refcnt <= 0) { 786 rt->rt_refcnt++; 787 rtfree(rt); 788 } 789 } 790 if (cmd == RTM_ADD && error == 0 && (rt = nrt)) { 791 rt->rt_refcnt--; 792 if (rt->rt_ifa != ifa) { 793 printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, 794 rt->rt_ifa); 795 if (rt->rt_ifa->ifa_rtrequest) 796 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, NULL); 797 IFAFREE(rt->rt_ifa); 798 rt->rt_ifa = ifa; 799 rt->rt_ifp = ifa->ifa_ifp; 800 IFAREF(ifa); 801 if (ifa->ifa_rtrequest) 802 ifa->ifa_rtrequest(RTM_ADD, rt, NULL); 803 } 804 rt_newaddrmsg(cmd, ifa, error, nrt); 805 } 806 return (error); 807 } 808 809 /* 810 * Route timer routines. These routes allow functions to be called 811 * for various routes at any time. This is useful in supporting 812 * path MTU discovery and redirect route deletion. 813 * 814 * This is similar to some BSDI internal functions, but it provides 815 * for multiple queues for efficiency's sake... 816 */ 817 818 LIST_HEAD(, rttimer_queue) rttimer_queue_head; 819 static int rt_init_done = 0; 820 821 #define RTTIMER_CALLOUT(r) do { \ 822 if (r->rtt_func != NULL) { \ 823 (*r->rtt_func)(r->rtt_rt, r); \ 824 } else { \ 825 rtrequest((int) RTM_DELETE, \ 826 (struct sockaddr *)rt_key(r->rtt_rt), \ 827 0, 0, 0, 0); \ 828 } \ 829 } while (/*CONSTCOND*/0) 830 831 /* 832 * Some subtle order problems with domain initialization mean that 833 * we cannot count on this being run from rt_init before various 834 * protocol initializations are done. Therefore, we make sure 835 * that this is run when the first queue is added... 836 */ 837 838 void 839 rt_timer_init(void) 840 { 841 assert(rt_init_done == 0); 842 843 LIST_INIT(&rttimer_queue_head); 844 callout_init(&rt_timer_ch); 845 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 846 rt_init_done = 1; 847 } 848 849 struct rttimer_queue * 850 rt_timer_queue_create(u_int timeout) 851 { 852 struct rttimer_queue *rtq; 853 854 if (rt_init_done == 0) 855 rt_timer_init(); 856 857 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); 858 if (rtq == NULL) 859 return (NULL); 860 Bzero(rtq, sizeof *rtq); 861 862 rtq->rtq_timeout = timeout; 863 rtq->rtq_count = 0; 864 TAILQ_INIT(&rtq->rtq_head); 865 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); 866 867 return (rtq); 868 } 869 870 void 871 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) 872 { 873 874 rtq->rtq_timeout = timeout; 875 } 876 877 void 878 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy) 879 { 880 struct rttimer *r; 881 882 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { 883 LIST_REMOVE(r, rtt_link); 884 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 885 if (destroy) 886 RTTIMER_CALLOUT(r); 887 pool_put(&rttimer_pool, r); 888 if (rtq->rtq_count > 0) 889 rtq->rtq_count--; 890 else 891 printf("rt_timer_queue_remove_all: " 892 "rtq_count reached 0\n"); 893 } 894 } 895 896 void 897 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) 898 { 899 900 rt_timer_queue_remove_all(rtq, destroy); 901 902 LIST_REMOVE(rtq, rtq_link); 903 904 /* 905 * Caller is responsible for freeing the rttimer_queue structure. 906 */ 907 } 908 909 unsigned long 910 rt_timer_count(struct rttimer_queue *rtq) 911 { 912 return rtq->rtq_count; 913 } 914 915 void 916 rt_timer_remove_all(struct rtentry *rt, int destroy) 917 { 918 struct rttimer *r; 919 920 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 921 LIST_REMOVE(r, rtt_link); 922 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 923 if (destroy) 924 RTTIMER_CALLOUT(r); 925 if (r->rtt_queue->rtq_count > 0) 926 r->rtt_queue->rtq_count--; 927 else 928 printf("rt_timer_remove_all: rtq_count reached 0\n"); 929 pool_put(&rttimer_pool, r); 930 } 931 } 932 933 int 934 rt_timer_add(struct rtentry *rt, 935 void (*func)(struct rtentry *, struct rttimer *), 936 struct rttimer_queue *queue) 937 { 938 struct rttimer *r; 939 940 /* 941 * If there's already a timer with this action, destroy it before 942 * we add a new one. 943 */ 944 for (r = LIST_FIRST(&rt->rt_timer); r != NULL; 945 r = LIST_NEXT(r, rtt_link)) { 946 if (r->rtt_func == func) { 947 LIST_REMOVE(r, rtt_link); 948 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 949 if (r->rtt_queue->rtq_count > 0) 950 r->rtt_queue->rtq_count--; 951 else 952 printf("rt_timer_add: rtq_count reached 0\n"); 953 pool_put(&rttimer_pool, r); 954 break; /* only one per list, so we can quit... */ 955 } 956 } 957 958 r = pool_get(&rttimer_pool, PR_NOWAIT); 959 if (r == NULL) 960 return (ENOBUFS); 961 Bzero(r, sizeof(*r)); 962 963 r->rtt_rt = rt; 964 r->rtt_time = time_uptime; 965 r->rtt_func = func; 966 r->rtt_queue = queue; 967 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); 968 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); 969 r->rtt_queue->rtq_count++; 970 971 return (0); 972 } 973 974 /* ARGSUSED */ 975 void 976 rt_timer_timer(void *arg) 977 { 978 struct rttimer_queue *rtq; 979 struct rttimer *r; 980 int s; 981 982 s = splsoftnet(); 983 for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; 984 rtq = LIST_NEXT(rtq, rtq_link)) { 985 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && 986 (r->rtt_time + rtq->rtq_timeout) < time_uptime) { 987 LIST_REMOVE(r, rtt_link); 988 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 989 RTTIMER_CALLOUT(r); 990 pool_put(&rttimer_pool, r); 991 if (rtq->rtq_count > 0) 992 rtq->rtq_count--; 993 else 994 printf("rt_timer_timer: rtq_count reached 0\n"); 995 } 996 } 997 splx(s); 998 999 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1000 } 1001