1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1980, 1986, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)route.c 8.3.1.1 (Berkeley) 2/23/95 32 * $FreeBSD$ 33 */ 34 /************************************************************************ 35 * Note: In this file a 'fib' is a "forwarding information base" * 36 * Which is the new name for an in kernel routing (next hop) table. * 37 ***********************************************************************/ 38 39 #include "opt_inet.h" 40 #include "opt_inet6.h" 41 #include "opt_mrouting.h" 42 #include "opt_mpath.h" 43 #include "opt_route.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/malloc.h> 48 #include <sys/mbuf.h> 49 #include <sys/socket.h> 50 #include <sys/sysctl.h> 51 #include <sys/syslog.h> 52 #include <sys/sysproto.h> 53 #include <sys/proc.h> 54 #include <sys/domain.h> 55 #include <sys/eventhandler.h> 56 #include <sys/kernel.h> 57 #include <sys/lock.h> 58 #include <sys/rmlock.h> 59 60 #include <net/if.h> 61 #include <net/if_var.h> 62 #include <net/if_dl.h> 63 #include <net/route.h> 64 #include <net/route/route_ctl.h> 65 #include <net/route/route_var.h> 66 #include <net/route/nhop.h> 67 #include <net/route/shared.h> 68 #include <net/vnet.h> 69 70 #ifdef RADIX_MPATH 71 #include <net/radix_mpath.h> 72 #endif 73 74 #include <netinet/in.h> 75 #include <netinet/ip_mroute.h> 76 77 #include <vm/uma.h> 78 79 #define RT_MAXFIBS UINT16_MAX 80 81 /* Kernel config default option. */ 82 #ifdef ROUTETABLES 83 #if ROUTETABLES <= 0 84 #error "ROUTETABLES defined too low" 85 #endif 86 #if ROUTETABLES > RT_MAXFIBS 87 #error "ROUTETABLES defined too big" 88 #endif 89 #define RT_NUMFIBS ROUTETABLES 90 #endif /* ROUTETABLES */ 91 /* Initialize to default if not otherwise set. */ 92 #ifndef RT_NUMFIBS 93 #define RT_NUMFIBS 1 94 #endif 95 96 /* This is read-only.. */ 97 u_int rt_numfibs = RT_NUMFIBS; 98 SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RDTUN, &rt_numfibs, 0, ""); 99 100 /* 101 * By default add routes to all fibs for new interfaces. 102 * Once this is set to 0 then only allocate routes on interface 103 * changes for the FIB of the caller when adding a new set of addresses 104 * to an interface. XXX this is a shotgun aproach to a problem that needs 105 * a more fine grained solution.. that will come. 106 * XXX also has the problems getting the FIB from curthread which will not 107 * always work given the fib can be overridden and prefixes can be added 108 * from the network stack context. 109 */ 110 VNET_DEFINE(u_int, rt_add_addr_allfibs) = 1; 111 SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET, 112 &VNET_NAME(rt_add_addr_allfibs), 0, ""); 113 114 VNET_PCPUSTAT_DEFINE(struct rtstat, rtstat); 115 116 VNET_PCPUSTAT_SYSINIT(rtstat); 117 #ifdef VIMAGE 118 VNET_PCPUSTAT_SYSUNINIT(rtstat); 119 #endif 120 121 VNET_DEFINE(struct rib_head *, rt_tables); 122 #define V_rt_tables VNET(rt_tables) 123 124 125 EVENTHANDLER_LIST_DEFINE(rt_addrmsg); 126 127 static int rt_ifdelroute(const struct rtentry *rt, const struct nhop_object *, 128 void *arg); 129 static int rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, 130 int flags); 131 132 /* 133 * handler for net.my_fibnum 134 */ 135 static int 136 sysctl_my_fibnum(SYSCTL_HANDLER_ARGS) 137 { 138 int fibnum; 139 int error; 140 141 fibnum = curthread->td_proc->p_fibnum; 142 error = sysctl_handle_int(oidp, &fibnum, 0, req); 143 return (error); 144 } 145 146 SYSCTL_PROC(_net, OID_AUTO, my_fibnum, 147 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, 148 &sysctl_my_fibnum, "I", 149 "default FIB of caller"); 150 151 static __inline struct rib_head ** 152 rt_tables_get_rnh_ptr(int table, int fam) 153 { 154 struct rib_head **rnh; 155 156 KASSERT(table >= 0 && table < rt_numfibs, 157 ("%s: table out of bounds (0 <= %d < %d)", __func__, table, 158 rt_numfibs)); 159 KASSERT(fam >= 0 && fam < (AF_MAX + 1), 160 ("%s: fam out of bounds (0 <= %d < %d)", __func__, fam, AF_MAX+1)); 161 162 /* rnh is [fib=0][af=0]. */ 163 rnh = (struct rib_head **)V_rt_tables; 164 /* Get the offset to the requested table and fam. */ 165 rnh += table * (AF_MAX+1) + fam; 166 167 return (rnh); 168 } 169 170 struct rib_head * 171 rt_tables_get_rnh(int table, int fam) 172 { 173 174 return (*rt_tables_get_rnh_ptr(table, fam)); 175 } 176 177 u_int 178 rt_tables_get_gen(int table, int fam) 179 { 180 struct rib_head *rnh; 181 182 rnh = *rt_tables_get_rnh_ptr(table, fam); 183 KASSERT(rnh != NULL, ("%s: NULL rib_head pointer table %d fam %d", 184 __func__, table, fam)); 185 return (rnh->rnh_gen); 186 } 187 188 189 /* 190 * route initialization must occur before ip6_init2(), which happenas at 191 * SI_ORDER_MIDDLE. 192 */ 193 static void 194 route_init(void) 195 { 196 197 /* whack the tunable ints into line. */ 198 if (rt_numfibs > RT_MAXFIBS) 199 rt_numfibs = RT_MAXFIBS; 200 if (rt_numfibs == 0) 201 rt_numfibs = 1; 202 nhops_init(); 203 } 204 SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, NULL); 205 206 static void 207 vnet_route_init(const void *unused __unused) 208 { 209 struct domain *dom; 210 struct rib_head **rnh; 211 int table; 212 int fam; 213 214 V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) * 215 sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO); 216 217 vnet_rtzone_init(); 218 for (dom = domains; dom; dom = dom->dom_next) { 219 if (dom->dom_rtattach == NULL) 220 continue; 221 222 for (table = 0; table < rt_numfibs; table++) { 223 fam = dom->dom_family; 224 if (table != 0 && fam != AF_INET6 && fam != AF_INET) 225 break; 226 227 rnh = rt_tables_get_rnh_ptr(table, fam); 228 if (rnh == NULL) 229 panic("%s: rnh NULL", __func__); 230 *rnh = dom->dom_rtattach(table); 231 } 232 } 233 } 234 VNET_SYSINIT(vnet_route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, 235 vnet_route_init, 0); 236 237 #ifdef VIMAGE 238 static void 239 vnet_route_uninit(const void *unused __unused) 240 { 241 int table; 242 int fam; 243 struct domain *dom; 244 struct rib_head **rnh; 245 246 for (dom = domains; dom; dom = dom->dom_next) { 247 if (dom->dom_rtdetach == NULL) 248 continue; 249 250 for (table = 0; table < rt_numfibs; table++) { 251 fam = dom->dom_family; 252 253 if (table != 0 && fam != AF_INET6 && fam != AF_INET) 254 break; 255 256 rnh = rt_tables_get_rnh_ptr(table, fam); 257 if (rnh == NULL) 258 panic("%s: rnh NULL", __func__); 259 dom->dom_rtdetach(*rnh); 260 } 261 } 262 263 /* 264 * dom_rtdetach calls rt_table_destroy(), which 265 * schedules deletion for all rtentries, nexthops and control 266 * structures. Wait for the destruction callbacks to fire. 267 * Note that this should result in freeing all rtentries, but 268 * nexthops deletions will be scheduled for the next epoch run 269 * and will be completed after vnet teardown. 270 */ 271 epoch_drain_callbacks(net_epoch_preempt); 272 273 free(V_rt_tables, M_RTABLE); 274 vnet_rtzone_destroy(); 275 } 276 VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, 277 vnet_route_uninit, 0); 278 #endif 279 280 struct rib_head * 281 rt_table_init(int offset, int family, u_int fibnum) 282 { 283 struct rib_head *rh; 284 285 rh = malloc(sizeof(struct rib_head), M_RTABLE, M_WAITOK | M_ZERO); 286 287 /* TODO: These details should be hidded inside radix.c */ 288 /* Init masks tree */ 289 rn_inithead_internal(&rh->head, rh->rnh_nodes, offset); 290 rn_inithead_internal(&rh->rmhead.head, rh->rmhead.mask_nodes, 0); 291 rh->head.rnh_masks = &rh->rmhead; 292 293 /* Save metadata associated with this routing table. */ 294 rh->rib_family = family; 295 rh->rib_fibnum = fibnum; 296 #ifdef VIMAGE 297 rh->rib_vnet = curvnet; 298 #endif 299 300 tmproutes_init(rh); 301 302 /* Init locks */ 303 RIB_LOCK_INIT(rh); 304 305 nhops_init_rib(rh); 306 307 /* Init subscription system */ 308 rib_init_subscriptions(rh); 309 310 /* Finally, set base callbacks */ 311 rh->rnh_addaddr = rn_addroute; 312 rh->rnh_deladdr = rn_delete; 313 rh->rnh_matchaddr = rn_match; 314 rh->rnh_lookup = rn_lookup; 315 rh->rnh_walktree = rn_walktree; 316 rh->rnh_walktree_from = rn_walktree_from; 317 318 return (rh); 319 } 320 321 static int 322 rt_freeentry(struct radix_node *rn, void *arg) 323 { 324 struct radix_head * const rnh = arg; 325 struct radix_node *x; 326 327 x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh); 328 if (x != NULL) 329 R_Free(x); 330 return (0); 331 } 332 333 void 334 rt_table_destroy(struct rib_head *rh) 335 { 336 337 tmproutes_destroy(rh); 338 339 rn_walktree(&rh->rmhead.head, rt_freeentry, &rh->rmhead.head); 340 341 nhops_destroy_rib(rh); 342 343 rib_destroy_subscriptions(rh); 344 345 /* Assume table is already empty */ 346 RIB_LOCK_DESTROY(rh); 347 free(rh, M_RTABLE); 348 } 349 350 351 #ifndef _SYS_SYSPROTO_H_ 352 struct setfib_args { 353 int fibnum; 354 }; 355 #endif 356 int 357 sys_setfib(struct thread *td, struct setfib_args *uap) 358 { 359 if (uap->fibnum < 0 || uap->fibnum >= rt_numfibs) 360 return EINVAL; 361 td->td_proc->p_fibnum = uap->fibnum; 362 return (0); 363 } 364 365 /* 366 * Adds a temporal redirect entry to the routing table. 367 * @fibnum: fib number 368 * @dst: destination to install redirect to 369 * @gateway: gateway to go via 370 * @author: sockaddr of originating router, can be NULL 371 * @ifp: interface to use for the redirected route 372 * @flags: set of flags to add. Allowed: RTF_GATEWAY 373 * @lifetime_sec: time in seconds to expire this redirect. 374 * 375 * Retuns 0 on success, errno otherwise. 376 */ 377 int 378 rib_add_redirect(u_int fibnum, struct sockaddr *dst, struct sockaddr *gateway, 379 struct sockaddr *author, struct ifnet *ifp, int flags, int lifetime_sec) 380 { 381 struct rib_cmd_info rc; 382 int error; 383 struct rt_addrinfo info; 384 struct rt_metrics rti_rmx; 385 struct ifaddr *ifa; 386 387 NET_EPOCH_ASSERT(); 388 389 if (rt_tables_get_rnh(fibnum, dst->sa_family) == NULL) 390 return (EAFNOSUPPORT); 391 392 /* Verify the allowed flag mask. */ 393 KASSERT(((flags & ~(RTF_GATEWAY)) == 0), 394 ("invalid redirect flags: %x", flags)); 395 396 /* Get the best ifa for the given interface and gateway. */ 397 if ((ifa = ifaof_ifpforaddr(gateway, ifp)) == NULL) 398 return (ENETUNREACH); 399 ifa_ref(ifa); 400 401 bzero(&info, sizeof(info)); 402 info.rti_info[RTAX_DST] = dst; 403 info.rti_info[RTAX_GATEWAY] = gateway; 404 info.rti_ifa = ifa; 405 info.rti_ifp = ifp; 406 info.rti_flags = flags | RTF_HOST | RTF_DYNAMIC; 407 408 /* Setup route metrics to define expire time. */ 409 bzero(&rti_rmx, sizeof(rti_rmx)); 410 /* Set expire time as absolute. */ 411 rti_rmx.rmx_expire = lifetime_sec + time_second; 412 info.rti_mflags |= RTV_EXPIRE; 413 info.rti_rmx = &rti_rmx; 414 415 error = rib_action(fibnum, RTM_ADD, &info, &rc); 416 ifa_free(ifa); 417 418 if (error != 0) { 419 /* TODO: add per-fib redirect stats. */ 420 return (error); 421 } 422 423 RT_LOCK(rc.rc_rt); 424 flags = rc.rc_rt->rt_flags; 425 RT_UNLOCK(rc.rc_rt); 426 427 RTSTAT_INC(rts_dynamic); 428 429 /* Send notification of a route addition to userland. */ 430 bzero(&info, sizeof(info)); 431 info.rti_info[RTAX_DST] = dst; 432 info.rti_info[RTAX_GATEWAY] = gateway; 433 info.rti_info[RTAX_AUTHOR] = author; 434 rt_missmsg_fib(RTM_REDIRECT, &info, flags, error, fibnum); 435 436 return (0); 437 } 438 439 /* 440 * Routing table ioctl interface. 441 */ 442 int 443 rtioctl_fib(u_long req, caddr_t data, u_int fibnum) 444 { 445 446 /* 447 * If more ioctl commands are added here, make sure the proper 448 * super-user checks are being performed because it is possible for 449 * prison-root to make it this far if raw sockets have been enabled 450 * in jails. 451 */ 452 #ifdef INET 453 /* Multicast goop, grrr... */ 454 return mrt_ioctl ? mrt_ioctl(req, data, fibnum) : EOPNOTSUPP; 455 #else /* INET */ 456 return ENXIO; 457 #endif /* INET */ 458 } 459 460 struct ifaddr * 461 ifa_ifwithroute(int flags, const struct sockaddr *dst, 462 const struct sockaddr *gateway, u_int fibnum) 463 { 464 struct ifaddr *ifa; 465 466 NET_EPOCH_ASSERT(); 467 if ((flags & RTF_GATEWAY) == 0) { 468 /* 469 * If we are adding a route to an interface, 470 * and the interface is a pt to pt link 471 * we should search for the destination 472 * as our clue to the interface. Otherwise 473 * we can use the local address. 474 */ 475 ifa = NULL; 476 if (flags & RTF_HOST) 477 ifa = ifa_ifwithdstaddr(dst, fibnum); 478 if (ifa == NULL) 479 ifa = ifa_ifwithaddr(gateway); 480 } else { 481 /* 482 * If we are adding a route to a remote net 483 * or host, the gateway may still be on the 484 * other end of a pt to pt link. 485 */ 486 ifa = ifa_ifwithdstaddr(gateway, fibnum); 487 } 488 if (ifa == NULL) 489 ifa = ifa_ifwithnet(gateway, 0, fibnum); 490 if (ifa == NULL) { 491 struct nhop_object *nh; 492 493 nh = rib_lookup(fibnum, gateway, NHR_NONE, 0); 494 495 /* 496 * dismiss a gateway that is reachable only 497 * through the default router 498 */ 499 if ((nh == NULL) || (nh->nh_flags & NHF_DEFAULT)) 500 return (NULL); 501 ifa = nh->nh_ifa; 502 } 503 if (ifa->ifa_addr->sa_family != dst->sa_family) { 504 struct ifaddr *oifa = ifa; 505 ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp); 506 if (ifa == NULL) 507 ifa = oifa; 508 } 509 510 return (ifa); 511 } 512 513 514 /* 515 * Copy most of @rt data into @info. 516 * 517 * If @flags contains NHR_COPY, copies dst,netmask and gw to the 518 * pointers specified by @info structure. Assume such pointers 519 * are zeroed sockaddr-like structures with sa_len field initialized 520 * to reflect size of the provided buffer. if no NHR_COPY is specified, 521 * point dst,netmask and gw @info fields to appropriate @rt values. 522 * 523 * if @flags contains NHR_REF, do refcouting on rt_ifp and rt_ifa. 524 * 525 * Returns 0 on success. 526 */ 527 int 528 rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, int flags) 529 { 530 struct rt_metrics *rmx; 531 struct sockaddr *src, *dst; 532 struct nhop_object *nh; 533 int sa_len; 534 535 if (flags & NHR_COPY) { 536 /* Copy destination if dst is non-zero */ 537 src = rt_key(rt); 538 dst = info->rti_info[RTAX_DST]; 539 sa_len = src->sa_len; 540 if (dst != NULL) { 541 if (src->sa_len > dst->sa_len) 542 return (ENOMEM); 543 memcpy(dst, src, src->sa_len); 544 info->rti_addrs |= RTA_DST; 545 } 546 547 /* Copy mask if set && dst is non-zero */ 548 src = rt_mask(rt); 549 dst = info->rti_info[RTAX_NETMASK]; 550 if (src != NULL && dst != NULL) { 551 552 /* 553 * Radix stores different value in sa_len, 554 * assume rt_mask() to have the same length 555 * as rt_key() 556 */ 557 if (sa_len > dst->sa_len) 558 return (ENOMEM); 559 memcpy(dst, src, src->sa_len); 560 info->rti_addrs |= RTA_NETMASK; 561 } 562 563 /* Copy gateway is set && dst is non-zero */ 564 src = &rt->rt_nhop->gw_sa; 565 dst = info->rti_info[RTAX_GATEWAY]; 566 if ((rt->rt_flags & RTF_GATEWAY) && src != NULL && dst != NULL){ 567 if (src->sa_len > dst->sa_len) 568 return (ENOMEM); 569 memcpy(dst, src, src->sa_len); 570 info->rti_addrs |= RTA_GATEWAY; 571 } 572 } else { 573 info->rti_info[RTAX_DST] = rt_key(rt); 574 info->rti_addrs |= RTA_DST; 575 if (rt_mask(rt) != NULL) { 576 info->rti_info[RTAX_NETMASK] = rt_mask(rt); 577 info->rti_addrs |= RTA_NETMASK; 578 } 579 if (rt->rt_flags & RTF_GATEWAY) { 580 info->rti_info[RTAX_GATEWAY] = &rt->rt_nhop->gw_sa; 581 info->rti_addrs |= RTA_GATEWAY; 582 } 583 } 584 585 nh = rt->rt_nhop; 586 rmx = info->rti_rmx; 587 if (rmx != NULL) { 588 info->rti_mflags |= RTV_MTU; 589 rmx->rmx_mtu = nh->nh_mtu; 590 } 591 592 info->rti_flags = rt->rt_flags | nhop_get_rtflags(nh); 593 info->rti_ifp = nh->nh_ifp; 594 info->rti_ifa = nh->nh_ifa; 595 if (flags & NHR_REF) { 596 if_ref(info->rti_ifp); 597 ifa_ref(info->rti_ifa); 598 } 599 600 return (0); 601 } 602 603 /* 604 * Lookups up route entry for @dst in RIB database for fib @fibnum. 605 * Exports entry data to @info using rt_exportinfo(). 606 * 607 * If @flags contains NHR_REF, refcouting is performed on rt_ifp and rt_ifa. 608 * All references can be released later by calling rib_free_info(). 609 * 610 * Returns 0 on success. 611 * Returns ENOENT for lookup failure, ENOMEM for export failure. 612 */ 613 int 614 rib_lookup_info(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags, 615 uint32_t flowid, struct rt_addrinfo *info) 616 { 617 RIB_RLOCK_TRACKER; 618 struct rib_head *rh; 619 struct radix_node *rn; 620 struct rtentry *rt; 621 int error; 622 623 KASSERT((fibnum < rt_numfibs), ("rib_lookup_rte: bad fibnum")); 624 rh = rt_tables_get_rnh(fibnum, dst->sa_family); 625 if (rh == NULL) 626 return (ENOENT); 627 628 RIB_RLOCK(rh); 629 rn = rh->rnh_matchaddr(__DECONST(void *, dst), &rh->head); 630 if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) { 631 rt = RNTORT(rn); 632 /* Ensure route & ifp is UP */ 633 if (RT_LINK_IS_UP(rt->rt_nhop->nh_ifp)) { 634 flags = (flags & NHR_REF) | NHR_COPY; 635 error = rt_exportinfo(rt, info, flags); 636 RIB_RUNLOCK(rh); 637 638 return (error); 639 } 640 } 641 RIB_RUNLOCK(rh); 642 643 return (ENOENT); 644 } 645 646 /* 647 * Releases all references acquired by rib_lookup_info() when 648 * called with NHR_REF flags. 649 */ 650 void 651 rib_free_info(struct rt_addrinfo *info) 652 { 653 654 ifa_free(info->rti_ifa); 655 if_rele(info->rti_ifp); 656 } 657 658 /* 659 * Iterates over all existing fibs in system calling 660 * @setwa_f function prior to traversing each fib. 661 * Calls @wa_f function for each element in current fib. 662 * If af is not AF_UNSPEC, iterates over fibs in particular 663 * address family. 664 */ 665 void 666 rt_foreach_fib_walk(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f, 667 void *arg) 668 { 669 struct rib_head *rnh; 670 uint32_t fibnum; 671 int i; 672 673 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 674 /* Do we want some specific family? */ 675 if (af != AF_UNSPEC) { 676 rnh = rt_tables_get_rnh(fibnum, af); 677 if (rnh == NULL) 678 continue; 679 if (setwa_f != NULL) 680 setwa_f(rnh, fibnum, af, arg); 681 682 RIB_WLOCK(rnh); 683 rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg); 684 RIB_WUNLOCK(rnh); 685 continue; 686 } 687 688 for (i = 1; i <= AF_MAX; i++) { 689 rnh = rt_tables_get_rnh(fibnum, i); 690 if (rnh == NULL) 691 continue; 692 if (setwa_f != NULL) 693 setwa_f(rnh, fibnum, i, arg); 694 695 RIB_WLOCK(rnh); 696 rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg); 697 RIB_WUNLOCK(rnh); 698 } 699 } 700 } 701 702 /* 703 * Iterates over all existing fibs in system and deletes each element 704 * for which @filter_f function returns non-zero value. 705 * If @family is not AF_UNSPEC, iterates over fibs in particular 706 * address family. 707 */ 708 void 709 rt_foreach_fib_walk_del(int family, rt_filter_f_t *filter_f, void *arg) 710 { 711 u_int fibnum; 712 int i, start, end; 713 714 for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { 715 /* Do we want some specific family? */ 716 if (family != AF_UNSPEC) { 717 start = family; 718 end = family; 719 } else { 720 start = 1; 721 end = AF_MAX; 722 } 723 724 for (i = start; i <= end; i++) { 725 if (rt_tables_get_rnh(fibnum, i) == NULL) 726 continue; 727 728 rib_walk_del(fibnum, i, filter_f, arg, 0); 729 } 730 } 731 } 732 733 /* 734 * Delete Routes for a Network Interface 735 * 736 * Called for each routing entry via the rnh->rnh_walktree() call above 737 * to delete all route entries referencing a detaching network interface. 738 * 739 * Arguments: 740 * rt pointer to rtentry 741 * nh pointer to nhop 742 * arg argument passed to rnh->rnh_walktree() - detaching interface 743 * 744 * Returns: 745 * 0 successful 746 * errno failed - reason indicated 747 */ 748 static int 749 rt_ifdelroute(const struct rtentry *rt, const struct nhop_object *nh, void *arg) 750 { 751 struct ifnet *ifp = arg; 752 753 if (nh->nh_ifp != ifp) 754 return (0); 755 756 /* 757 * Protect (sorta) against walktree recursion problems 758 * with cloned routes 759 */ 760 if ((rt->rt_flags & RTF_UP) == 0) 761 return (0); 762 763 return (1); 764 } 765 766 /* 767 * Delete all remaining routes using this interface 768 * Unfortuneatly the only way to do this is to slog through 769 * the entire routing table looking for routes which point 770 * to this interface...oh well... 771 */ 772 void 773 rt_flushifroutes_af(struct ifnet *ifp, int af) 774 { 775 KASSERT((af >= 1 && af <= AF_MAX), ("%s: af %d not >= 1 and <= %d", 776 __func__, af, AF_MAX)); 777 778 rt_foreach_fib_walk_del(af, rt_ifdelroute, ifp); 779 } 780 781 void 782 rt_flushifroutes(struct ifnet *ifp) 783 { 784 785 rt_foreach_fib_walk_del(AF_UNSPEC, rt_ifdelroute, ifp); 786 } 787 788 /* 789 * Look up rt_addrinfo for a specific fib. Note that if rti_ifa is defined, 790 * it will be referenced so the caller must free it. 791 * 792 * Assume basic consistency checks are executed by callers: 793 * RTAX_DST exists, if RTF_GATEWAY is set, RTAX_GATEWAY exists as well. 794 */ 795 int 796 rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum) 797 { 798 const struct sockaddr *dst, *gateway, *ifpaddr, *ifaaddr; 799 struct epoch_tracker et; 800 int needref, error, flags; 801 802 dst = info->rti_info[RTAX_DST]; 803 gateway = info->rti_info[RTAX_GATEWAY]; 804 ifpaddr = info->rti_info[RTAX_IFP]; 805 ifaaddr = info->rti_info[RTAX_IFA]; 806 flags = info->rti_flags; 807 808 /* 809 * ifp may be specified by sockaddr_dl 810 * when protocol address is ambiguous. 811 */ 812 error = 0; 813 needref = (info->rti_ifa == NULL); 814 NET_EPOCH_ENTER(et); 815 816 /* If we have interface specified by the ifindex in the address, use it */ 817 if (info->rti_ifp == NULL && ifpaddr != NULL && 818 ifpaddr->sa_family == AF_LINK) { 819 const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifpaddr; 820 if (sdl->sdl_index != 0) 821 info->rti_ifp = ifnet_byindex(sdl->sdl_index); 822 } 823 /* 824 * If we have source address specified, try to find it 825 * TODO: avoid enumerating all ifas on all interfaces. 826 */ 827 if (info->rti_ifa == NULL && ifaaddr != NULL) 828 info->rti_ifa = ifa_ifwithaddr(ifaaddr); 829 if (info->rti_ifa == NULL) { 830 const struct sockaddr *sa; 831 832 /* 833 * Most common use case for the userland-supplied routes. 834 * 835 * Choose sockaddr to select ifa. 836 * -- if ifp is set -- 837 * Order of preference: 838 * 1) IFA address 839 * 2) gateway address 840 * Note: for interface routes link-level gateway address 841 * is specified to indicate the interface index without 842 * specifying RTF_GATEWAY. In this case, ignore gateway 843 * Note: gateway AF may be different from dst AF. In this case, 844 * ignore gateway 845 * 3) final destination. 846 * 4) if all of these fails, try to get at least link-level ifa. 847 * -- else -- 848 * try to lookup gateway or dst in the routing table to get ifa 849 */ 850 if (info->rti_info[RTAX_IFA] != NULL) 851 sa = info->rti_info[RTAX_IFA]; 852 else if ((info->rti_flags & RTF_GATEWAY) != 0 && 853 gateway->sa_family == dst->sa_family) 854 sa = gateway; 855 else 856 sa = dst; 857 if (info->rti_ifp != NULL) { 858 info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp); 859 /* Case 4 */ 860 if (info->rti_ifa == NULL && gateway != NULL) 861 info->rti_ifa = ifaof_ifpforaddr(gateway, info->rti_ifp); 862 } else if (dst != NULL && gateway != NULL) 863 info->rti_ifa = ifa_ifwithroute(flags, dst, gateway, 864 fibnum); 865 else if (sa != NULL) 866 info->rti_ifa = ifa_ifwithroute(flags, sa, sa, 867 fibnum); 868 } 869 if (needref && info->rti_ifa != NULL) { 870 if (info->rti_ifp == NULL) 871 info->rti_ifp = info->rti_ifa->ifa_ifp; 872 ifa_ref(info->rti_ifa); 873 } else 874 error = ENETUNREACH; 875 NET_EPOCH_EXIT(et); 876 return (error); 877 } 878 879 void 880 rt_updatemtu(struct ifnet *ifp) 881 { 882 struct rib_head *rnh; 883 int mtu; 884 int i, j; 885 886 /* 887 * Try to update rt_mtu for all routes using this interface 888 * Unfortunately the only way to do this is to traverse all 889 * routing tables in all fibs/domains. 890 */ 891 for (i = 1; i <= AF_MAX; i++) { 892 mtu = if_getmtu_family(ifp, i); 893 for (j = 0; j < rt_numfibs; j++) { 894 rnh = rt_tables_get_rnh(j, i); 895 if (rnh == NULL) 896 continue; 897 nhops_update_ifmtu(rnh, ifp, mtu); 898 } 899 } 900 } 901 902 903 #if 0 904 int p_sockaddr(char *buf, int buflen, struct sockaddr *s); 905 int rt_print(char *buf, int buflen, struct rtentry *rt); 906 907 int 908 p_sockaddr(char *buf, int buflen, struct sockaddr *s) 909 { 910 void *paddr = NULL; 911 912 switch (s->sa_family) { 913 case AF_INET: 914 paddr = &((struct sockaddr_in *)s)->sin_addr; 915 break; 916 case AF_INET6: 917 paddr = &((struct sockaddr_in6 *)s)->sin6_addr; 918 break; 919 } 920 921 if (paddr == NULL) 922 return (0); 923 924 if (inet_ntop(s->sa_family, paddr, buf, buflen) == NULL) 925 return (0); 926 927 return (strlen(buf)); 928 } 929 930 int 931 rt_print(char *buf, int buflen, struct rtentry *rt) 932 { 933 struct sockaddr *addr, *mask; 934 int i = 0; 935 936 addr = rt_key(rt); 937 mask = rt_mask(rt); 938 939 i = p_sockaddr(buf, buflen, addr); 940 if (!(rt->rt_flags & RTF_HOST)) { 941 buf[i++] = '/'; 942 i += p_sockaddr(buf + i, buflen - i, mask); 943 } 944 945 if (rt->rt_flags & RTF_GATEWAY) { 946 buf[i++] = '>'; 947 i += p_sockaddr(buf + i, buflen - i, &rt->rt_nhop->gw_sa); 948 } 949 950 return (i); 951 } 952 #endif 953 954 #ifdef RADIX_MPATH 955 /* 956 * Deletes key for single-path routes, unlinks rtentry with 957 * gateway specified in @info from multi-path routes. 958 * 959 * Returnes unlinked entry. In case of failure, returns NULL 960 * and sets @perror to ESRCH. 961 */ 962 struct radix_node * 963 rt_mpath_unlink(struct rib_head *rnh, struct rt_addrinfo *info, 964 struct rtentry *rto, int *perror) 965 { 966 /* 967 * if we got multipath routes, we require users to specify 968 * a matching RTAX_GATEWAY. 969 */ 970 struct rtentry *rt; // *rto = NULL; 971 struct radix_node *rn; 972 struct sockaddr *gw; 973 974 gw = info->rti_info[RTAX_GATEWAY]; 975 rt = rt_mpath_matchgate(rto, gw); 976 if (rt == NULL) { 977 *perror = ESRCH; 978 return (NULL); 979 } 980 981 /* 982 * this is the first entry in the chain 983 */ 984 if (rto == rt) { 985 rn = rn_mpath_next((struct radix_node *)rt); 986 /* 987 * there is another entry, now it's active 988 */ 989 if (rn) { 990 rto = RNTORT(rn); 991 RT_LOCK(rto); 992 rto->rt_flags |= RTF_UP; 993 RT_UNLOCK(rto); 994 } else if (rt->rt_flags & RTF_GATEWAY) { 995 /* 996 * For gateway routes, we need to 997 * make sure that we we are deleting 998 * the correct gateway. 999 * rt_mpath_matchgate() does not 1000 * check the case when there is only 1001 * one route in the chain. 1002 */ 1003 if (gw && 1004 (rt->rt_nhop->gw_sa.sa_len != gw->sa_len || 1005 memcmp(&rt->rt_nhop->gw_sa, gw, gw->sa_len))) { 1006 *perror = ESRCH; 1007 return (NULL); 1008 } 1009 } 1010 1011 /* 1012 * use the normal delete code to remove 1013 * the first entry 1014 */ 1015 rn = rnh->rnh_deladdr(info->rti_info[RTAX_DST], 1016 info->rti_info[RTAX_NETMASK], 1017 &rnh->head); 1018 if (rn != NULL) { 1019 *perror = 0; 1020 } else { 1021 *perror = ESRCH; 1022 } 1023 return (rn); 1024 } 1025 1026 /* 1027 * if the entry is 2nd and on up 1028 */ 1029 if (rt_mpath_deldup(rto, rt) == 0) 1030 panic ("rtrequest1: rt_mpath_deldup"); 1031 *perror = 0; 1032 rn = (struct radix_node *)rt; 1033 return (rn); 1034 } 1035 #endif 1036 1037 void 1038 rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt) 1039 { 1040 1041 if (info->rti_mflags & RTV_WEIGHT) 1042 rt->rt_weight = info->rti_rmx->rmx_weight; 1043 /* Kernel -> userland timebase conversion. */ 1044 if (info->rti_mflags & RTV_EXPIRE) 1045 rt->rt_expire = info->rti_rmx->rmx_expire ? 1046 info->rti_rmx->rmx_expire - time_second + time_uptime : 0; 1047 } 1048 1049 void 1050 rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask) 1051 { 1052 u_char *cp1 = (u_char *)src; 1053 u_char *cp2 = (u_char *)dst; 1054 u_char *cp3 = (u_char *)netmask; 1055 u_char *cplim = cp2 + *cp3; 1056 u_char *cplim2 = cp2 + *cp1; 1057 1058 *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */ 1059 cp3 += 2; 1060 if (cplim > cplim2) 1061 cplim = cplim2; 1062 while (cp2 < cplim) 1063 *cp2++ = *cp1++ & *cp3++; 1064 if (cp2 < cplim2) 1065 bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2)); 1066 } 1067 1068 /* 1069 * Set up a routing table entry, normally 1070 * for an interface. 1071 */ 1072 #define _SOCKADDR_TMPSIZE 128 /* Not too big.. kernel stack size is limited */ 1073 static inline int 1074 rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) 1075 { 1076 RIB_RLOCK_TRACKER; 1077 struct epoch_tracker et; 1078 struct sockaddr *dst; 1079 struct sockaddr *netmask; 1080 struct rib_cmd_info rc; 1081 struct rt_addrinfo info; 1082 int error = 0; 1083 int startfib, endfib; 1084 char tempbuf[_SOCKADDR_TMPSIZE]; 1085 int didwork = 0; 1086 int a_failure = 0; 1087 struct sockaddr_dl_short *sdl = NULL; 1088 struct rib_head *rnh; 1089 1090 if (flags & RTF_HOST) { 1091 dst = ifa->ifa_dstaddr; 1092 netmask = NULL; 1093 } else { 1094 dst = ifa->ifa_addr; 1095 netmask = ifa->ifa_netmask; 1096 } 1097 if (dst->sa_len == 0) 1098 return(EINVAL); 1099 switch (dst->sa_family) { 1100 case AF_INET6: 1101 case AF_INET: 1102 /* We support multiple FIBs. */ 1103 break; 1104 default: 1105 fibnum = RT_DEFAULT_FIB; 1106 break; 1107 } 1108 if (fibnum == RT_ALL_FIBS) { 1109 if (V_rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) 1110 startfib = endfib = ifa->ifa_ifp->if_fib; 1111 else { 1112 startfib = 0; 1113 endfib = rt_numfibs - 1; 1114 } 1115 } else { 1116 KASSERT((fibnum < rt_numfibs), ("rtinit1: bad fibnum")); 1117 startfib = fibnum; 1118 endfib = fibnum; 1119 } 1120 1121 /* 1122 * If it's a delete, check that if it exists, 1123 * it's on the correct interface or we might scrub 1124 * a route to another ifa which would 1125 * be confusing at best and possibly worse. 1126 */ 1127 if (cmd == RTM_DELETE) { 1128 /* 1129 * It's a delete, so it should already exist.. 1130 * If it's a net, mask off the host bits 1131 * (Assuming we have a mask) 1132 * XXX this is kinda inet specific.. 1133 */ 1134 if (netmask != NULL) { 1135 rt_maskedcopy(dst, (struct sockaddr *)tempbuf, netmask); 1136 dst = (struct sockaddr *)tempbuf; 1137 } 1138 } else if (cmd == RTM_ADD) { 1139 sdl = (struct sockaddr_dl_short *)tempbuf; 1140 bzero(sdl, sizeof(struct sockaddr_dl_short)); 1141 sdl->sdl_family = AF_LINK; 1142 sdl->sdl_len = sizeof(struct sockaddr_dl_short); 1143 sdl->sdl_type = ifa->ifa_ifp->if_type; 1144 sdl->sdl_index = ifa->ifa_ifp->if_index; 1145 } 1146 /* 1147 * Now go through all the requested tables (fibs) and do the 1148 * requested action. Realistically, this will either be fib 0 1149 * for protocols that don't do multiple tables or all the 1150 * tables for those that do. 1151 */ 1152 for ( fibnum = startfib; fibnum <= endfib; fibnum++) { 1153 if (cmd == RTM_DELETE) { 1154 struct radix_node *rn; 1155 /* 1156 * Look up an rtentry that is in the routing tree and 1157 * contains the correct info. 1158 */ 1159 rnh = rt_tables_get_rnh(fibnum, dst->sa_family); 1160 if (rnh == NULL) 1161 /* this table doesn't exist but others might */ 1162 continue; 1163 RIB_RLOCK(rnh); 1164 rn = rnh->rnh_lookup(dst, netmask, &rnh->head); 1165 #ifdef RADIX_MPATH 1166 if (rt_mpath_capable(rnh)) { 1167 1168 if (rn == NULL) 1169 error = ESRCH; 1170 else { 1171 struct rtentry *rt = RNTORT(rn); 1172 /* 1173 * for interface route the gateway 1174 * gateway is sockaddr_dl, so 1175 * rt_mpath_matchgate must use the 1176 * interface address 1177 */ 1178 rt = rt_mpath_matchgate(rt, 1179 ifa->ifa_addr); 1180 if (rt == NULL) 1181 error = ESRCH; 1182 } 1183 } 1184 #endif 1185 error = (rn == NULL || 1186 (rn->rn_flags & RNF_ROOT) || 1187 RNTORT(rn)->rt_nhop->nh_ifa != ifa); 1188 RIB_RUNLOCK(rnh); 1189 if (error) { 1190 /* this is only an error if bad on ALL tables */ 1191 continue; 1192 } 1193 } 1194 /* 1195 * Do the actual request 1196 */ 1197 bzero((caddr_t)&info, sizeof(info)); 1198 info.rti_ifa = ifa; 1199 info.rti_flags = flags | 1200 (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED; 1201 info.rti_info[RTAX_DST] = dst; 1202 /* 1203 * doing this for compatibility reasons 1204 */ 1205 if (cmd == RTM_ADD) 1206 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)sdl; 1207 else 1208 info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; 1209 info.rti_info[RTAX_NETMASK] = netmask; 1210 NET_EPOCH_ENTER(et); 1211 error = rib_action(fibnum, cmd, &info, &rc); 1212 if (error == 0 && rc.rc_rt != NULL) { 1213 /* 1214 * notify any listening routing agents of the change 1215 */ 1216 1217 /* TODO: interface routes/aliases */ 1218 rt_newaddrmsg_fib(cmd, ifa, rc.rc_rt, fibnum); 1219 didwork = 1; 1220 } 1221 NET_EPOCH_EXIT(et); 1222 if (error) 1223 a_failure = error; 1224 } 1225 if (cmd == RTM_DELETE) { 1226 if (didwork) { 1227 error = 0; 1228 } else { 1229 /* we only give an error if it wasn't in any table */ 1230 error = ((flags & RTF_HOST) ? 1231 EHOSTUNREACH : ENETUNREACH); 1232 } 1233 } else { 1234 if (a_failure) { 1235 /* return an error if any of them failed */ 1236 error = a_failure; 1237 } 1238 } 1239 return (error); 1240 } 1241 1242 /* 1243 * Set up a routing table entry, normally 1244 * for an interface. 1245 */ 1246 int 1247 rtinit(struct ifaddr *ifa, int cmd, int flags) 1248 { 1249 struct sockaddr *dst; 1250 int fib = RT_DEFAULT_FIB; 1251 1252 if (flags & RTF_HOST) { 1253 dst = ifa->ifa_dstaddr; 1254 } else { 1255 dst = ifa->ifa_addr; 1256 } 1257 1258 switch (dst->sa_family) { 1259 case AF_INET6: 1260 case AF_INET: 1261 /* We do support multiple FIBs. */ 1262 fib = RT_ALL_FIBS; 1263 break; 1264 } 1265 return (rtinit1(ifa, cmd, flags, fib)); 1266 } 1267 1268 /* 1269 * Announce interface address arrival/withdraw 1270 * Returns 0 on success. 1271 */ 1272 int 1273 rt_addrmsg(int cmd, struct ifaddr *ifa, int fibnum) 1274 { 1275 1276 KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, 1277 ("unexpected cmd %d", cmd)); 1278 KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), 1279 ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); 1280 1281 EVENTHANDLER_DIRECT_INVOKE(rt_addrmsg, ifa, cmd); 1282 return (rtsock_addrmsg(cmd, ifa, fibnum)); 1283 } 1284 1285 /* 1286 * Announce kernel-originated route addition/removal to rtsock based on @rt data. 1287 * cmd: RTM_ cmd 1288 * @rt: valid rtentry 1289 * @ifp: target route interface 1290 * @fibnum: fib id or RT_ALL_FIBS 1291 * 1292 * Returns 0 on success. 1293 */ 1294 int 1295 rt_routemsg(int cmd, struct rtentry *rt, struct ifnet *ifp, int rti_addrs, 1296 int fibnum) 1297 { 1298 1299 KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, 1300 ("unexpected cmd %d", cmd)); 1301 1302 KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), 1303 ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); 1304 1305 KASSERT(rt_key(rt) != NULL, (":%s: rt_key must be supplied", __func__)); 1306 1307 return (rtsock_routemsg(cmd, rt, ifp, 0, fibnum)); 1308 } 1309 1310 /* 1311 * Announce kernel-originated route addition/removal to rtsock based on @rt data. 1312 * cmd: RTM_ cmd 1313 * @info: addrinfo structure with valid data. 1314 * @fibnum: fib id or RT_ALL_FIBS 1315 * 1316 * Returns 0 on success. 1317 */ 1318 int 1319 rt_routemsg_info(int cmd, struct rt_addrinfo *info, int fibnum) 1320 { 1321 1322 KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE || cmd == RTM_CHANGE, 1323 ("unexpected cmd %d", cmd)); 1324 1325 KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), 1326 ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); 1327 1328 KASSERT(info->rti_info[RTAX_DST] != NULL, (":%s: RTAX_DST must be supplied", __func__)); 1329 1330 return (rtsock_routemsg_info(cmd, info, fibnum)); 1331 } 1332 1333 1334 /* 1335 * This is called to generate messages from the routing socket 1336 * indicating a network interface has had addresses associated with it. 1337 */ 1338 void 1339 rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, struct rtentry *rt, int fibnum) 1340 { 1341 1342 KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE, 1343 ("unexpected cmd %u", cmd)); 1344 KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs), 1345 ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs)); 1346 1347 if (cmd == RTM_ADD) { 1348 rt_addrmsg(cmd, ifa, fibnum); 1349 if (rt != NULL) 1350 rt_routemsg(cmd, rt, ifa->ifa_ifp, 0, fibnum); 1351 } else { 1352 if (rt != NULL) 1353 rt_routemsg(cmd, rt, ifa->ifa_ifp, 0, fibnum); 1354 rt_addrmsg(cmd, ifa, fibnum); 1355 } 1356 } 1357 1358