1 /* $NetBSD: route.c,v 1.76 2006/11/16 01:33:40 christos 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.76 2006/11/16 01:33:40 christos Exp $"); 102 103 104 #include <sys/param.h> 105 #include <sys/systm.h> 106 #include <sys/callout.h> 107 #include <sys/proc.h> 108 #include <sys/mbuf.h> 109 #include <sys/socket.h> 110 #include <sys/socketvar.h> 111 #include <sys/domain.h> 112 #include <sys/protosw.h> 113 #include <sys/kernel.h> 114 #include <sys/ioctl.h> 115 #include <sys/pool.h> 116 117 #include <net/if.h> 118 #include <net/route.h> 119 #include <net/raw_cb.h> 120 121 #include <netinet/in.h> 122 #include <netinet/in_var.h> 123 124 125 struct route_cb route_cb; 126 struct rtstat rtstat; 127 struct radix_node_head *rt_tables[AF_MAX+1]; 128 129 int rttrash; /* routes not in table but not freed */ 130 struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ 131 132 POOL_INIT(rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", NULL); 133 POOL_INIT(rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", NULL); 134 135 struct callout rt_timer_ch; /* callout for rt_timer_timer() */ 136 137 static int rtdeletemsg(struct rtentry *); 138 static int rtflushclone1(struct radix_node *, void *); 139 static void rtflushclone(struct radix_node_head *, struct rtentry *); 140 141 void 142 rtable_init(void **table) 143 { 144 struct domain *dom; 145 DOMAIN_FOREACH(dom) 146 if (dom->dom_rtattach) 147 dom->dom_rtattach(&table[dom->dom_family], 148 dom->dom_rtoffset); 149 } 150 151 void 152 route_init(void) 153 { 154 155 rn_init(); /* initialize all zeroes, all ones, mask table */ 156 rtable_init((void **)rt_tables); 157 } 158 159 /* 160 * Packet routing routines. 161 */ 162 void 163 rtalloc(struct route *ro) 164 { 165 if (ro->ro_rt != NULL) { 166 if (ro->ro_rt->rt_ifp != NULL && 167 (ro->ro_rt->rt_flags & RTF_UP) != 0) 168 return; 169 RTFREE(ro->ro_rt); 170 } 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 const struct sockaddr *dst = info->rti_info[RTAX_DST]; 501 const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY]; 502 const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA]; 503 const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP]; 504 int flags = info->rti_flags; 505 506 /* 507 * ifp may be specified by sockaddr_dl when protocol address 508 * is ambiguous 509 */ 510 if (info->rti_ifp == NULL && ifpaddr != NULL 511 && ifpaddr->sa_family == AF_LINK && 512 (ifa = ifa_ifwithnet((const struct sockaddr *)ifpaddr)) != NULL) 513 info->rti_ifp = ifa->ifa_ifp; 514 if (info->rti_ifa == NULL && ifaaddr != NULL) 515 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 516 if (info->rti_ifa == NULL) { 517 const struct sockaddr *sa; 518 519 sa = ifaaddr != NULL ? ifaaddr : 520 (gateway != NULL ? gateway : dst); 521 if (sa != NULL && info->rti_ifp != NULL) 522 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 523 else if (dst != NULL && gateway != NULL) 524 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway); 525 else if (sa != NULL) 526 info->rti_ifa = ifa_ifwithroute(flags, sa, sa); 527 } 528 if ((ifa = info->rti_ifa) == NULL) 529 return ENETUNREACH; 530 if (ifa->ifa_getifa != NULL) 531 info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst); 532 if (info->rti_ifp == NULL) 533 info->rti_ifp = ifa->ifa_ifp; 534 return 0; 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 /* Already at splsoftnet() so pool_get/pool_put are safe */ 615 rt = pool_get(&rtentry_pool, PR_NOWAIT); 616 if (rt == NULL) 617 senderr(ENOBUFS); 618 Bzero(rt, sizeof(*rt)); 619 rt->rt_flags = RTF_UP | flags; 620 LIST_INIT(&rt->rt_timer); 621 if (rt_setgate(rt, dst, gateway)) { 622 pool_put(&rtentry_pool, rt); 623 senderr(ENOBUFS); 624 } 625 ndst = rt_key(rt); 626 if (netmask) { 627 rt_maskedcopy(dst, ndst, netmask); 628 } else 629 Bcopy(dst, ndst, dst->sa_len); 630 rt_set_ifa(rt, 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 rt_replace_ifa(rt, ifa); 798 rt->rt_ifp = ifa->ifa_ifp; 799 if (ifa->ifa_rtrequest) 800 ifa->ifa_rtrequest(RTM_ADD, rt, NULL); 801 } 802 rt_newaddrmsg(cmd, ifa, error, nrt); 803 } 804 return (error); 805 } 806 807 /* 808 * Route timer routines. These routes allow functions to be called 809 * for various routes at any time. This is useful in supporting 810 * path MTU discovery and redirect route deletion. 811 * 812 * This is similar to some BSDI internal functions, but it provides 813 * for multiple queues for efficiency's sake... 814 */ 815 816 LIST_HEAD(, rttimer_queue) rttimer_queue_head; 817 static int rt_init_done = 0; 818 819 #define RTTIMER_CALLOUT(r) do { \ 820 if (r->rtt_func != NULL) { \ 821 (*r->rtt_func)(r->rtt_rt, r); \ 822 } else { \ 823 rtrequest((int) RTM_DELETE, \ 824 (struct sockaddr *)rt_key(r->rtt_rt), \ 825 0, 0, 0, 0); \ 826 } \ 827 } while (/*CONSTCOND*/0) 828 829 /* 830 * Some subtle order problems with domain initialization mean that 831 * we cannot count on this being run from rt_init before various 832 * protocol initializations are done. Therefore, we make sure 833 * that this is run when the first queue is added... 834 */ 835 836 void 837 rt_timer_init(void) 838 { 839 assert(rt_init_done == 0); 840 841 LIST_INIT(&rttimer_queue_head); 842 callout_init(&rt_timer_ch); 843 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 844 rt_init_done = 1; 845 } 846 847 struct rttimer_queue * 848 rt_timer_queue_create(u_int timeout) 849 { 850 struct rttimer_queue *rtq; 851 852 if (rt_init_done == 0) 853 rt_timer_init(); 854 855 R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq); 856 if (rtq == NULL) 857 return (NULL); 858 Bzero(rtq, sizeof *rtq); 859 860 rtq->rtq_timeout = timeout; 861 rtq->rtq_count = 0; 862 TAILQ_INIT(&rtq->rtq_head); 863 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); 864 865 return (rtq); 866 } 867 868 void 869 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) 870 { 871 872 rtq->rtq_timeout = timeout; 873 } 874 875 void 876 rt_timer_queue_remove_all(struct rttimer_queue *rtq, int destroy) 877 { 878 struct rttimer *r; 879 880 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { 881 LIST_REMOVE(r, rtt_link); 882 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 883 if (destroy) 884 RTTIMER_CALLOUT(r); 885 /* we are already at splsoftnet */ 886 pool_put(&rttimer_pool, r); 887 if (rtq->rtq_count > 0) 888 rtq->rtq_count--; 889 else 890 printf("rt_timer_queue_remove_all: " 891 "rtq_count reached 0\n"); 892 } 893 } 894 895 void 896 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) 897 { 898 899 rt_timer_queue_remove_all(rtq, destroy); 900 901 LIST_REMOVE(rtq, rtq_link); 902 903 /* 904 * Caller is responsible for freeing the rttimer_queue structure. 905 */ 906 } 907 908 unsigned long 909 rt_timer_count(struct rttimer_queue *rtq) 910 { 911 return rtq->rtq_count; 912 } 913 914 void 915 rt_timer_remove_all(struct rtentry *rt, int destroy) 916 { 917 struct rttimer *r; 918 919 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 920 LIST_REMOVE(r, rtt_link); 921 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 922 if (destroy) 923 RTTIMER_CALLOUT(r); 924 if (r->rtt_queue->rtq_count > 0) 925 r->rtt_queue->rtq_count--; 926 else 927 printf("rt_timer_remove_all: rtq_count reached 0\n"); 928 /* we are already at splsoftnet */ 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 int s; 940 941 /* 942 * If there's already a timer with this action, destroy it before 943 * we add a new one. 944 */ 945 for (r = LIST_FIRST(&rt->rt_timer); r != NULL; 946 r = LIST_NEXT(r, rtt_link)) { 947 if (r->rtt_func == func) { 948 LIST_REMOVE(r, rtt_link); 949 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 950 if (r->rtt_queue->rtq_count > 0) 951 r->rtt_queue->rtq_count--; 952 else 953 printf("rt_timer_add: rtq_count reached 0\n"); 954 s = splsoftnet(); 955 pool_put(&rttimer_pool, r); 956 splx(s); 957 break; /* only one per list, so we can quit... */ 958 } 959 } 960 961 s = splsoftnet(); 962 r = pool_get(&rttimer_pool, PR_NOWAIT); 963 splx(s); 964 if (r == NULL) 965 return (ENOBUFS); 966 Bzero(r, sizeof(*r)); 967 968 r->rtt_rt = rt; 969 r->rtt_time = time_uptime; 970 r->rtt_func = func; 971 r->rtt_queue = queue; 972 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); 973 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); 974 r->rtt_queue->rtq_count++; 975 976 return (0); 977 } 978 979 /* ARGSUSED */ 980 void 981 rt_timer_timer(void *arg) 982 { 983 struct rttimer_queue *rtq; 984 struct rttimer *r; 985 int s; 986 987 s = splsoftnet(); 988 for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; 989 rtq = LIST_NEXT(rtq, rtq_link)) { 990 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && 991 (r->rtt_time + rtq->rtq_timeout) < time_uptime) { 992 LIST_REMOVE(r, rtt_link); 993 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 994 RTTIMER_CALLOUT(r); 995 pool_put(&rttimer_pool, r); 996 if (rtq->rtq_count > 0) 997 rtq->rtq_count--; 998 else 999 printf("rt_timer_timer: rtq_count reached 0\n"); 1000 } 1001 } 1002 splx(s); 1003 1004 callout_reset(&rt_timer_ch, hz, rt_timer_timer, NULL); 1005 } 1006