1 /* 2 * Copyright (c) 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (C) 2017 THL A29 Limited, a Tencent company. 5 * 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 * 4. 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 * Copied part from FreeBSD rtsock.c. 32 * 33 */ 34 35 #include <sys/param.h> 36 #include <sys/proc.h> 37 #include <sys/jail.h> 38 #include <sys/kernel.h> 39 #include <sys/domain.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/priv.h> 45 #include <sys/rmlock.h> 46 47 #include <net/if.h> 48 #include <net/if_var.h> 49 #include <net/if_dl.h> 50 #include <net/if_llatbl.h> 51 #include <net/if_types.h> 52 #include <net/route.h> 53 #include <net/route/route_var.h> 54 #include <net/route/route_ctl.h> 55 #include <net/route/nhgrp_var.h> 56 #include <netinet/if_ether.h> 57 #ifdef INET6 58 #include <netinet6/scope6_var.h> 59 #include <netinet6/ip6_var.h> 60 #include <netinet6/in6_var.h> 61 #endif 62 63 #include "ff_api.h" 64 #include "ff_host_interface.h" 65 66 #ifndef _SOCKADDR_UNION_DEFINED 67 #define _SOCKADDR_UNION_DEFINED 68 /* 69 * The union of all possible address formats we handle. 70 */ 71 union sockaddr_union { 72 struct sockaddr sa; 73 struct sockaddr_in sin; 74 struct sockaddr_in6 sin6; 75 }; 76 #endif /* _SOCKADDR_UNION_DEFINED */ 77 78 static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, }; 79 80 struct walkarg { 81 int w_tmemsize; 82 int w_op, w_arg; 83 caddr_t w_tmem; 84 struct sysctl_req *w_req; 85 }; 86 87 /* 88 * Extract the addresses of the passed sockaddrs. 89 * Do a little sanity checking so as to avoid bad memory references. 90 * This data is derived straight from userland. 91 */ 92 static int 93 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 94 { 95 struct sockaddr *sa; 96 int i; 97 98 for (i = 0; i < RTAX_MAX && cp < cplim; i++) { 99 if ((rtinfo->rti_addrs & (1 << i)) == 0) 100 continue; 101 sa = (struct sockaddr *)cp; 102 /* 103 * It won't fit. 104 */ 105 if (cp + sa->sa_len > cplim) 106 return (EINVAL); 107 /* 108 * there are no more.. quit now 109 * If there are more bits, they are in error. 110 * I've seen this. route(1) can evidently generate these. 111 * This causes kernel to core dump. 112 * for compatibility, If we see this, point to a safe address. 113 */ 114 if (sa->sa_len == 0) { 115 rtinfo->rti_info[i] = &sa_zero; 116 return (0); /* should be EINVAL but for compat */ 117 } 118 /* accept it */ 119 #ifdef INET6 120 if (sa->sa_family == AF_INET6) 121 sa6_embedscope((struct sockaddr_in6 *)sa, 122 V_ip6_use_defzone); 123 #endif 124 rtinfo->rti_info[i] = sa; 125 cp += SA_SIZE(sa); 126 } 127 return (0); 128 } 129 130 static inline void 131 fill_sockaddr_inet(struct sockaddr_in *sin, struct in_addr addr) 132 { 133 const struct sockaddr_in nsin = { 134 .sin_family = AF_INET, 135 .sin_len = sizeof(struct sockaddr_in), 136 .sin_addr = addr, 137 }; 138 *sin = nsin; 139 } 140 141 #ifdef INET6 142 static inline void 143 fill_sockaddr_inet6(struct sockaddr_in6 *sin6, const struct in6_addr *addr6, 144 uint32_t scopeid) 145 { 146 147 const struct sockaddr_in6 nsin6 = { 148 .sin6_family = AF_INET6, 149 .sin6_len = sizeof(struct sockaddr_in6), 150 .sin6_addr = *addr6, 151 .sin6_scope_id = scopeid, 152 }; 153 *sin6 = nsin6; 154 } 155 #endif 156 157 /* 158 * Checks if gateway is suitable for lltable operations. 159 * Lltable code requires AF_LINK gateway with ifindex 160 * and mac address specified. 161 * Returns 0 on success. 162 */ 163 static int 164 cleanup_xaddrs_lladdr(struct rt_addrinfo *info) 165 { 166 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY]; 167 168 if (sdl->sdl_family != AF_LINK) 169 return (EINVAL); 170 171 if (sdl->sdl_index == 0) 172 return (EINVAL); 173 174 if (offsetof(struct sockaddr_dl, sdl_data) + sdl->sdl_nlen + sdl->sdl_alen > sdl->sdl_len) 175 return (EINVAL); 176 177 return (0); 178 } 179 180 static int 181 cleanup_xaddrs_gateway(struct rt_addrinfo *info) 182 { 183 struct sockaddr *gw = info->rti_info[RTAX_GATEWAY]; 184 185 if (info->rti_flags & RTF_LLDATA) 186 return (cleanup_xaddrs_lladdr(info)); 187 188 switch (gw->sa_family) { 189 case AF_INET: 190 { 191 struct sockaddr_in *gw_sin = (struct sockaddr_in *)gw; 192 if (gw_sin->sin_len < sizeof(struct sockaddr_in)) { 193 printf("gw sin_len too small\n"); 194 return (EINVAL); 195 } 196 fill_sockaddr_inet(gw_sin, gw_sin->sin_addr); 197 } 198 break; 199 #ifdef INET6 200 case AF_INET6: 201 { 202 struct sockaddr_in6 *gw_sin6 = (struct sockaddr_in6 *)gw; 203 if (gw_sin6->sin6_len < sizeof(struct sockaddr_in6)) { 204 printf("gw sin6_len too small\n"); 205 return (EINVAL); 206 } 207 fill_sockaddr_inet6(gw_sin6, &gw_sin6->sin6_addr, 0); 208 break; 209 } 210 #endif 211 case AF_LINK: 212 { 213 struct sockaddr_dl_short *gw_sdl; 214 215 gw_sdl = (struct sockaddr_dl_short *)gw; 216 if (gw_sdl->sdl_len < sizeof(struct sockaddr_dl_short)) { 217 printf("gw sdl_len too small\n"); 218 return (EINVAL); 219 } 220 221 const struct sockaddr_dl_short sdl = { 222 .sdl_family = AF_LINK, 223 .sdl_len = sizeof(struct sockaddr_dl_short), 224 .sdl_index = gw_sdl->sdl_index, 225 }; 226 *gw_sdl = sdl; 227 break; 228 } 229 } 230 231 return (0); 232 } 233 234 static void 235 remove_netmask(struct rt_addrinfo *info) 236 { 237 info->rti_info[RTAX_NETMASK] = NULL; 238 info->rti_flags |= RTF_HOST; 239 info->rti_addrs &= ~RTA_NETMASK; 240 } 241 242 static int 243 cleanup_xaddrs_inet(struct rt_addrinfo *info) 244 { 245 struct sockaddr_in *dst_sa, *mask_sa; 246 247 /* Check & fixup dst/netmask combination first */ 248 dst_sa = (struct sockaddr_in *)info->rti_info[RTAX_DST]; 249 mask_sa = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 250 251 struct in_addr mask = { 252 .s_addr = mask_sa ? mask_sa->sin_addr.s_addr : INADDR_BROADCAST, 253 }; 254 struct in_addr dst = { 255 .s_addr = htonl(ntohl(dst_sa->sin_addr.s_addr) & ntohl(mask.s_addr)) 256 }; 257 258 if (dst_sa->sin_len < sizeof(struct sockaddr_in)) { 259 printf("dst sin_len too small\n"); 260 return (EINVAL); 261 } 262 if (mask_sa && mask_sa->sin_len < sizeof(struct sockaddr_in)) { 263 printf("mask sin_len too small\n"); 264 return (EINVAL); 265 } 266 fill_sockaddr_inet(dst_sa, dst); 267 268 if (mask.s_addr != INADDR_BROADCAST) 269 fill_sockaddr_inet(mask_sa, mask); 270 else 271 remove_netmask(info); 272 273 /* Check gateway */ 274 if (info->rti_info[RTAX_GATEWAY] != NULL) 275 return (cleanup_xaddrs_gateway(info)); 276 277 return (0); 278 } 279 280 #ifdef INET6 281 static int 282 cleanup_xaddrs_inet6(struct rt_addrinfo *info) 283 { 284 struct sockaddr_in6 *dst_sa, *mask_sa; 285 struct in6_addr mask; 286 287 /* Check & fixup dst/netmask combination first */ 288 dst_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_DST]; 289 mask_sa = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 290 291 mask = mask_sa ? mask_sa->sin6_addr : in6mask128; 292 IN6_MASK_ADDR(&dst_sa->sin6_addr, &mask); 293 294 if (dst_sa->sin6_len < sizeof(struct sockaddr_in6)) { 295 printf("dst sin6_len too small\n"); 296 return (EINVAL); 297 } 298 if (mask_sa && mask_sa->sin6_len < sizeof(struct sockaddr_in6)) { 299 printf("mask sin6_len too small\n"); 300 return (EINVAL); 301 } 302 fill_sockaddr_inet6(dst_sa, &dst_sa->sin6_addr, 0); 303 304 if (!IN6_ARE_ADDR_EQUAL(&mask, &in6mask128)) 305 fill_sockaddr_inet6(mask_sa, &mask, 0); 306 else 307 remove_netmask(info); 308 309 /* Check gateway */ 310 if (info->rti_info[RTAX_GATEWAY] != NULL) 311 return (cleanup_xaddrs_gateway(info)); 312 313 return (0); 314 } 315 #endif 316 317 static int 318 cleanup_xaddrs(struct rt_addrinfo *info) 319 { 320 int error = EAFNOSUPPORT; 321 322 if (info->rti_info[RTAX_DST] == NULL) 323 return (EINVAL); 324 325 if (info->rti_flags & RTF_LLDATA) { 326 /* 327 * arp(8)/ndp(8) sends RTA_NETMASK for the associated 328 * prefix along with the actual address in RTA_DST. 329 * Remove netmask to avoid unnecessary address masking. 330 */ 331 remove_netmask(info); 332 } 333 334 switch (info->rti_info[RTAX_DST]->sa_family) { 335 case AF_INET: 336 error = cleanup_xaddrs_inet(info); 337 break; 338 #ifdef INET6 339 case AF_INET6: 340 error = cleanup_xaddrs_inet6(info); 341 break; 342 #endif 343 } 344 345 return (error); 346 } 347 348 static int 349 rtm_get_jailed(struct rt_addrinfo *info, struct ifnet *ifp, 350 struct nhop_object *nh, union sockaddr_union *saun, struct ucred *cred) 351 { 352 #if defined(INET) || defined(INET6) 353 struct epoch_tracker et; 354 #endif 355 356 /* First, see if the returned address is part of the jail. */ 357 if (prison_if(cred, nh->nh_ifa->ifa_addr) == 0) { 358 info->rti_info[RTAX_IFA] = nh->nh_ifa->ifa_addr; 359 return (0); 360 } 361 362 switch (info->rti_info[RTAX_DST]->sa_family) { 363 case AF_INET: 364 { 365 struct in_addr ia; 366 struct ifaddr *ifa; 367 int found; 368 369 found = 0; 370 /* 371 * Try to find an address on the given outgoing interface 372 * that belongs to the jail. 373 */ 374 NET_EPOCH_ENTER(et); 375 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 376 struct sockaddr *sa; 377 sa = ifa->ifa_addr; 378 if (sa->sa_family != AF_INET) 379 continue; 380 ia = ((struct sockaddr_in *)sa)->sin_addr; 381 if (prison_check_ip4(cred, &ia) == 0) { 382 found = 1; 383 break; 384 } 385 } 386 NET_EPOCH_EXIT(et); 387 if (!found) { 388 /* 389 * As a last resort return the 'default' jail address. 390 */ 391 ia = ((struct sockaddr_in *)nh->nh_ifa->ifa_addr)-> 392 sin_addr; 393 if (prison_get_ip4(cred, &ia) != 0) 394 return (ESRCH); 395 } 396 bzero(&saun->sin, sizeof(struct sockaddr_in)); 397 saun->sin.sin_len = sizeof(struct sockaddr_in); 398 saun->sin.sin_family = AF_INET; 399 saun->sin.sin_addr.s_addr = ia.s_addr; 400 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin; 401 break; 402 } 403 #ifdef INET6 404 case AF_INET6: 405 { 406 struct in6_addr ia6; 407 struct ifaddr *ifa; 408 int found; 409 410 found = 0; 411 /* 412 * Try to find an address on the given outgoing interface 413 * that belongs to the jail. 414 */ 415 NET_EPOCH_ENTER(et); 416 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 417 struct sockaddr *sa; 418 sa = ifa->ifa_addr; 419 if (sa->sa_family != AF_INET6) 420 continue; 421 bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr, 422 &ia6, sizeof(struct in6_addr)); 423 if (prison_check_ip6(cred, &ia6) == 0) { 424 found = 1; 425 break; 426 } 427 } 428 NET_EPOCH_EXIT(et); 429 if (!found) { 430 /* 431 * As a last resort return the 'default' jail address. 432 */ 433 ia6 = ((struct sockaddr_in6 *)nh->nh_ifa->ifa_addr)-> 434 sin6_addr; 435 if (prison_get_ip6(cred, &ia6) != 0) 436 return (ESRCH); 437 } 438 bzero(&saun->sin6, sizeof(struct sockaddr_in6)); 439 saun->sin6.sin6_len = sizeof(struct sockaddr_in6); 440 saun->sin6.sin6_family = AF_INET6; 441 bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr)); 442 if (sa6_recoverscope(&saun->sin6) != 0) 443 return (ESRCH); 444 info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6; 445 break; 446 } 447 #endif 448 default: 449 return (ESRCH); 450 } 451 return (0); 452 } 453 454 static int 455 fill_blackholeinfo(struct rt_addrinfo *info, union sockaddr_union *saun) 456 { 457 struct ifaddr *ifa; 458 sa_family_t saf; 459 460 if (V_loif == NULL) { 461 printf("Unable to add blackhole/reject nhop without loopback"); 462 return (ENOTSUP); 463 } 464 info->rti_ifp = V_loif; 465 466 saf = info->rti_info[RTAX_DST]->sa_family; 467 468 CK_STAILQ_FOREACH(ifa, &info->rti_ifp->if_addrhead, ifa_link) { 469 if (ifa->ifa_addr->sa_family == saf) { 470 info->rti_ifa = ifa; 471 break; 472 } 473 } 474 if (info->rti_ifa == NULL) 475 return (ENOTSUP); 476 477 bzero(saun, sizeof(union sockaddr_union)); 478 switch (saf) { 479 case AF_INET: 480 saun->sin.sin_family = AF_INET; 481 saun->sin.sin_len = sizeof(struct sockaddr_in); 482 saun->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 483 break; 484 #ifdef INET6 485 case AF_INET6: 486 saun->sin6.sin6_family = AF_INET6; 487 saun->sin6.sin6_len = sizeof(struct sockaddr_in6); 488 saun->sin6.sin6_addr = in6addr_loopback; 489 break; 490 #endif 491 default: 492 return (ENOTSUP); 493 } 494 info->rti_info[RTAX_GATEWAY] = &saun->sa; 495 info->rti_flags |= RTF_GATEWAY; 496 497 return (0); 498 } 499 500 /* 501 * Fills in @info based on userland-provided @rtm message. 502 * 503 * Returns 0 on success. 504 */ 505 static int 506 fill_addrinfo(struct rt_msghdr *rtm, int len, u_int fibnum, struct rt_addrinfo *info) 507 { 508 int error; 509 sa_family_t saf; 510 511 rtm->rtm_pid = curproc->p_pid; 512 info->rti_addrs = rtm->rtm_addrs; 513 514 info->rti_mflags = rtm->rtm_inits; 515 info->rti_rmx = &rtm->rtm_rmx; 516 517 /* 518 * rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6 519 * link-local address because rtrequest requires addresses with 520 * embedded scope id. 521 */ 522 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, info)) 523 return (EINVAL); 524 525 if (rtm->rtm_flags & RTF_RNH_LOCKED) 526 return (EINVAL); 527 info->rti_flags = rtm->rtm_flags; 528 error = cleanup_xaddrs(info); 529 if (error != 0) 530 return (error); 531 saf = info->rti_info[RTAX_DST]->sa_family; 532 /* 533 * Verify that the caller has the appropriate privilege; RTM_GET 534 * is the only operation the non-superuser is allowed. 535 */ 536 if (rtm->rtm_type != RTM_GET) { 537 error = priv_check(curthread, PRIV_NET_ROUTE); 538 if (error != 0) 539 return (error); 540 } 541 542 /* 543 * The given gateway address may be an interface address. 544 * For example, issuing a "route change" command on a route 545 * entry that was created from a tunnel, and the gateway 546 * address given is the local end point. In this case the 547 * RTF_GATEWAY flag must be cleared or the destination will 548 * not be reachable even though there is no error message. 549 */ 550 if (info->rti_info[RTAX_GATEWAY] != NULL && 551 info->rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) { 552 struct rt_addrinfo ginfo; 553 struct sockaddr *gdst; 554 struct sockaddr_storage ss; 555 556 bzero(&ginfo, sizeof(ginfo)); 557 bzero(&ss, sizeof(ss)); 558 ss.ss_len = sizeof(ss); 559 560 ginfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&ss; 561 gdst = info->rti_info[RTAX_GATEWAY]; 562 563 /* 564 * A host route through the loopback interface is 565 * installed for each interface adddress. In pre 8.0 566 * releases the interface address of a PPP link type 567 * is not reachable locally. This behavior is fixed as 568 * part of the new L2/L3 redesign and rewrite work. The 569 * signature of this interface address route is the 570 * AF_LINK sa_family type of the gateway, and the 571 * rt_ifp has the IFF_LOOPBACK flag set. 572 */ 573 if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) { 574 if (ss.ss_family == AF_LINK && 575 ginfo.rti_ifp->if_flags & IFF_LOOPBACK) { 576 info->rti_flags &= ~RTF_GATEWAY; 577 info->rti_flags |= RTF_GWFLAG_COMPAT; 578 } 579 rib_free_info(&ginfo); 580 } 581 } 582 583 return (0); 584 } 585 586 /* 587 * Returns pointer to array of nexthops with weights for 588 * given @nhg. Stores number of items in the array into @pnum_nhops. 589 */ 590 struct weightened_nhop * 591 nhgrp_get_nhops(struct nhgrp_object *nhg, uint32_t *pnum_nhops) 592 { 593 struct nhgrp_priv *nhg_priv; 594 595 KASSERT(((nhg->nhg_flags & MPF_MULTIPATH) != 0), ("nhop is not mpath")); 596 597 nhg_priv = NHGRP_PRIV(nhg); 598 *pnum_nhops = nhg_priv->nhg_nh_count; 599 600 return (nhg_priv->nhg_nh_weights); 601 } 602 603 static struct nhop_object * 604 select_nhop(struct nhop_object *nh, const struct sockaddr *gw) 605 { 606 if (!NH_IS_NHGRP(nh)) 607 return (nh); 608 #ifdef ROUTE_MPATH 609 struct weightened_nhop *wn; 610 uint32_t num_nhops; 611 wn = nhgrp_get_nhops((struct nhgrp_object *)nh, &num_nhops); 612 if (gw == NULL) 613 return (wn[0].nh); 614 for (int i = 0; i < num_nhops; i++) { 615 if (match_nhop_gw(wn[i].nh, gw)) 616 return (wn[i].nh); 617 } 618 #endif 619 return (NULL); 620 } 621 622 /* 623 * Handles RTM_GET message from routing socket, returning matching rt. 624 * 625 * Returns: 626 * 0 on success, with locked and referenced matching rt in @rt_nrt 627 * errno of failure 628 */ 629 static int 630 handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, 631 struct rt_msghdr *rtm, struct rib_cmd_info *rc) 632 { 633 RIB_RLOCK_TRACKER; 634 struct rib_head *rnh; 635 struct nhop_object *nh; 636 sa_family_t saf; 637 638 saf = info->rti_info[RTAX_DST]->sa_family; 639 640 rnh = rt_tables_get_rnh(fibnum, saf); 641 if (rnh == NULL) 642 return (EAFNOSUPPORT); 643 644 RIB_RLOCK(rnh); 645 646 /* 647 * By (implicit) convention host route (one without netmask) 648 * means longest-prefix-match request and the route with netmask 649 * means exact-match lookup. 650 * As cleanup_xaddrs() cleans up info flags&addrs for the /32,/128 651 * prefixes, use original data to check for the netmask presence. 652 */ 653 if ((rtm->rtm_addrs & RTA_NETMASK) == 0) { 654 /* 655 * Provide longest prefix match for 656 * address lookup (no mask). 657 * 'route -n get addr' 658 */ 659 rc->rc_rt = (struct rtentry *) rnh->rnh_matchaddr( 660 info->rti_info[RTAX_DST], &rnh->head); 661 } else 662 rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( 663 info->rti_info[RTAX_DST], 664 info->rti_info[RTAX_NETMASK], &rnh->head); 665 666 if (rc->rc_rt == NULL) { 667 RIB_RUNLOCK(rnh); 668 return (ESRCH); 669 } 670 671 nh = select_nhop(rt_get_raw_nhop(rc->rc_rt), info->rti_info[RTAX_GATEWAY]); 672 if (nh == NULL) { 673 RIB_RUNLOCK(rnh); 674 return (ESRCH); 675 } 676 /* 677 * If performing proxied L2 entry insertion, and 678 * the actual PPP host entry is found, perform 679 * another search to retrieve the prefix route of 680 * the local end point of the PPP link. 681 * TODO: move this logic to userland. 682 */ 683 if (rtm->rtm_flags & RTF_ANNOUNCE) { 684 struct sockaddr laddr; 685 686 if (nh->nh_ifp != NULL && 687 nh->nh_ifp->if_type == IFT_PROPVIRTUAL) { 688 struct ifaddr *ifa; 689 690 ifa = ifa_ifwithnet(info->rti_info[RTAX_DST], 1, 691 RT_ALL_FIBS); 692 if (ifa != NULL) 693 rt_maskedcopy(ifa->ifa_addr, 694 &laddr, 695 ifa->ifa_netmask); 696 } else 697 rt_maskedcopy(nh->nh_ifa->ifa_addr, 698 &laddr, 699 nh->nh_ifa->ifa_netmask); 700 /* 701 * refactor rt and no lock operation necessary 702 */ 703 rc->rc_rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, 704 &rnh->head); 705 if (rc->rc_rt == NULL) { 706 RIB_RUNLOCK(rnh); 707 return (ESRCH); 708 } 709 nh = select_nhop(rt_get_raw_nhop(rc->rc_rt), info->rti_info[RTAX_GATEWAY]); 710 if (nh == NULL) { 711 RIB_RUNLOCK(rnh); 712 return (ESRCH); 713 } 714 } 715 rc->rc_nh_new = nh; 716 rc->rc_nh_weight = rc->rc_rt->rt_weight; 717 RIB_RUNLOCK(rnh); 718 719 return (0); 720 } 721 722 /* 723 * Writes information related to @rtinfo object to preallocated buffer. 724 * Stores needed size in @plen. If @w is NULL, calculates size without 725 * writing. 726 * Used for sysctl dumps and rtsock answers (RTM_DEL/RTM_GET) generation. 727 * 728 * Returns 0 on success. 729 * 730 */ 731 static int 732 rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int *plen) 733 { 734 int i; 735 int len, buflen = 0, dlen; 736 caddr_t cp = NULL; 737 struct rt_msghdr *rtm = NULL; 738 #ifdef INET6 739 struct sockaddr_storage ss; 740 struct sockaddr_in6 *sin6; 741 #endif 742 743 switch (type) { 744 745 case RTM_DELADDR: 746 case RTM_NEWADDR: 747 if (w != NULL && w->w_op == NET_RT_IFLISTL) { 748 #ifdef COMPAT_FREEBSD32 749 if (w->w_req->flags & SCTL_MASK32) 750 len = sizeof(struct ifa_msghdrl32); 751 else 752 #endif 753 len = sizeof(struct ifa_msghdrl); 754 } else 755 len = sizeof(struct ifa_msghdr); 756 break; 757 758 case RTM_IFINFO: 759 #ifdef COMPAT_FREEBSD32 760 if (w != NULL && w->w_req->flags & SCTL_MASK32) { 761 if (w->w_op == NET_RT_IFLISTL) 762 len = sizeof(struct if_msghdrl32); 763 else 764 len = sizeof(struct if_msghdr32); 765 break; 766 } 767 #endif 768 if (w != NULL && w->w_op == NET_RT_IFLISTL) 769 len = sizeof(struct if_msghdrl); 770 else 771 len = sizeof(struct if_msghdr); 772 break; 773 774 case RTM_NEWMADDR: 775 len = sizeof(struct ifma_msghdr); 776 break; 777 778 default: 779 len = sizeof(struct rt_msghdr); 780 } 781 782 if (w != NULL) { 783 rtm = (struct rt_msghdr *)w->w_tmem; 784 buflen = w->w_tmemsize - len; 785 cp = (caddr_t)w->w_tmem + len; 786 } 787 788 rtinfo->rti_addrs = 0; 789 for (i = 0; i < RTAX_MAX; i++) { 790 struct sockaddr *sa; 791 792 if ((sa = rtinfo->rti_info[i]) == NULL) 793 continue; 794 rtinfo->rti_addrs |= (1 << i); 795 dlen = SA_SIZE(sa); 796 if (cp != NULL && buflen >= dlen) { 797 #ifdef INET6 798 if (sa->sa_family == AF_INET6) { 799 sin6 = (struct sockaddr_in6 *)&ss; 800 bcopy(sa, sin6, sizeof(*sin6)); 801 if (sa6_recoverscope(sin6) == 0) 802 sa = (struct sockaddr *)sin6; 803 } 804 #endif 805 bcopy((caddr_t)sa, cp, (unsigned)dlen); 806 cp += dlen; 807 buflen -= dlen; 808 } else if (cp != NULL) { 809 /* 810 * Buffer too small. Count needed size 811 * and return with error. 812 */ 813 cp = NULL; 814 } 815 816 len += dlen; 817 } 818 819 if (cp != NULL) { 820 dlen = ALIGN(len) - len; 821 if (buflen < dlen) 822 cp = NULL; 823 else 824 buflen -= dlen; 825 } 826 len = ALIGN(len); 827 828 if (cp != NULL) { 829 /* fill header iff buffer is large enough */ 830 rtm->rtm_version = RTM_VERSION; 831 rtm->rtm_type = type; 832 rtm->rtm_msglen = len; 833 } 834 835 *plen = len; 836 837 if (w != NULL && cp == NULL) 838 return (ENOBUFS); 839 840 return (0); 841 } 842 843 #if 0 844 /* 845 * Fill in @dmask with valid netmask leaving original @smask 846 * intact. Mostly used with radix netmasks. 847 */ 848 struct sockaddr * 849 rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask, 850 struct sockaddr_storage *dmask) 851 { 852 if (dst == NULL || smask == NULL) 853 return (NULL); 854 855 memset(dmask, 0, dst->sa_len); 856 memcpy(dmask, smask, smask->sa_len); 857 dmask->ss_len = dst->sa_len; 858 dmask->ss_family = dst->sa_family; 859 860 return ((struct sockaddr *)dmask); 861 } 862 #endif 863 864 static void 865 rt_getmetrics(const struct rtentry *rt, const struct nhop_object *nh, 866 struct rt_metrics *out) 867 { 868 869 bzero(out, sizeof(*out)); 870 out->rmx_mtu = nh->nh_mtu; 871 out->rmx_weight = rt->rt_weight; 872 out->rmx_nhidx = nhop_get_idx(nh); 873 /* Kernel -> userland timebase conversion. */ 874 out->rmx_expire = rt->rt_expire ? 875 rt->rt_expire - time_uptime + time_second : 0; 876 } 877 878 static void 879 init_sockaddrs_family(int family, struct sockaddr *dst, struct sockaddr *mask) 880 { 881 if (family == AF_INET) { 882 struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; 883 struct sockaddr_in *mask4 = (struct sockaddr_in *)mask; 884 885 bzero(dst4, sizeof(struct sockaddr_in)); 886 bzero(mask4, sizeof(struct sockaddr_in)); 887 888 dst4->sin_family = AF_INET; 889 dst4->sin_len = sizeof(struct sockaddr_in); 890 mask4->sin_family = AF_INET; 891 mask4->sin_len = sizeof(struct sockaddr_in); 892 } 893 #ifdef INET6 894 if (family == AF_INET6) { 895 struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; 896 struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask; 897 898 bzero(dst6, sizeof(struct sockaddr_in6)); 899 bzero(mask6, sizeof(struct sockaddr_in6)); 900 901 dst6->sin6_family = AF_INET6; 902 dst6->sin6_len = sizeof(struct sockaddr_in6); 903 mask6->sin6_family = AF_INET6; 904 mask6->sin6_len = sizeof(struct sockaddr_in6); 905 } 906 #endif 907 } 908 909 static void 910 export_rtaddrs(const struct rtentry *rt, struct sockaddr *dst, 911 struct sockaddr *mask) 912 { 913 if (dst->sa_family == AF_INET) { 914 struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; 915 struct sockaddr_in *mask4 = (struct sockaddr_in *)mask; 916 uint32_t scopeid = 0; 917 rt_get_inet_prefix_pmask(rt, &dst4->sin_addr, &mask4->sin_addr, 918 &scopeid); 919 return; 920 } 921 #ifdef INET6 922 if (dst->sa_family == AF_INET6) { 923 struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; 924 struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask; 925 uint32_t scopeid = 0; 926 rt_get_inet6_prefix_pmask(rt, &dst6->sin6_addr, 927 &mask6->sin6_addr, &scopeid); 928 dst6->sin6_scope_id = scopeid; 929 return; 930 } 931 #endif 932 } 933 934 static int 935 update_rtm_from_rc(struct rt_addrinfo *info, struct rt_msghdr **prtm, 936 int alloc_len, struct rib_cmd_info *rc, struct nhop_object *nh, unsigned maxlen) 937 { 938 struct walkarg w; 939 union sockaddr_union saun; 940 struct rt_msghdr *rtm, *orig_rtm = NULL; 941 struct ifnet *ifp; 942 int error, len; 943 944 rtm = *prtm; 945 union sockaddr_union sa_dst, sa_mask; 946 int family = info->rti_info[RTAX_DST]->sa_family; 947 init_sockaddrs_family(family, &sa_dst.sa, &sa_mask.sa); 948 export_rtaddrs(rc->rc_rt, &sa_dst.sa, &sa_mask.sa); 949 950 info->rti_info[RTAX_DST] = &sa_dst.sa; 951 info->rti_info[RTAX_NETMASK] = rt_is_host(rc->rc_rt) ? NULL : &sa_mask.sa; 952 info->rti_info[RTAX_GATEWAY] = &nh->gw_sa; 953 info->rti_info[RTAX_GENMASK] = 0; 954 ifp = nh->nh_ifp; 955 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 956 if (ifp) { 957 info->rti_info[RTAX_IFP] = 958 ifp->if_addr->ifa_addr; 959 error = rtm_get_jailed(info, ifp, nh, 960 &saun, curthread->td_ucred); 961 if (error != 0) 962 return (error); 963 if (ifp->if_flags & IFF_POINTOPOINT) 964 info->rti_info[RTAX_BRD] = 965 nh->nh_ifa->ifa_dstaddr; 966 rtm->rtm_index = ifp->if_index; 967 } else { 968 info->rti_info[RTAX_IFP] = NULL; 969 info->rti_info[RTAX_IFA] = NULL; 970 } 971 } else if (ifp != NULL) 972 rtm->rtm_index = ifp->if_index; 973 974 /* Check if we need to realloc storage */ 975 rtsock_msg_buffer(rtm->rtm_type, info, NULL, &len); 976 if (len > maxlen) { 977 return (ENOBUFS); 978 } 979 980 if (len > alloc_len) { 981 struct rt_msghdr *tmp_rtm; 982 983 tmp_rtm = malloc(len, M_TEMP, M_NOWAIT); 984 if (tmp_rtm == NULL) 985 return (ENOBUFS); 986 bcopy(rtm, tmp_rtm, rtm->rtm_msglen); 987 orig_rtm = rtm; 988 rtm = tmp_rtm; 989 alloc_len = len; 990 991 /* 992 * Delay freeing original rtm as info contains 993 * data referencing it. 994 */ 995 } 996 997 w.w_tmem = (caddr_t)rtm; 998 w.w_tmemsize = alloc_len; 999 rtsock_msg_buffer(rtm->rtm_type, info, &w, &len); 1000 1001 rtm->rtm_flags = rc->rc_rt->rte_flags | nhop_get_rtflags(nh); 1002 if (rtm->rtm_flags & RTF_GWFLAG_COMPAT) 1003 rtm->rtm_flags = RTF_GATEWAY | 1004 (rtm->rtm_flags & ~RTF_GWFLAG_COMPAT); 1005 rt_getmetrics(rc->rc_rt, nh, &rtm->rtm_rmx); 1006 rtm->rtm_rmx.rmx_weight = rc->rc_nh_weight; 1007 rtm->rtm_addrs = info->rti_addrs; 1008 1009 if (orig_rtm != NULL) 1010 free(orig_rtm, M_TEMP); 1011 *prtm = rtm; 1012 1013 return (0); 1014 } 1015 1016 /* 1017 * Checks if rte can be exported v.r.t jails/vnets. 1018 * 1019 * Returns 1 if it can, 0 otherwise. 1020 */ 1021 static bool 1022 can_export_rte(struct ucred *td_ucred, bool rt_is_host, 1023 const struct sockaddr *rt_dst) 1024 { 1025 1026 if ((!rt_is_host) ? jailed_without_vnet(td_ucred) 1027 : prison_if(td_ucred, rt_dst) != 0) 1028 return (false); 1029 return (true); 1030 } 1031 1032 int 1033 ff_rtioctl(int fibnum, void *data, unsigned *plen, unsigned maxlen) 1034 { 1035 struct rt_msghdr *rtm = NULL; 1036 struct rtentry *rt = NULL; 1037 struct rt_addrinfo info; 1038 struct epoch_tracker et; 1039 #ifdef INET6 1040 struct sockaddr_storage ss; 1041 struct sockaddr_in6 *sin6; 1042 int i, rti_need_deembed = 0; 1043 #endif 1044 int alloc_len = 0, len, error = 0; 1045 sa_family_t saf = AF_UNSPEC; 1046 struct rib_cmd_info rc; 1047 struct nhop_object *nh; 1048 1049 #define senderr(e) { error = e; goto flush;} 1050 1051 len = *plen; 1052 1053 /* 1054 * Most of current messages are in range 200-240 bytes, 1055 * minimize possible re-allocation on reply using larger size 1056 * buffer aligned on 1k boundaty. 1057 */ 1058 alloc_len = roundup2(len, 1024); 1059 if ((rtm = malloc(alloc_len, M_TEMP, M_NOWAIT)) == NULL) 1060 senderr(ENOBUFS); 1061 1062 bcopy(data, (caddr_t)rtm, len); 1063 1064 if (len < sizeof(*rtm) || len != rtm->rtm_msglen) 1065 senderr(EINVAL); 1066 1067 bzero(&info, sizeof(info)); 1068 nh = NULL; 1069 1070 if (rtm->rtm_version != RTM_VERSION) { 1071 /* Do not touch message since format is unknown */ 1072 free(rtm, M_TEMP); 1073 rtm = NULL; 1074 senderr(EPROTONOSUPPORT); 1075 } 1076 1077 /* 1078 * Starting from here, it is possible 1079 * to alter original message and insert 1080 * caller PID and error value. 1081 */ 1082 1083 if ((error = fill_addrinfo(rtm, len, fibnum, &info)) != 0) { 1084 senderr(error); 1085 } 1086 1087 saf = info.rti_info[RTAX_DST]->sa_family; 1088 1089 /* support for new ARP code */ 1090 if (rtm->rtm_flags & RTF_LLDATA) { 1091 error = lla_rt_output(rtm, &info); 1092 #ifdef INET6 1093 if (error == 0) 1094 rti_need_deembed = 1; 1095 #endif 1096 goto flush; 1097 } 1098 1099 union sockaddr_union gw_saun; 1100 int blackhole_flags = rtm->rtm_flags & (RTF_BLACKHOLE|RTF_REJECT); 1101 if (blackhole_flags != 0) { 1102 if (blackhole_flags != (RTF_BLACKHOLE | RTF_REJECT)) 1103 error = fill_blackholeinfo(&info, &gw_saun); 1104 else 1105 error = EINVAL; 1106 if (error != 0) 1107 senderr(error); 1108 /* TODO: rebuild rtm from scratch */ 1109 } 1110 1111 switch (rtm->rtm_type) { 1112 case RTM_ADD: 1113 case RTM_CHANGE: 1114 if (rtm->rtm_type == RTM_ADD) { 1115 if (info.rti_info[RTAX_GATEWAY] == NULL) 1116 senderr(EINVAL); 1117 } 1118 error = rib_action(fibnum, rtm->rtm_type, &info, &rc); 1119 if (error == 0) { 1120 #ifdef INET6 1121 rti_need_deembed = 1; 1122 #endif 1123 #ifdef ROUTE_MPATH 1124 if (NH_IS_NHGRP(rc.rc_nh_new) || 1125 (rc.rc_nh_old && NH_IS_NHGRP(rc.rc_nh_old))) { 1126 struct rib_cmd_info rc_simple = {}; 1127 rib_decompose_notification(&rc, 1128 save_add_notification, (void *)&rc_simple); 1129 rc = rc_simple; 1130 } 1131 #endif 1132 nh = rc.rc_nh_new; 1133 rtm->rtm_index = nh->nh_ifp->if_index; 1134 rtm->rtm_flags = rc.rc_rt->rte_flags | nhop_get_rtflags(nh); 1135 } 1136 break; 1137 1138 case RTM_DELETE: 1139 error = rib_action(fibnum, RTM_DELETE, &info, &rc); 1140 if (error == 0) { 1141 #ifdef ROUTE_MPATH 1142 if (NH_IS_NHGRP(rc.rc_nh_old) || 1143 (rc.rc_nh_new && NH_IS_NHGRP(rc.rc_nh_new))) { 1144 struct rib_cmd_info rc_simple = {}; 1145 rib_decompose_notification(&rc, 1146 save_del_notification, (void *)&rc_simple); 1147 rc = rc_simple; 1148 } 1149 #endif 1150 nh = rc.rc_nh_old; 1151 goto report; 1152 } 1153 #ifdef INET6 1154 /* rt_msg2() will not be used when RTM_DELETE fails. */ 1155 rti_need_deembed = 1; 1156 #endif 1157 break; 1158 1159 case RTM_GET: 1160 error = handle_rtm_get(&info, fibnum, rtm, &rc); 1161 if (error != 0) 1162 senderr(error); 1163 nh = rc.rc_nh_new; 1164 1165 report: 1166 if (!can_export_rte(curthread->td_ucred, 1167 info.rti_info[RTAX_NETMASK] == NULL, 1168 info.rti_info[RTAX_DST])) { 1169 senderr(ESRCH); 1170 } 1171 1172 error = update_rtm_from_rc(&info, &rtm, alloc_len, &rc, nh, maxlen); 1173 /* 1174 * Note that some sockaddr pointers may have changed to 1175 * point to memory outsize @rtm. Some may be pointing 1176 * to the on-stack variables. 1177 * Given that, any pointer in @info CANNOT BE USED. 1178 */ 1179 1180 /* 1181 * scopeid deembedding has been performed while 1182 * writing updated rtm in rtsock_msg_buffer(). 1183 * With that in mind, skip deembedding procedure below. 1184 */ 1185 #ifdef INET6 1186 rti_need_deembed = 0; 1187 #endif 1188 if (error != 0) 1189 senderr(error); 1190 break; 1191 1192 default: 1193 senderr(EOPNOTSUPP); 1194 } 1195 1196 flush: 1197 NET_EPOCH_EXIT(et); 1198 rt = NULL; 1199 1200 if (rtm != NULL) { 1201 #ifdef INET6 1202 if (rti_need_deembed) { 1203 /* sin6_scope_id is recovered before sending rtm. */ 1204 sin6 = (struct sockaddr_in6 *)&ss; 1205 for (i = 0; i < RTAX_MAX; i++) { 1206 if (info.rti_info[i] == NULL) 1207 continue; 1208 if (info.rti_info[i]->sa_family != AF_INET6) 1209 continue; 1210 bcopy(info.rti_info[i], sin6, sizeof(*sin6)); 1211 if (sa6_recoverscope(sin6) == 0) 1212 bcopy(sin6, info.rti_info[i], 1213 sizeof(*sin6)); 1214 } 1215 } 1216 #endif 1217 if (error != 0) 1218 rtm->rtm_errno = error; 1219 else 1220 rtm->rtm_flags |= RTF_DONE; 1221 1222 bcopy((caddr_t)rtm, data, rtm->rtm_msglen); 1223 *plen = rtm->rtm_msglen; 1224 free(rtm, M_TEMP); 1225 } 1226 1227 if (error != 0) { 1228 ff_os_errno(error); 1229 return (-1); 1230 } 1231 1232 return (error); 1233 } 1234 1235 #if 0 1236 int 1237 ff_rtioctl_old(int fibnum, void *data, unsigned *plen, unsigned maxlen) 1238 { 1239 struct rt_msghdr *rtm = NULL; 1240 struct rtentry *rt = NULL; 1241 struct rib_head *rnh; 1242 struct rt_addrinfo info; 1243 union sockaddr_union saun; 1244 sa_family_t saf = AF_UNSPEC; 1245 struct sockaddr_storage ss; 1246 struct walkarg w; 1247 int error = 0, alloc_len = 0, len; 1248 struct ifnet *ifp = NULL; 1249 1250 #ifdef INET6 1251 struct sockaddr_in6 *sin6; 1252 int i, rti_need_deembed = 0; 1253 #endif 1254 1255 #define senderr(e) { error = e; goto flush;} 1256 1257 len = *plen; 1258 /* 1259 * Most of current messages are in range 200-240 bytes, 1260 * minimize possible re-allocation on reply using larger size 1261 * buffer aligned on 1k boundaty. 1262 */ 1263 alloc_len = roundup2(len, 1024); 1264 if ((rtm = malloc(alloc_len, M_TEMP, M_NOWAIT)) == NULL) 1265 senderr(ENOBUFS); 1266 bcopy(data, (caddr_t)rtm, len); 1267 1268 if (len < sizeof(*rtm) || len != rtm->rtm_msglen) 1269 senderr(EINVAL); 1270 1271 bzero(&info, sizeof(info)); 1272 bzero(&w, sizeof(w)); 1273 1274 if (rtm->rtm_version != RTM_VERSION) 1275 senderr(EPROTONOSUPPORT); 1276 1277 /* 1278 * Starting from here, it is possible 1279 * to alter original message and insert 1280 * caller PID and error value. 1281 */ 1282 1283 rtm->rtm_pid = curproc->p_pid; 1284 info.rti_addrs = rtm->rtm_addrs; 1285 1286 info.rti_mflags = rtm->rtm_inits; 1287 info.rti_rmx = &rtm->rtm_rmx; 1288 1289 /* 1290 * rt_xaddrs() performs s6_addr[2] := sin6_scope_id for AF_INET6 1291 * link-local address because rtrequest requires addresses with 1292 * embedded scope id. 1293 */ 1294 if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) 1295 senderr(EINVAL); 1296 1297 info.rti_flags = rtm->rtm_flags; 1298 if (info.rti_info[RTAX_DST] == NULL || 1299 info.rti_info[RTAX_DST]->sa_family >= AF_MAX || 1300 (info.rti_info[RTAX_GATEWAY] != NULL && 1301 info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) 1302 senderr(EINVAL); 1303 saf = info.rti_info[RTAX_DST]->sa_family; 1304 1305 /* 1306 * The given gateway address may be an interface address. 1307 * For example, issuing a "route change" command on a route 1308 * entry that was created from a tunnel, and the gateway 1309 * address given is the local end point. In this case the 1310 * RTF_GATEWAY flag must be cleared or the destination will 1311 * not be reachable even though there is no error message. 1312 */ 1313 if (info.rti_info[RTAX_GATEWAY] != NULL && 1314 info.rti_info[RTAX_GATEWAY]->sa_family != AF_LINK) { 1315 struct rt_addrinfo ginfo; 1316 struct sockaddr *gdst; 1317 1318 bzero(&ginfo, sizeof(ginfo)); 1319 bzero(&ss, sizeof(ss)); 1320 ss.ss_len = sizeof(ss); 1321 1322 ginfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&ss; 1323 gdst = info.rti_info[RTAX_GATEWAY]; 1324 1325 /* 1326 * A host route through the loopback interface is 1327 * installed for each interface adddress. In pre 8.0 1328 * releases the interface address of a PPP link type 1329 * is not reachable locally. This behavior is fixed as 1330 * part of the new L2/L3 redesign and rewrite work. The 1331 * signature of this interface address route is the 1332 * AF_LINK sa_family type of the rt_gateway, and the 1333 * rt_ifp has the IFF_LOOPBACK flag set. 1334 */ 1335 if (rib_lookup_info(fibnum, gdst, NHR_REF, 0, &ginfo) == 0) { 1336 if (ss.ss_family == AF_LINK && 1337 ginfo.rti_ifp->if_flags & IFF_LOOPBACK) { 1338 info.rti_flags &= ~RTF_GATEWAY; 1339 info.rti_flags |= RTF_GWFLAG_COMPAT; 1340 } 1341 rib_free_info(&ginfo); 1342 } 1343 } 1344 1345 switch (rtm->rtm_type) { 1346 struct rtentry *saved_nrt; 1347 1348 case RTM_ADD: 1349 case RTM_CHANGE: 1350 if (info.rti_info[RTAX_GATEWAY] == NULL) 1351 senderr(EINVAL); 1352 saved_nrt = NULL; 1353 1354 /* support for new ARP code */ 1355 if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK && 1356 (rtm->rtm_flags & RTF_LLDATA) != 0) { 1357 error = lla_rt_output(rtm, &info); 1358 #ifdef INET6 1359 if (error == 0) 1360 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0; 1361 #endif 1362 break; 1363 } 1364 error = rtrequest1_fib(rtm->rtm_type, &info, &saved_nrt, 1365 fibnum); 1366 if (error == 0 && saved_nrt != NULL) { 1367 #ifdef INET6 1368 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0; 1369 #endif 1370 RT_LOCK(saved_nrt); 1371 rtm->rtm_index = saved_nrt->rt_ifp->if_index; 1372 RT_REMREF(saved_nrt); 1373 RT_UNLOCK(saved_nrt); 1374 } 1375 break; 1376 1377 case RTM_DELETE: 1378 saved_nrt = NULL; 1379 /* support for new ARP code */ 1380 if (info.rti_info[RTAX_GATEWAY] && 1381 (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) && 1382 (rtm->rtm_flags & RTF_LLDATA) != 0) { 1383 error = lla_rt_output(rtm, &info); 1384 #ifdef INET6 1385 if (error == 0) 1386 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0; 1387 #endif 1388 break; 1389 } 1390 error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt, fibnum); 1391 if (error == 0) { 1392 RT_LOCK(saved_nrt); 1393 rt = saved_nrt; 1394 goto report; 1395 } 1396 #ifdef INET6 1397 /* rt_msg2() will not be used when RTM_DELETE fails. */ 1398 rti_need_deembed = (V_deembed_scopeid) ? 1 : 0; 1399 #endif 1400 break; 1401 1402 case RTM_GET: 1403 rnh = rt_tables_get_rnh(fibnum, saf); 1404 if (rnh == NULL) 1405 senderr(EAFNOSUPPORT); 1406 1407 RIB_RLOCK(rnh); 1408 1409 if (info.rti_info[RTAX_NETMASK] == NULL && 1410 rtm->rtm_type == RTM_GET) { 1411 /* 1412 * Provide logest prefix match for 1413 * address lookup (no mask). 1414 * 'route -n get addr' 1415 */ 1416 rt = (struct rtentry *) rnh->rnh_matchaddr( 1417 info.rti_info[RTAX_DST], &rnh->head); 1418 } else 1419 rt = (struct rtentry *) rnh->rnh_lookup( 1420 info.rti_info[RTAX_DST], 1421 info.rti_info[RTAX_NETMASK], &rnh->head); 1422 1423 if (rt == NULL) { 1424 RIB_RUNLOCK(rnh); 1425 senderr(ESRCH); 1426 } 1427 #ifdef RADIX_MPATH 1428 /* 1429 * for RTM_CHANGE/LOCK, if we got multipath routes, 1430 * we require users to specify a matching RTAX_GATEWAY. 1431 * 1432 * for RTM_GET, gate is optional even with multipath. 1433 * if gate == NULL the first match is returned. 1434 * (no need to call rt_mpath_matchgate if gate == NULL) 1435 */ 1436 if (rt_mpath_capable(rnh) && 1437 (rtm->rtm_type != RTM_GET || info.rti_info[RTAX_GATEWAY])) { 1438 rt = rt_mpath_matchgate(rt, info.rti_info[RTAX_GATEWAY]); 1439 if (!rt) { 1440 RIB_RUNLOCK(rnh); 1441 senderr(ESRCH); 1442 } 1443 } 1444 #endif 1445 /* 1446 * If performing proxied L2 entry insertion, and 1447 * the actual PPP host entry is found, perform 1448 * another search to retrieve the prefix route of 1449 * the local end point of the PPP link. 1450 */ 1451 if (rtm->rtm_flags & RTF_ANNOUNCE) { 1452 struct sockaddr laddr; 1453 1454 if (rt->rt_ifp != NULL && 1455 rt->rt_ifp->if_type == IFT_PROPVIRTUAL) { 1456 struct ifaddr *ifa; 1457 1458 ifa = ifa_ifwithnet(info.rti_info[RTAX_DST], 1, 1459 RT_ALL_FIBS); 1460 if (ifa != NULL) 1461 rt_maskedcopy(ifa->ifa_addr, 1462 &laddr, 1463 ifa->ifa_netmask); 1464 } else 1465 rt_maskedcopy(rt->rt_ifa->ifa_addr, 1466 &laddr, 1467 rt->rt_ifa->ifa_netmask); 1468 /* 1469 * refactor rt and no lock operation necessary 1470 */ 1471 rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, 1472 &rnh->head); 1473 if (rt == NULL) { 1474 RIB_RUNLOCK(rnh); 1475 senderr(ESRCH); 1476 } 1477 } 1478 RT_LOCK(rt); 1479 RT_ADDREF(rt); 1480 RIB_RUNLOCK(rnh); 1481 1482 report: 1483 RT_LOCK_ASSERT(rt); 1484 if ((rt->rt_flags & RTF_HOST) == 0 1485 ? jailed_without_vnet(curthread->td_ucred) 1486 : prison_if(curthread->td_ucred, 1487 rt_key(rt)) != 0) { 1488 RT_UNLOCK(rt); 1489 senderr(ESRCH); 1490 } 1491 info.rti_info[RTAX_DST] = rt_key(rt); 1492 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1493 info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), 1494 rt_mask(rt), &ss); 1495 info.rti_info[RTAX_GENMASK] = 0; 1496 if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { 1497 ifp = rt->rt_ifp; 1498 if (ifp) { 1499 info.rti_info[RTAX_IFP] = 1500 ifp->if_addr->ifa_addr; 1501 error = rtm_get_jailed(&info, ifp, rt, 1502 &saun, curthread->td_ucred); 1503 if (error != 0) { 1504 RT_UNLOCK(rt); 1505 senderr(error); 1506 } 1507 if (ifp->if_flags & IFF_POINTOPOINT) 1508 info.rti_info[RTAX_BRD] = 1509 rt->rt_ifa->ifa_dstaddr; 1510 rtm->rtm_index = ifp->if_index; 1511 } else { 1512 info.rti_info[RTAX_IFP] = NULL; 1513 info.rti_info[RTAX_IFA] = NULL; 1514 } 1515 } else if ((ifp = rt->rt_ifp) != NULL) { 1516 rtm->rtm_index = ifp->if_index; 1517 } 1518 1519 /* Check if we need to realloc storage */ 1520 rtsock_msg_buffer(rtm->rtm_type, &info, NULL, &len); 1521 if (len > maxlen) { 1522 RT_UNLOCK(rt); 1523 senderr(ENOBUFS); 1524 } 1525 1526 if (len > alloc_len) { 1527 struct rt_msghdr *new_rtm; 1528 new_rtm = malloc(len, M_TEMP, M_NOWAIT); 1529 if (new_rtm == NULL) { 1530 RT_UNLOCK(rt); 1531 senderr(ENOBUFS); 1532 } 1533 bcopy(rtm, new_rtm, rtm->rtm_msglen); 1534 free(rtm, M_TEMP); 1535 rtm = new_rtm; 1536 alloc_len = len; 1537 } 1538 1539 w.w_tmem = (caddr_t)rtm; 1540 w.w_tmemsize = alloc_len; 1541 rtsock_msg_buffer(rtm->rtm_type, &info, &w, &len); 1542 1543 if (rt->rt_flags & RTF_GWFLAG_COMPAT) 1544 rtm->rtm_flags = RTF_GATEWAY | 1545 (rt->rt_flags & ~RTF_GWFLAG_COMPAT); 1546 else 1547 rtm->rtm_flags = rt->rt_flags; 1548 rt_getmetrics(rt, &rtm->rtm_rmx); 1549 rtm->rtm_addrs = info.rti_addrs; 1550 1551 RT_UNLOCK(rt); 1552 break; 1553 1554 default: 1555 senderr(EOPNOTSUPP); 1556 } 1557 1558 flush: 1559 if (rt != NULL) 1560 RTFREE(rt); 1561 1562 if (rtm != NULL) { 1563 #ifdef INET6 1564 if (rti_need_deembed) { 1565 /* sin6_scope_id is recovered before sending rtm. */ 1566 sin6 = (struct sockaddr_in6 *)&ss; 1567 for (i = 0; i < RTAX_MAX; i++) { 1568 if (info.rti_info[i] == NULL) 1569 continue; 1570 if (info.rti_info[i]->sa_family != AF_INET6) 1571 continue; 1572 bcopy(info.rti_info[i], sin6, sizeof(*sin6)); 1573 if (sa6_recoverscope(sin6) == 0) 1574 bcopy(sin6, info.rti_info[i], 1575 sizeof(*sin6)); 1576 } 1577 } 1578 #endif 1579 if (error != 0) 1580 rtm->rtm_errno = error; 1581 else 1582 rtm->rtm_flags |= RTF_DONE; 1583 1584 bcopy((caddr_t)rtm, data, rtm->rtm_msglen); 1585 *plen = rtm->rtm_msglen; 1586 free(rtm, M_TEMP); 1587 } 1588 1589 if (error != 0) { 1590 ff_os_errno(error); 1591 return (-1); 1592 } 1593 1594 return (error); 1595 } 1596 #endif 1597