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