1 /* $OpenBSD: route.c,v 1.136 2012/05/09 06:50:55 markus Exp $ */ 2 /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1980, 1986, 1991, 1993 35 * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 * @(#)route.c 8.2 (Berkeley) 11/15/93 62 */ 63 64 /* 65 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 66 * 67 * NRL grants permission for redistribution and use in source and binary 68 * forms, with or without modification, of the software and documentation 69 * created at NRL provided that the following conditions are met: 70 * 71 * 1. Redistributions of source code must retain the above copyright 72 * notice, this list of conditions and the following disclaimer. 73 * 2. Redistributions in binary form must reproduce the above copyright 74 * notice, this list of conditions and the following disclaimer in the 75 * documentation and/or other materials provided with the distribution. 76 * 3. All advertising materials mentioning features or use of this software 77 * must display the following acknowledgements: 78 * This product includes software developed by the University of 79 * California, Berkeley and its contributors. 80 * This product includes software developed at the Information 81 * Technology Division, US Naval Research Laboratory. 82 * 4. Neither the name of the NRL nor the names of its contributors 83 * may be used to endorse or promote products derived from this software 84 * without specific prior written permission. 85 * 86 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 87 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 88 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 89 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 90 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 91 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 92 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 93 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 94 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 95 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 96 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 97 * 98 * The views and conclusions contained in the software and documentation 99 * are those of the authors and should not be interpreted as representing 100 * official policies, either expressed or implied, of the US Naval 101 * Research Laboratory (NRL). 102 */ 103 104 #include <sys/param.h> 105 #include <sys/systm.h> 106 #include <sys/proc.h> 107 #include <sys/mbuf.h> 108 #include <sys/socket.h> 109 #include <sys/socketvar.h> 110 #include <sys/domain.h> 111 #include <sys/protosw.h> 112 #include <sys/ioctl.h> 113 #include <sys/kernel.h> 114 #include <sys/queue.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 #ifdef MPLS 125 #include <netmpls/mpls.h> 126 #endif 127 128 #ifdef IPSEC 129 #include <netinet/ip_ipsp.h> 130 #include <net/if_enc.h> 131 132 struct ifaddr *encap_findgwifa(struct sockaddr *, u_int); 133 #endif 134 135 #define SA(p) ((struct sockaddr *)(p)) 136 137 struct route_cb route_cb; 138 struct rtstat rtstat; 139 struct radix_node_head ***rt_tables; 140 u_int8_t af2rtafidx[AF_MAX+1]; 141 u_int8_t rtafidx_max; 142 u_int rtbl_id_max = 0; 143 u_int *rt_tab2dom; /* rt table to domain lookup table */ 144 145 int rttrash; /* routes not in table but not freed */ 146 147 struct pool rtentry_pool; /* pool for rtentry structures */ 148 struct pool rttimer_pool; /* pool for rttimer structures */ 149 150 int rtable_init(struct radix_node_head ***, u_int); 151 int rtflushclone1(struct radix_node *, void *, u_int); 152 void rtflushclone(struct radix_node_head *, struct rtentry *); 153 int rt_if_remove_rtdelete(struct radix_node *, void *, u_int); 154 155 #define LABELID_MAX 50000 156 157 struct rt_label { 158 TAILQ_ENTRY(rt_label) rtl_entry; 159 char rtl_name[RTLABEL_LEN]; 160 u_int16_t rtl_id; 161 int rtl_ref; 162 }; 163 164 TAILQ_HEAD(rt_labels, rt_label) rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); 165 166 #ifdef IPSEC 167 struct ifaddr * 168 encap_findgwifa(struct sockaddr *gw, u_int rdomain) 169 { 170 struct ifnet *encif; 171 172 if ((encif = enc_getif(rdomain, 0)) == NULL) 173 return (NULL); 174 175 return (TAILQ_FIRST(&encif->if_addrlist)); 176 } 177 #endif 178 179 int 180 rtable_init(struct radix_node_head ***table, u_int id) 181 { 182 void **p; 183 struct domain *dom; 184 u_int8_t i; 185 186 if ((p = malloc(sizeof(void *) * (rtafidx_max + 1), M_RTABLE, 187 M_NOWAIT|M_ZERO)) == NULL) 188 return (ENOMEM); 189 190 /* 2nd pass: attach */ 191 for (dom = domains; dom != NULL; dom = dom->dom_next) 192 if (dom->dom_rtattach) 193 dom->dom_rtattach(&p[af2rtafidx[dom->dom_family]], 194 dom->dom_rtoffset); 195 196 *table = (struct radix_node_head **)p; 197 198 for (i = 0; i < rtafidx_max; i++) { 199 if ((*table)[i] != NULL) 200 (*table)[i]->rnh_rtableid = id; 201 } 202 203 return (0); 204 } 205 206 void 207 route_init(void) 208 { 209 struct domain *dom; 210 211 pool_init(&rtentry_pool, sizeof(struct rtentry), 0, 0, 0, "rtentpl", 212 NULL); 213 rn_init(); /* initialize all zeroes, all ones, mask table */ 214 215 bzero(af2rtafidx, sizeof(af2rtafidx)); 216 rtafidx_max = 1; /* must have NULL at index 0, so start at 1 */ 217 218 /* find out how many tables to allocate */ 219 for (dom = domains; dom != NULL; dom = dom->dom_next) 220 if (dom->dom_rtattach) 221 af2rtafidx[dom->dom_family] = rtafidx_max++; 222 223 if (rtable_add(0) != 0) 224 panic("route_init rtable_add"); 225 } 226 227 int 228 rtable_add(u_int id) /* must be called at splsoftnet */ 229 { 230 void *p, *q; 231 232 if (id > RT_TABLEID_MAX) 233 return (EINVAL); 234 235 if (id == 0 || id > rtbl_id_max) { 236 size_t newlen = sizeof(void *) * (id+1); 237 size_t newlen2 = sizeof(u_int) * (id+1); 238 239 if ((p = malloc(newlen, M_RTABLE, M_NOWAIT|M_ZERO)) == NULL) 240 return (ENOMEM); 241 if ((q = malloc(newlen2, M_RTABLE, M_NOWAIT|M_ZERO)) == NULL) { 242 free(p, M_RTABLE); 243 return (ENOMEM); 244 } 245 if (rt_tables) { 246 bcopy(rt_tables, p, sizeof(void *) * (rtbl_id_max+1)); 247 bcopy(rt_tab2dom, q, sizeof(u_int) * (rtbl_id_max+1)); 248 free(rt_tables, M_RTABLE); 249 free(rt_tab2dom, M_RTABLE); 250 } 251 rt_tables = p; 252 rt_tab2dom = q; 253 rtbl_id_max = id; 254 } 255 256 if (rt_tables[id] != NULL) /* already exists */ 257 return (EEXIST); 258 259 rt_tab2dom[id] = 0; /* use main table/domain by default */ 260 return (rtable_init(&rt_tables[id], id)); 261 } 262 263 u_int 264 rtable_l2(u_int id) 265 { 266 if (id > rtbl_id_max) 267 return (0); 268 return (rt_tab2dom[id]); 269 } 270 271 void 272 rtable_l2set(u_int id, u_int parent) 273 { 274 if (!rtable_exists(id) || !rtable_exists(parent)) 275 return; 276 rt_tab2dom[id] = parent; 277 } 278 279 int 280 rtable_exists(u_int id) /* verify table with that ID exists */ 281 { 282 if (id > RT_TABLEID_MAX) 283 return (0); 284 285 if (id > rtbl_id_max) 286 return (0); 287 288 if (rt_tables[id] == NULL) 289 return (0); 290 291 return (1); 292 } 293 294 /* 295 * Packet routing routines. 296 */ 297 void 298 rtalloc_noclone(struct route *ro) 299 { 300 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 301 return; /* XXX */ 302 ro->ro_rt = rtalloc1(&ro->ro_dst, RT_REPORT | RT_NOCLONING, 303 ro->ro_tableid); 304 } 305 306 void 307 rtalloc(struct route *ro) 308 { 309 if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) 310 return; /* XXX */ 311 ro->ro_rt = rtalloc1(&ro->ro_dst, RT_REPORT, ro->ro_tableid); 312 } 313 314 struct rtentry * 315 rtalloc1(struct sockaddr *dst, int flags, u_int tableid) 316 { 317 struct radix_node_head *rnh; 318 struct rtentry *rt; 319 struct radix_node *rn; 320 struct rtentry *newrt = 0; 321 struct rt_addrinfo info; 322 int s = splsoftnet(), err = 0, msgtype = RTM_MISS; 323 324 bzero(&info, sizeof(info)); 325 info.rti_info[RTAX_DST] = dst; 326 327 rnh = rt_gettable(dst->sa_family, tableid); 328 if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && 329 ((rn->rn_flags & RNF_ROOT) == 0)) { 330 newrt = rt = (struct rtentry *)rn; 331 if ((rt->rt_flags & RTF_CLONING) && 332 ISSET(flags, RT_REPORT | RT_NOCLONING) == RT_REPORT) { 333 err = rtrequest1(RTM_RESOLVE, &info, RTP_DEFAULT, 334 &newrt, tableid); 335 if (err) { 336 newrt = rt; 337 rt->rt_refcnt++; 338 goto miss; 339 } 340 if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) { 341 msgtype = RTM_RESOLVE; 342 goto miss; 343 } 344 /* Inform listeners of the new route */ 345 bzero(&info, sizeof(info)); 346 info.rti_info[RTAX_DST] = rt_key(rt); 347 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 348 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 349 if (rt->rt_ifp != NULL) { 350 info.rti_info[RTAX_IFP] = 351 TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr; 352 info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 353 } 354 rt_missmsg(RTM_ADD, &info, rt->rt_flags, 355 rt->rt_ifp, 0, tableid); 356 } else 357 rt->rt_refcnt++; 358 } else { 359 if (dst->sa_family != PF_KEY) 360 rtstat.rts_unreach++; 361 /* 362 * IP encapsulation does lots of lookups where we don't need nor want 363 * the RTM_MISSes that would be generated. It causes RTM_MISS storms 364 * sent upward breaking user-level routing queries. 365 */ 366 miss: 367 if (ISSET(flags, RT_REPORT) && dst->sa_family != PF_KEY) { 368 bzero((caddr_t)&info, sizeof(info)); 369 info.rti_info[RTAX_DST] = dst; 370 rt_missmsg(msgtype, &info, 0, NULL, err, tableid); 371 } 372 } 373 splx(s); 374 return (newrt); 375 } 376 377 void 378 rtfree(struct rtentry *rt) 379 { 380 struct ifaddr *ifa; 381 382 if (rt == NULL) 383 panic("rtfree"); 384 385 rt->rt_refcnt--; 386 387 if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) { 388 if (rt->rt_refcnt == 0 && (rt->rt_nodes->rn_flags & RNF_ACTIVE)) 389 return; /* route still active but currently down */ 390 if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 391 panic("rtfree 2"); 392 rttrash--; 393 if (rt->rt_refcnt < 0) { 394 printf("rtfree: %p not freed (neg refs)\n", rt); 395 return; 396 } 397 rt_timer_remove_all(rt); 398 ifa = rt->rt_ifa; 399 if (ifa) 400 IFAFREE(ifa); 401 rtlabel_unref(rt->rt_labelid); 402 #ifdef MPLS 403 if (rt->rt_flags & RTF_MPLS) 404 free(rt->rt_llinfo, M_TEMP); 405 #endif 406 Free(rt_key(rt)); 407 pool_put(&rtentry_pool, rt); 408 } 409 } 410 411 void 412 ifafree(struct ifaddr *ifa) 413 { 414 if (ifa == NULL) 415 panic("ifafree"); 416 if (ifa->ifa_refcnt == 0) 417 free(ifa, M_IFADDR); 418 else 419 ifa->ifa_refcnt--; 420 } 421 422 /* 423 * Force a routing table entry to the specified 424 * destination to go through the given gateway. 425 * Normally called as a result of a routing redirect 426 * message from the network layer. 427 * 428 * N.B.: must be called at splsoftnet 429 */ 430 void 431 rtredirect(struct sockaddr *dst, struct sockaddr *gateway, 432 struct sockaddr *netmask, int flags, struct sockaddr *src, 433 struct rtentry **rtp, u_int rdomain) 434 { 435 struct rtentry *rt; 436 int error = 0; 437 u_int32_t *stat = NULL; 438 struct rt_addrinfo info; 439 struct ifaddr *ifa; 440 struct ifnet *ifp = NULL; 441 442 splsoftassert(IPL_SOFTNET); 443 444 /* verify the gateway is directly reachable */ 445 if ((ifa = ifa_ifwithnet(gateway, rdomain)) == NULL) { 446 error = ENETUNREACH; 447 goto out; 448 } 449 ifp = ifa->ifa_ifp; 450 rt = rtalloc1(dst, 0, rdomain); 451 /* 452 * If the redirect isn't from our current router for this dst, 453 * it's either old or wrong. If it redirects us to ourselves, 454 * we have a routing loop, perhaps as a result of an interface 455 * going down recently. 456 */ 457 #define equal(a1, a2) \ 458 ((a1)->sa_len == (a2)->sa_len && \ 459 bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0) 460 if (!(flags & RTF_DONE) && rt && 461 (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa)) 462 error = EINVAL; 463 else if (ifa_ifwithaddr(gateway, rdomain) != NULL) 464 error = EHOSTUNREACH; 465 if (error) 466 goto done; 467 /* 468 * Create a new entry if we just got back a wildcard entry 469 * or the lookup failed. This is necessary for hosts 470 * which use routing redirects generated by smart gateways 471 * to dynamically build the routing tables. 472 */ 473 if ((rt == NULL) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2)) 474 goto create; 475 /* 476 * Don't listen to the redirect if it's 477 * for a route to an interface. 478 */ 479 if (rt->rt_flags & RTF_GATEWAY) { 480 if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) { 481 /* 482 * Changing from route to net => route to host. 483 * Create new route, rather than smashing route to net. 484 */ 485 create: 486 if (rt) 487 rtfree(rt); 488 flags |= RTF_GATEWAY | RTF_DYNAMIC; 489 bzero(&info, sizeof(info)); 490 info.rti_info[RTAX_DST] = dst; 491 info.rti_info[RTAX_GATEWAY] = gateway; 492 info.rti_info[RTAX_NETMASK] = netmask; 493 info.rti_ifa = ifa; 494 info.rti_flags = flags; 495 rt = NULL; 496 error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &rt, 497 rdomain); 498 if (rt != NULL) 499 flags = rt->rt_flags; 500 stat = &rtstat.rts_dynamic; 501 } else { 502 /* 503 * Smash the current notion of the gateway to 504 * this destination. Should check about netmask!!! 505 */ 506 rt->rt_flags |= RTF_MODIFIED; 507 flags |= RTF_MODIFIED; 508 stat = &rtstat.rts_newgateway; 509 rt_setgate(rt, rt_key(rt), gateway, rdomain); 510 } 511 } else 512 error = EHOSTUNREACH; 513 done: 514 if (rt) { 515 if (rtp && !error) 516 *rtp = rt; 517 else 518 rtfree(rt); 519 } 520 out: 521 if (error) 522 rtstat.rts_badredirect++; 523 else if (stat != NULL) 524 (*stat)++; 525 bzero((caddr_t)&info, sizeof(info)); 526 info.rti_info[RTAX_DST] = dst; 527 info.rti_info[RTAX_GATEWAY] = gateway; 528 info.rti_info[RTAX_NETMASK] = netmask; 529 info.rti_info[RTAX_AUTHOR] = src; 530 rt_missmsg(RTM_REDIRECT, &info, flags, ifp, error, rdomain); 531 } 532 533 /* 534 * Delete a route and generate a message 535 */ 536 int 537 rtdeletemsg(struct rtentry *rt, u_int tableid) 538 { 539 int error; 540 struct rt_addrinfo info; 541 struct ifnet *ifp; 542 543 /* 544 * Request the new route so that the entry is not actually 545 * deleted. That will allow the information being reported to 546 * be accurate (and consistent with route_output()). 547 */ 548 bzero((caddr_t)&info, sizeof(info)); 549 info.rti_info[RTAX_DST] = rt_key(rt); 550 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 551 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 552 info.rti_flags = rt->rt_flags; 553 ifp = rt->rt_ifp; 554 error = rtrequest1(RTM_DELETE, &info, rt->rt_priority, &rt, tableid); 555 556 rt_missmsg(RTM_DELETE, &info, info.rti_flags, ifp, error, tableid); 557 558 /* Adjust the refcount */ 559 if (error == 0 && rt->rt_refcnt <= 0) { 560 rt->rt_refcnt++; 561 rtfree(rt); 562 } 563 return (error); 564 } 565 566 int 567 rtflushclone1(struct radix_node *rn, void *arg, u_int id) 568 { 569 struct rtentry *rt, *parent; 570 571 rt = (struct rtentry *)rn; 572 parent = (struct rtentry *)arg; 573 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent) 574 rtdeletemsg(rt, id); 575 return 0; 576 } 577 578 void 579 rtflushclone(struct radix_node_head *rnh, struct rtentry *parent) 580 { 581 582 #ifdef DIAGNOSTIC 583 if (!parent || (parent->rt_flags & RTF_CLONING) == 0) 584 panic("rtflushclone: called with a non-cloning route"); 585 if (!rnh->rnh_walktree) 586 panic("rtflushclone: no rnh_walktree"); 587 #endif 588 rnh->rnh_walktree(rnh, rtflushclone1, (void *)parent); 589 } 590 591 int 592 rtioctl(u_long req, caddr_t data, struct proc *p) 593 { 594 return (EOPNOTSUPP); 595 } 596 597 struct ifaddr * 598 ifa_ifwithroute(int flags, struct sockaddr *dst, struct sockaddr *gateway, 599 u_int rtableid) 600 { 601 struct ifaddr *ifa; 602 603 #ifdef IPSEC 604 /* 605 * If the destination is a PF_KEY address, we'll look 606 * for the existence of a encap interface number or address 607 * in the options list of the gateway. By default, we'll return 608 * enc0. 609 */ 610 if (dst && (dst->sa_family == PF_KEY)) 611 return (encap_findgwifa(gateway, rtableid)); 612 #endif 613 614 if ((flags & RTF_GATEWAY) == 0) { 615 /* 616 * If we are adding a route to an interface, 617 * and the interface is a pt to pt link 618 * we should search for the destination 619 * as our clue to the interface. Otherwise 620 * we can use the local address. 621 */ 622 ifa = NULL; 623 if (flags & RTF_HOST) 624 ifa = ifa_ifwithdstaddr(dst, rtableid); 625 if (ifa == NULL) 626 ifa = ifa_ifwithaddr(gateway, rtableid); 627 } else { 628 /* 629 * If we are adding a route to a remote net 630 * or host, the gateway may still be on the 631 * other end of a pt to pt link. 632 */ 633 ifa = ifa_ifwithdstaddr(gateway, rtableid); 634 } 635 if (ifa == NULL) 636 ifa = ifa_ifwithnet(gateway, rtableid); 637 if (ifa == NULL) { 638 struct rtentry *rt = rtalloc1(gateway, 0, rtable_l2(rtableid)); 639 if (rt == NULL) 640 return (NULL); 641 rt->rt_refcnt--; 642 /* The gateway must be local if the same address family. */ 643 if ((rt->rt_flags & RTF_GATEWAY) && 644 rt_key(rt)->sa_family == dst->sa_family) 645 return (0); 646 if ((ifa = rt->rt_ifa) == NULL) 647 return (NULL); 648 } 649 if (ifa->ifa_addr->sa_family != dst->sa_family) { 650 struct ifaddr *oifa = ifa; 651 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 652 if (ifa == NULL) 653 ifa = oifa; 654 } 655 return (ifa); 656 } 657 658 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 659 660 int 661 rt_getifa(struct rt_addrinfo *info, u_int rtid) 662 { 663 struct ifaddr *ifa; 664 665 /* 666 * ifp may be specified by sockaddr_dl when protocol address 667 * is ambiguous 668 */ 669 if (info->rti_ifp == NULL && info->rti_info[RTAX_IFP] != NULL 670 && info->rti_info[RTAX_IFP]->sa_family == AF_LINK && 671 (ifa = ifa_ifwithnet((struct sockaddr *)info->rti_info[RTAX_IFP], 672 rtid)) != NULL) 673 info->rti_ifp = ifa->ifa_ifp; 674 675 if (info->rti_ifa == NULL && info->rti_info[RTAX_IFA] != NULL) 676 info->rti_ifa = ifa_ifwithaddr(info->rti_info[RTAX_IFA], rtid); 677 678 if (info->rti_ifa == NULL) { 679 struct sockaddr *sa; 680 681 if ((sa = info->rti_info[RTAX_IFA]) == NULL) 682 if ((sa = info->rti_info[RTAX_GATEWAY]) == NULL) 683 sa = info->rti_info[RTAX_DST]; 684 685 if (sa != NULL && info->rti_ifp != NULL) 686 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 687 else if (info->rti_info[RTAX_DST] != NULL && 688 info->rti_info[RTAX_GATEWAY] != NULL) 689 info->rti_ifa = ifa_ifwithroute(info->rti_flags, 690 info->rti_info[RTAX_DST], 691 info->rti_info[RTAX_GATEWAY], 692 rtid); 693 else if (sa != NULL) 694 info->rti_ifa = ifa_ifwithroute(info->rti_flags, 695 sa, sa, rtid); 696 } 697 698 if ((ifa = info->rti_ifa) == NULL) 699 return (ENETUNREACH); 700 701 if (info->rti_ifp == NULL) 702 info->rti_ifp = ifa->ifa_ifp; 703 704 return (0); 705 } 706 707 int 708 rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, 709 struct rtentry **ret_nrt, u_int tableid) 710 { 711 int s = splsoftnet(); int error = 0; 712 struct rtentry *rt, *crt; 713 struct radix_node *rn; 714 struct radix_node_head *rnh; 715 struct ifaddr *ifa; 716 struct sockaddr *ndst; 717 struct sockaddr_rtlabel *sa_rl, sa_rl2; 718 #ifdef MPLS 719 struct sockaddr_mpls *sa_mpls; 720 #endif 721 #define senderr(x) { error = x ; goto bad; } 722 723 if ((rnh = rt_gettable(info->rti_info[RTAX_DST]->sa_family, tableid)) == 724 NULL) 725 senderr(EAFNOSUPPORT); 726 if (info->rti_flags & RTF_HOST) 727 info->rti_info[RTAX_NETMASK] = NULL; 728 switch (req) { 729 case RTM_DELETE: 730 if ((rn = rnh->rnh_lookup(info->rti_info[RTAX_DST], 731 info->rti_info[RTAX_NETMASK], rnh)) == NULL) 732 senderr(ESRCH); 733 rt = (struct rtentry *)rn; 734 #ifndef SMALL_KERNEL 735 /* 736 * if we got multipath routes, we require users to specify 737 * a matching RTAX_GATEWAY. 738 */ 739 if (rn_mpath_capable(rnh)) { 740 rt = rt_mpath_matchgate(rt, 741 info->rti_info[RTAX_GATEWAY], prio); 742 rn = (struct radix_node *)rt; 743 if (!rt) 744 senderr(ESRCH); 745 } 746 #endif 747 if ((rn = rnh->rnh_deladdr(info->rti_info[RTAX_DST], 748 info->rti_info[RTAX_NETMASK], rnh, rn)) == NULL) 749 senderr(ESRCH); 750 rt = (struct rtentry *)rn; 751 752 /* clean up any cloned children */ 753 if ((rt->rt_flags & RTF_CLONING) != 0) 754 rtflushclone(rnh, rt); 755 756 if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) 757 panic ("rtrequest delete"); 758 759 if (rt->rt_gwroute) { 760 rt = rt->rt_gwroute; RTFREE(rt); 761 (rt = (struct rtentry *)rn)->rt_gwroute = NULL; 762 } 763 764 if (rt->rt_parent) { 765 rt->rt_parent->rt_refcnt--; 766 rt->rt_parent = NULL; 767 } 768 769 #ifndef SMALL_KERNEL 770 if (rn_mpath_capable(rnh)) { 771 if ((rn = rnh->rnh_lookup(info->rti_info[RTAX_DST], 772 info->rti_info[RTAX_NETMASK], rnh)) != NULL && 773 rn_mpath_next(rn, 0) == NULL) 774 ((struct rtentry *)rn)->rt_flags &= ~RTF_MPATH; 775 } 776 #endif 777 778 rt->rt_flags &= ~RTF_UP; 779 if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) 780 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 781 rttrash++; 782 783 if (ret_nrt) 784 *ret_nrt = rt; 785 else if (rt->rt_refcnt <= 0) { 786 rt->rt_refcnt++; 787 rtfree(rt); 788 } 789 break; 790 791 case RTM_RESOLVE: 792 if (ret_nrt == NULL || (rt = *ret_nrt) == NULL) 793 senderr(EINVAL); 794 if ((rt->rt_flags & RTF_CLONING) == 0) 795 senderr(EINVAL); 796 if (rt->rt_ifa->ifa_ifp) { 797 info->rti_ifa = rt->rt_ifa; 798 } else { 799 /* 800 * The interface address at the cloning route 801 * is not longer referenced by an interface. 802 * Try to find a similar active address and use 803 * it for the cloned route. The cloning route 804 * will get the new address and interface later. 805 */ 806 info->rti_ifa = NULL; 807 info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; 808 } 809 info->rti_ifp = rt->rt_ifp; 810 info->rti_flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); 811 info->rti_flags |= RTF_CLONED; 812 info->rti_info[RTAX_GATEWAY] = rt->rt_gateway; 813 if ((info->rti_info[RTAX_NETMASK] = rt->rt_genmask) == NULL) 814 info->rti_flags |= RTF_HOST; 815 info->rti_info[RTAX_LABEL] = 816 rtlabel_id2sa(rt->rt_labelid, &sa_rl2); 817 /* FALLTHROUGH */ 818 819 case RTM_ADD: 820 if (info->rti_ifa == NULL && (error = rt_getifa(info, tableid))) 821 senderr(error); 822 ifa = info->rti_ifa; 823 rt = pool_get(&rtentry_pool, PR_NOWAIT | PR_ZERO); 824 if (rt == NULL) 825 senderr(ENOBUFS); 826 827 rt->rt_flags = info->rti_flags; 828 829 if (prio == 0) 830 prio = ifa->ifa_ifp->if_priority + RTP_STATIC; 831 rt->rt_priority = prio; /* init routing priority */ 832 LIST_INIT(&rt->rt_timer); 833 if (rt_setgate(rt, info->rti_info[RTAX_DST], 834 info->rti_info[RTAX_GATEWAY], tableid)) { 835 pool_put(&rtentry_pool, rt); 836 senderr(ENOBUFS); 837 } 838 ndst = rt_key(rt); 839 if (info->rti_info[RTAX_NETMASK] != NULL) { 840 rt_maskedcopy(info->rti_info[RTAX_DST], ndst, 841 info->rti_info[RTAX_NETMASK]); 842 } else 843 Bcopy(info->rti_info[RTAX_DST], ndst, 844 info->rti_info[RTAX_DST]->sa_len); 845 #ifndef SMALL_KERNEL 846 if (rn_mpath_capable(rnh)) { 847 /* do not permit exactly the same dst/mask/gw pair */ 848 if (rt_mpath_conflict(rnh, rt, 849 info->rti_info[RTAX_NETMASK], 850 info->rti_flags & RTF_MPATH)) { 851 if (rt->rt_gwroute) 852 rtfree(rt->rt_gwroute); 853 Free(rt_key(rt)); 854 pool_put(&rtentry_pool, rt); 855 senderr(EEXIST); 856 } 857 /* check the link state since the table supports it */ 858 if (LINK_STATE_IS_UP(ifa->ifa_ifp->if_link_state) && 859 ifa->ifa_ifp->if_flags & IFF_UP) 860 rt->rt_flags |= RTF_UP; 861 else { 862 rt->rt_flags &= ~RTF_UP; 863 rt->rt_priority |= RTP_DOWN; 864 } 865 } 866 #endif 867 868 if (info->rti_info[RTAX_LABEL] != NULL) { 869 sa_rl = (struct sockaddr_rtlabel *) 870 info->rti_info[RTAX_LABEL]; 871 rt->rt_labelid = rtlabel_name2id(sa_rl->sr_label); 872 } 873 874 #ifdef MPLS 875 /* We have to allocate additional space for MPLS infos */ 876 if (info->rti_flags & RTF_MPLS && 877 (info->rti_info[RTAX_SRC] != NULL || 878 info->rti_info[RTAX_DST]->sa_family == AF_MPLS)) { 879 struct rt_mpls *rt_mpls; 880 881 sa_mpls = (struct sockaddr_mpls *) 882 info->rti_info[RTAX_SRC]; 883 884 rt->rt_llinfo = (caddr_t)malloc(sizeof(struct rt_mpls), 885 M_TEMP, M_NOWAIT|M_ZERO); 886 887 if (rt->rt_llinfo == NULL) { 888 if (rt->rt_gwroute) 889 rtfree(rt->rt_gwroute); 890 Free(rt_key(rt)); 891 pool_put(&rtentry_pool, rt); 892 senderr(ENOMEM); 893 } 894 895 rt_mpls = (struct rt_mpls *)rt->rt_llinfo; 896 897 if (sa_mpls != NULL) 898 rt_mpls->mpls_label = sa_mpls->smpls_label; 899 900 rt_mpls->mpls_operation = info->rti_mpls; 901 902 /* XXX: set experimental bits */ 903 904 rt->rt_flags |= RTF_MPLS; 905 } else 906 rt->rt_flags &= ~RTF_MPLS; 907 #endif 908 909 ifa->ifa_refcnt++; 910 rt->rt_ifa = ifa; 911 rt->rt_ifp = ifa->ifa_ifp; 912 if (req == RTM_RESOLVE) { 913 /* 914 * If the ifa of the cloning route was stale, a 915 * successful lookup for an ifa with the same address 916 * has been made. Use this ifa also for the cloning 917 * route. 918 */ 919 if ((*ret_nrt)->rt_ifa->ifa_ifp == NULL) { 920 printf("rtrequest1 RTM_RESOLVE: wrong ifa (%p) " 921 "was (%p)\n", ifa, (*ret_nrt)->rt_ifa); 922 if ((*ret_nrt)->rt_ifa->ifa_rtrequest) 923 (*ret_nrt)->rt_ifa->ifa_rtrequest( 924 RTM_DELETE, *ret_nrt, NULL); 925 IFAFREE((*ret_nrt)->rt_ifa); 926 (*ret_nrt)->rt_ifa = ifa; 927 (*ret_nrt)->rt_ifp = ifa->ifa_ifp; 928 ifa->ifa_refcnt++; 929 if (ifa->ifa_rtrequest) 930 ifa->ifa_rtrequest(RTM_ADD, *ret_nrt, 931 NULL); 932 } 933 /* 934 * Copy both metrics and a back pointer to the cloned 935 * route's parent. 936 */ 937 rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ 938 rt->rt_priority = (*ret_nrt)->rt_priority; 939 rt->rt_parent = *ret_nrt; /* Back ptr. to parent. */ 940 rt->rt_parent->rt_refcnt++; 941 } 942 rn = rnh->rnh_addaddr((caddr_t)ndst, 943 (caddr_t)info->rti_info[RTAX_NETMASK], rnh, rt->rt_nodes, 944 rt->rt_priority); 945 if (rn == NULL && (crt = rtalloc1(ndst, 0, tableid)) != NULL) { 946 /* overwrite cloned route */ 947 if ((crt->rt_flags & RTF_CLONED) != 0) { 948 rtdeletemsg(crt, tableid); 949 rn = rnh->rnh_addaddr((caddr_t)ndst, 950 (caddr_t)info->rti_info[RTAX_NETMASK], 951 rnh, rt->rt_nodes, rt->rt_priority); 952 } 953 RTFREE(crt); 954 } 955 if (rn == 0) { 956 IFAFREE(ifa); 957 if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent) 958 rtfree(rt->rt_parent); 959 if (rt->rt_gwroute) 960 rtfree(rt->rt_gwroute); 961 Free(rt_key(rt)); 962 pool_put(&rtentry_pool, rt); 963 senderr(EEXIST); 964 } 965 966 #ifndef SMALL_KERNEL 967 if (rn_mpath_capable(rnh) && 968 (rn = rnh->rnh_lookup(info->rti_info[RTAX_DST], 969 info->rti_info[RTAX_NETMASK], rnh)) != NULL && 970 (rn = rn_mpath_prio(rn, prio)) != NULL) { 971 if (rn_mpath_next(rn, 0) == NULL) 972 ((struct rtentry *)rn)->rt_flags &= ~RTF_MPATH; 973 else 974 ((struct rtentry *)rn)->rt_flags |= RTF_MPATH; 975 } 976 #endif 977 978 if (ifa->ifa_rtrequest) 979 ifa->ifa_rtrequest(req, rt, info); 980 if (ret_nrt) { 981 *ret_nrt = rt; 982 rt->rt_refcnt++; 983 } 984 if ((rt->rt_flags & RTF_CLONING) != 0) { 985 /* clean up any cloned children */ 986 rtflushclone(rnh, rt); 987 } 988 989 if_group_routechange(info->rti_info[RTAX_DST], 990 info->rti_info[RTAX_NETMASK]); 991 break; 992 } 993 bad: 994 splx(s); 995 return (error); 996 } 997 998 int 999 rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate, 1000 u_int tableid) 1001 { 1002 caddr_t new, old; 1003 int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len); 1004 1005 if (rt->rt_gateway == NULL || glen > ROUNDUP(rt->rt_gateway->sa_len)) { 1006 old = (caddr_t)rt_key(rt); 1007 R_Malloc(new, caddr_t, dlen + glen); 1008 if (new == NULL) 1009 return 1; 1010 rt->rt_nodes->rn_key = new; 1011 } else { 1012 new = rt->rt_nodes->rn_key; 1013 old = NULL; 1014 } 1015 Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen); 1016 if (old) { 1017 Bcopy(dst, new, dlen); 1018 Free(old); 1019 } 1020 if (rt->rt_gwroute != NULL) { 1021 RTFREE(rt->rt_gwroute); 1022 rt->rt_gwroute = NULL; 1023 } 1024 if (rt->rt_flags & RTF_GATEWAY) { 1025 /* XXX is this actually valid to cross tables here? */ 1026 rt->rt_gwroute = rtalloc1(gate, RT_REPORT, rtable_l2(tableid)); 1027 /* 1028 * If we switched gateways, grab the MTU from the new 1029 * gateway route if the current MTU is 0 or greater 1030 * than the MTU of gateway. 1031 * Note that, if the MTU of gateway is 0, we will reset the 1032 * MTU of the route to run PMTUD again from scratch. XXX 1033 */ 1034 if (rt->rt_gwroute && !(rt->rt_rmx.rmx_locks & RTV_MTU) && 1035 rt->rt_rmx.rmx_mtu && 1036 rt->rt_rmx.rmx_mtu > rt->rt_gwroute->rt_rmx.rmx_mtu) { 1037 rt->rt_rmx.rmx_mtu = rt->rt_gwroute->rt_rmx.rmx_mtu; 1038 } 1039 } 1040 return (0); 1041 } 1042 1043 void 1044 rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, 1045 struct sockaddr *netmask) 1046 { 1047 u_char *cp1 = (u_char *)src; 1048 u_char *cp2 = (u_char *)dst; 1049 u_char *cp3 = (u_char *)netmask; 1050 u_char *cplim = cp2 + *cp3; 1051 u_char *cplim2 = cp2 + *cp1; 1052 1053 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 1054 cp3 += 2; 1055 if (cplim > cplim2) 1056 cplim = cplim2; 1057 while (cp2 < cplim) 1058 *cp2++ = *cp1++ & *cp3++; 1059 if (cp2 < cplim2) 1060 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 1061 } 1062 1063 /* 1064 * Set up a routing table entry, normally 1065 * for an interface. 1066 */ 1067 int 1068 rtinit(struct ifaddr *ifa, int cmd, int flags) 1069 { 1070 struct rtentry *rt; 1071 struct sockaddr *dst, *deldst; 1072 struct mbuf *m = NULL; 1073 struct rtentry *nrt = NULL; 1074 int error; 1075 struct rt_addrinfo info; 1076 struct sockaddr_rtlabel sa_rl; 1077 u_short rtableid = ifa->ifa_ifp->if_rdomain; 1078 1079 dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr; 1080 if (cmd == RTM_DELETE) { 1081 if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) { 1082 m = m_get(M_DONTWAIT, MT_SONAME); 1083 if (m == NULL) 1084 return (ENOBUFS); 1085 deldst = mtod(m, struct sockaddr *); 1086 rt_maskedcopy(dst, deldst, ifa->ifa_netmask); 1087 dst = deldst; 1088 } 1089 if ((rt = rtalloc1(dst, 0, rtableid)) != NULL) { 1090 rt->rt_refcnt--; 1091 /* try to find the right route */ 1092 while (rt && rt->rt_ifa != ifa) 1093 rt = (struct rtentry *) 1094 ((struct radix_node *)rt)->rn_dupedkey; 1095 if (!rt) { 1096 if (m != NULL) 1097 (void) m_free(m); 1098 return (flags & RTF_HOST ? EHOSTUNREACH 1099 : ENETUNREACH); 1100 } 1101 } 1102 } 1103 bzero(&info, sizeof(info)); 1104 info.rti_ifa = ifa; 1105 info.rti_flags = flags | ifa->ifa_flags; 1106 info.rti_info[RTAX_DST] = dst; 1107 if (cmd == RTM_ADD) 1108 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 1109 info.rti_info[RTAX_LABEL] = 1110 rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl); 1111 1112 /* 1113 * XXX here, it seems that we are assuming that ifa_netmask is NULL 1114 * for RTF_HOST. bsdi4 passes NULL explicitly (via intermediate 1115 * variable) when RTF_HOST is 1. still not sure if i can safely 1116 * change it to meet bsdi4 behavior. 1117 */ 1118 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1119 error = rtrequest1(cmd, &info, RTP_CONNECTED, &nrt, rtableid); 1120 if (cmd == RTM_DELETE) { 1121 if (error == 0 && (rt = nrt) != NULL) { 1122 rt_newaddrmsg(cmd, ifa, error, nrt); 1123 if (rt->rt_refcnt <= 0) { 1124 rt->rt_refcnt++; 1125 rtfree(rt); 1126 } 1127 } 1128 if (m != NULL) 1129 (void) m_free(m); 1130 } 1131 if (cmd == RTM_ADD && error == 0 && (rt = nrt) != NULL) { 1132 rt->rt_refcnt--; 1133 if (rt->rt_ifa != ifa) { 1134 printf("rtinit: wrong ifa (%p) was (%p)\n", 1135 ifa, rt->rt_ifa); 1136 if (rt->rt_ifa->ifa_rtrequest) 1137 rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, NULL); 1138 IFAFREE(rt->rt_ifa); 1139 rt->rt_ifa = ifa; 1140 rt->rt_ifp = ifa->ifa_ifp; 1141 ifa->ifa_refcnt++; 1142 if (ifa->ifa_rtrequest) 1143 ifa->ifa_rtrequest(RTM_ADD, rt, NULL); 1144 } 1145 rt_newaddrmsg(cmd, ifa, error, nrt); 1146 } 1147 return (error); 1148 } 1149 1150 /* 1151 * Route timer routines. These routes allow functions to be called 1152 * for various routes at any time. This is useful in supporting 1153 * path MTU discovery and redirect route deletion. 1154 * 1155 * This is similar to some BSDI internal functions, but it provides 1156 * for multiple queues for efficiency's sake... 1157 */ 1158 1159 LIST_HEAD(, rttimer_queue) rttimer_queue_head; 1160 static int rt_init_done = 0; 1161 1162 #define RTTIMER_CALLOUT(r) { \ 1163 if (r->rtt_func != NULL) { \ 1164 (*r->rtt_func)(r->rtt_rt, r); \ 1165 } else { \ 1166 struct rt_addrinfo info; \ 1167 bzero(&info, sizeof(info)); \ 1168 info.rti_info[RTAX_DST] = rt_key(r->rtt_rt); \ 1169 rtrequest1(RTM_DELETE, &info, \ 1170 r->rtt_rt->rt_priority, NULL, r->rtt_tableid); \ 1171 } \ 1172 } 1173 1174 /* 1175 * Some subtle order problems with domain initialization mean that 1176 * we cannot count on this being run from rt_init before various 1177 * protocol initializations are done. Therefore, we make sure 1178 * that this is run when the first queue is added... 1179 */ 1180 1181 void 1182 rt_timer_init() 1183 { 1184 static struct timeout rt_timer_timeout; 1185 1186 if (rt_init_done) 1187 panic("rt_timer_init: already initialized"); 1188 1189 pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl", 1190 NULL); 1191 1192 LIST_INIT(&rttimer_queue_head); 1193 timeout_set(&rt_timer_timeout, rt_timer_timer, &rt_timer_timeout); 1194 timeout_add_sec(&rt_timer_timeout, 1); 1195 rt_init_done = 1; 1196 } 1197 1198 struct rttimer_queue * 1199 rt_timer_queue_create(u_int timeout) 1200 { 1201 struct rttimer_queue *rtq; 1202 1203 if (rt_init_done == 0) 1204 rt_timer_init(); 1205 1206 if ((rtq = malloc(sizeof(*rtq), M_RTABLE, M_NOWAIT|M_ZERO)) == NULL) 1207 return (NULL); 1208 1209 rtq->rtq_timeout = timeout; 1210 rtq->rtq_count = 0; 1211 TAILQ_INIT(&rtq->rtq_head); 1212 LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link); 1213 1214 return (rtq); 1215 } 1216 1217 void 1218 rt_timer_queue_change(struct rttimer_queue *rtq, long timeout) 1219 { 1220 rtq->rtq_timeout = timeout; 1221 } 1222 1223 void 1224 rt_timer_queue_destroy(struct rttimer_queue *rtq, int destroy) 1225 { 1226 struct rttimer *r; 1227 1228 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) { 1229 LIST_REMOVE(r, rtt_link); 1230 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1231 if (destroy) 1232 RTTIMER_CALLOUT(r); 1233 pool_put(&rttimer_pool, r); 1234 if (rtq->rtq_count > 0) 1235 rtq->rtq_count--; 1236 else 1237 printf("rt_timer_queue_destroy: rtq_count reached 0\n"); 1238 } 1239 1240 LIST_REMOVE(rtq, rtq_link); 1241 free(rtq, M_RTABLE); 1242 } 1243 1244 unsigned long 1245 rt_timer_count(struct rttimer_queue *rtq) 1246 { 1247 return (rtq->rtq_count); 1248 } 1249 1250 void 1251 rt_timer_remove_all(struct rtentry *rt) 1252 { 1253 struct rttimer *r; 1254 1255 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 1256 LIST_REMOVE(r, rtt_link); 1257 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1258 if (r->rtt_queue->rtq_count > 0) 1259 r->rtt_queue->rtq_count--; 1260 else 1261 printf("rt_timer_remove_all: rtq_count reached 0\n"); 1262 pool_put(&rttimer_pool, r); 1263 } 1264 } 1265 1266 int 1267 rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *, 1268 struct rttimer *), struct rttimer_queue *queue, u_int rtableid) 1269 { 1270 struct rttimer *r; 1271 long current_time; 1272 1273 current_time = time_uptime; 1274 rt->rt_rmx.rmx_expire = time_second + queue->rtq_timeout; 1275 1276 /* 1277 * If there's already a timer with this action, destroy it before 1278 * we add a new one. 1279 */ 1280 for (r = LIST_FIRST(&rt->rt_timer); r != NULL; 1281 r = LIST_NEXT(r, rtt_link)) { 1282 if (r->rtt_func == func) { 1283 LIST_REMOVE(r, rtt_link); 1284 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1285 if (r->rtt_queue->rtq_count > 0) 1286 r->rtt_queue->rtq_count--; 1287 else 1288 printf("rt_timer_add: rtq_count reached 0\n"); 1289 pool_put(&rttimer_pool, r); 1290 break; /* only one per list, so we can quit... */ 1291 } 1292 } 1293 1294 r = pool_get(&rttimer_pool, PR_NOWAIT | PR_ZERO); 1295 if (r == NULL) 1296 return (ENOBUFS); 1297 1298 r->rtt_rt = rt; 1299 r->rtt_time = current_time; 1300 r->rtt_func = func; 1301 r->rtt_queue = queue; 1302 r->rtt_tableid = rtableid; 1303 LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link); 1304 TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next); 1305 r->rtt_queue->rtq_count++; 1306 1307 return (0); 1308 } 1309 1310 struct radix_node_head * 1311 rt_gettable(sa_family_t af, u_int id) 1312 { 1313 if (id > rtbl_id_max) 1314 return (NULL); 1315 return (rt_tables[id] ? rt_tables[id][af2rtafidx[af]] : NULL); 1316 } 1317 1318 struct radix_node * 1319 rt_lookup(struct sockaddr *dst, struct sockaddr *mask, u_int tableid) 1320 { 1321 struct radix_node_head *rnh; 1322 1323 if ((rnh = rt_gettable(dst->sa_family, tableid)) == NULL) 1324 return (NULL); 1325 1326 return (rnh->rnh_lookup(dst, mask, rnh)); 1327 } 1328 1329 /* ARGSUSED */ 1330 void 1331 rt_timer_timer(void *arg) 1332 { 1333 struct timeout *to = (struct timeout *)arg; 1334 struct rttimer_queue *rtq; 1335 struct rttimer *r; 1336 long current_time; 1337 int s; 1338 1339 current_time = time_uptime; 1340 1341 s = splsoftnet(); 1342 for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL; 1343 rtq = LIST_NEXT(rtq, rtq_link)) { 1344 while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL && 1345 (r->rtt_time + rtq->rtq_timeout) < current_time) { 1346 LIST_REMOVE(r, rtt_link); 1347 TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next); 1348 RTTIMER_CALLOUT(r); 1349 pool_put(&rttimer_pool, r); 1350 if (rtq->rtq_count > 0) 1351 rtq->rtq_count--; 1352 else 1353 printf("rt_timer_timer: rtq_count reached 0\n"); 1354 } 1355 } 1356 splx(s); 1357 1358 timeout_add_sec(to, 1); 1359 } 1360 1361 u_int16_t 1362 rtlabel_name2id(char *name) 1363 { 1364 struct rt_label *label, *p = NULL; 1365 u_int16_t new_id = 1; 1366 1367 if (!name[0]) 1368 return (0); 1369 1370 TAILQ_FOREACH(label, &rt_labels, rtl_entry) 1371 if (strcmp(name, label->rtl_name) == 0) { 1372 label->rtl_ref++; 1373 return (label->rtl_id); 1374 } 1375 1376 /* 1377 * to avoid fragmentation, we do a linear search from the beginning 1378 * and take the first free slot we find. if there is none or the list 1379 * is empty, append a new entry at the end. 1380 */ 1381 1382 if (!TAILQ_EMPTY(&rt_labels)) 1383 for (p = TAILQ_FIRST(&rt_labels); p != NULL && 1384 p->rtl_id == new_id; p = TAILQ_NEXT(p, rtl_entry)) 1385 new_id = p->rtl_id + 1; 1386 1387 if (new_id > LABELID_MAX) 1388 return (0); 1389 1390 label = malloc(sizeof(*label), M_TEMP, M_NOWAIT|M_ZERO); 1391 if (label == NULL) 1392 return (0); 1393 strlcpy(label->rtl_name, name, sizeof(label->rtl_name)); 1394 label->rtl_id = new_id; 1395 label->rtl_ref++; 1396 1397 if (p != NULL) /* insert new entry before p */ 1398 TAILQ_INSERT_BEFORE(p, label, rtl_entry); 1399 else /* either list empty or no free slot in between */ 1400 TAILQ_INSERT_TAIL(&rt_labels, label, rtl_entry); 1401 1402 return (label->rtl_id); 1403 } 1404 1405 const char * 1406 rtlabel_id2name(u_int16_t id) 1407 { 1408 struct rt_label *label; 1409 1410 TAILQ_FOREACH(label, &rt_labels, rtl_entry) 1411 if (label->rtl_id == id) 1412 return (label->rtl_name); 1413 1414 return (NULL); 1415 } 1416 1417 struct sockaddr * 1418 rtlabel_id2sa(u_int16_t labelid, struct sockaddr_rtlabel *sa_rl) 1419 { 1420 const char *label; 1421 1422 if (labelid == 0 || (label = rtlabel_id2name(labelid)) == NULL) 1423 return (NULL); 1424 1425 bzero(sa_rl, sizeof(*sa_rl)); 1426 sa_rl->sr_len = sizeof(*sa_rl); 1427 sa_rl->sr_family = AF_UNSPEC; 1428 strlcpy(sa_rl->sr_label, label, sizeof(sa_rl->sr_label)); 1429 1430 return ((struct sockaddr *)sa_rl); 1431 } 1432 1433 void 1434 rtlabel_unref(u_int16_t id) 1435 { 1436 struct rt_label *p, *next; 1437 1438 if (id == 0) 1439 return; 1440 1441 for (p = TAILQ_FIRST(&rt_labels); p != NULL; p = next) { 1442 next = TAILQ_NEXT(p, rtl_entry); 1443 if (id == p->rtl_id) { 1444 if (--p->rtl_ref == 0) { 1445 TAILQ_REMOVE(&rt_labels, p, rtl_entry); 1446 free(p, M_TEMP); 1447 } 1448 break; 1449 } 1450 } 1451 } 1452 1453 void 1454 rt_if_remove(struct ifnet *ifp) 1455 { 1456 int i; 1457 u_int tid; 1458 struct radix_node_head *rnh; 1459 1460 for (tid = 0; tid <= rtbl_id_max; tid++) { 1461 for (i = 1; i <= AF_MAX; i++) { 1462 if ((rnh = rt_gettable(i, tid)) != NULL) 1463 while ((*rnh->rnh_walktree)(rnh, 1464 rt_if_remove_rtdelete, ifp) == EAGAIN) 1465 ; /* nothing */ 1466 } 1467 } 1468 } 1469 1470 /* 1471 * Note that deleting a RTF_CLONING route can trigger the 1472 * deletion of more entries, so we need to cancel the walk 1473 * and return EAGAIN. The caller should restart the walk 1474 * as long as EAGAIN is returned. 1475 */ 1476 int 1477 rt_if_remove_rtdelete(struct radix_node *rn, void *vifp, u_int id) 1478 { 1479 struct ifnet *ifp = vifp; 1480 struct rtentry *rt = (struct rtentry *)rn; 1481 1482 if (rt->rt_ifp == ifp) { 1483 int cloning = (rt->rt_flags & RTF_CLONING); 1484 1485 if (rtdeletemsg(rt, id) == 0 && cloning) 1486 return (EAGAIN); 1487 } 1488 1489 /* 1490 * XXX There should be no need to check for rt_ifa belonging to this 1491 * interface, because then rt_ifp is set, right? 1492 */ 1493 1494 return (0); 1495 } 1496 1497 #ifndef SMALL_KERNEL 1498 void 1499 rt_if_track(struct ifnet *ifp) 1500 { 1501 struct radix_node_head *rnh; 1502 int i; 1503 u_int tid; 1504 1505 if (rt_tables == NULL) 1506 return; 1507 1508 for (tid = 0; tid <= rtbl_id_max; tid++) { 1509 for (i = 1; i <= AF_MAX; i++) { 1510 if ((rnh = rt_gettable(i, tid)) != NULL) { 1511 if (!rn_mpath_capable(rnh)) 1512 continue; 1513 while ((*rnh->rnh_walktree)(rnh, 1514 rt_if_linkstate_change, ifp) == EAGAIN) 1515 ; /* nothing */ 1516 } 1517 } 1518 } 1519 } 1520 1521 int 1522 rt_if_linkstate_change(struct radix_node *rn, void *arg, u_int id) 1523 { 1524 struct ifnet *ifp = arg; 1525 struct rtentry *rt = (struct rtentry *)rn; 1526 1527 if (rt->rt_ifp == ifp) { 1528 if (LINK_STATE_IS_UP(ifp->if_link_state) && 1529 ifp->if_flags & IFF_UP) { 1530 if (!(rt->rt_flags & RTF_UP)) { 1531 /* bring route up */ 1532 rt->rt_flags |= RTF_UP; 1533 rn_mpath_reprio(rn, rt->rt_priority & RTP_MASK); 1534 } 1535 } else { 1536 if (rt->rt_flags & RTF_UP) { 1537 /* take route done */ 1538 rt->rt_flags &= ~RTF_UP; 1539 rn_mpath_reprio(rn, rt->rt_priority | RTP_DOWN); 1540 } 1541 } 1542 if_group_routechange(rt_key(rt), rt_mask(rt)); 1543 } 1544 1545 return (0); 1546 } 1547 #endif 1548