1 /* $NetBSD: rtsock.c,v 1.173 2015/08/07 08:11:33 ozaki-r Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 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 * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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 32 /* 33 * Copyright (c) 1988, 1991, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.173 2015/08/07 08:11:33 ozaki-r Exp $"); 65 66 #ifdef _KERNEL_OPT 67 #include "opt_inet.h" 68 #include "opt_mpls.h" 69 #include "opt_compat_netbsd.h" 70 #endif 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/proc.h> 75 #include <sys/socket.h> 76 #include <sys/socketvar.h> 77 #include <sys/domain.h> 78 #include <sys/protosw.h> 79 #include <sys/sysctl.h> 80 #include <sys/kauth.h> 81 #include <sys/kmem.h> 82 #include <sys/intr.h> 83 #ifdef RTSOCK_DEBUG 84 #include <netinet/in.h> 85 #endif /* RTSOCK_DEBUG */ 86 87 #include <net/if.h> 88 #include <net/route.h> 89 #include <net/raw_cb.h> 90 91 #include <netmpls/mpls.h> 92 93 #if defined(COMPAT_14) || defined(COMPAT_50) 94 #include <compat/net/if.h> 95 #include <compat/net/route.h> 96 #endif 97 #ifdef COMPAT_RTSOCK 98 #define RTM_XVERSION RTM_OVERSION 99 #define RT_XADVANCE(a,b) RT_OADVANCE(a,b) 100 #define RT_XROUNDUP(n) RT_OROUNDUP(n) 101 #define PF_XROUTE PF_OROUTE 102 #define rt_xmsghdr rt_msghdr50 103 #define if_xmsghdr if_msghdr /* if_msghdr50 is for RTM_OIFINFO */ 104 #define ifa_xmsghdr ifa_msghdr50 105 #define if_xannouncemsghdr if_announcemsghdr50 106 #define COMPATNAME(x) compat_50_ ## x 107 #define DOMAINNAME "oroute" 108 CTASSERT(sizeof(struct ifa_xmsghdr) == 20); 109 DOMAIN_DEFINE(compat_50_routedomain); /* forward declare and add to link set */ 110 #else /* COMPAT_RTSOCK */ 111 #define RTM_XVERSION RTM_VERSION 112 #define RT_XADVANCE(a,b) RT_ADVANCE(a,b) 113 #define RT_XROUNDUP(n) RT_ROUNDUP(n) 114 #define PF_XROUTE PF_ROUTE 115 #define rt_xmsghdr rt_msghdr 116 #define if_xmsghdr if_msghdr 117 #define ifa_xmsghdr ifa_msghdr 118 #define if_xannouncemsghdr if_announcemsghdr 119 #define COMPATNAME(x) x 120 #define DOMAINNAME "route" 121 CTASSERT(sizeof(struct ifa_xmsghdr) == 24); 122 #ifdef COMPAT_50 123 #define COMPATCALL(name, args) compat_50_ ## name args 124 #endif 125 DOMAIN_DEFINE(routedomain); /* forward declare and add to link set */ 126 #undef COMPAT_50 127 #undef COMPAT_14 128 #endif /* COMPAT_RTSOCK */ 129 130 #ifndef COMPATCALL 131 #define COMPATCALL(name, args) do { } while (/*CONSTCOND*/ 0) 132 #endif 133 134 #ifdef RTSOCK_DEBUG 135 #define RT_IN_PRINT(b, a) (in_print((b), sizeof(b), \ 136 &((const struct sockaddr_in *)info.rti_info[(a)])->sin_addr), (b)) 137 #endif /* RTSOCK_DEBUG */ 138 139 struct route_info COMPATNAME(route_info) = { 140 .ri_dst = { .sa_len = 2, .sa_family = PF_XROUTE, }, 141 .ri_src = { .sa_len = 2, .sa_family = PF_XROUTE, }, 142 .ri_maxqlen = IFQ_MAXLEN, 143 }; 144 145 #define PRESERVED_RTF (RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK) 146 147 static void COMPATNAME(route_init)(void); 148 static int COMPATNAME(route_output)(struct mbuf *, ...); 149 150 static int rt_msg2(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *); 151 static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *); 152 static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int, 153 struct rt_addrinfo *); 154 static void rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *); 155 static void rtm_setmetrics(const struct rtentry *, struct rt_xmsghdr *); 156 static void sysctl_net_route_setup(struct sysctllog **); 157 static int sysctl_dumpentry(struct rtentry *, void *); 158 static int sysctl_iflist(int, struct rt_walkarg *, int); 159 static int sysctl_rtable(SYSCTLFN_PROTO); 160 static void rt_adjustcount(int, int); 161 162 static void 163 rt_adjustcount(int af, int cnt) 164 { 165 struct route_cb * const cb = &COMPATNAME(route_info).ri_cb; 166 167 cb->any_count += cnt; 168 169 switch (af) { 170 case AF_INET: 171 cb->ip_count += cnt; 172 return; 173 #ifdef INET6 174 case AF_INET6: 175 cb->ip6_count += cnt; 176 return; 177 #endif 178 case AF_MPLS: 179 cb->mpls_count += cnt; 180 return; 181 } 182 } 183 184 static int 185 COMPATNAME(route_attach)(struct socket *so, int proto) 186 { 187 struct rawcb *rp; 188 int s, error; 189 190 KASSERT(sotorawcb(so) == NULL); 191 rp = kmem_zalloc(sizeof(*rp), KM_SLEEP); 192 rp->rcb_len = sizeof(*rp); 193 so->so_pcb = rp; 194 195 s = splsoftnet(); 196 if ((error = raw_attach(so, proto)) == 0) { 197 rt_adjustcount(rp->rcb_proto.sp_protocol, 1); 198 rp->rcb_laddr = &COMPATNAME(route_info).ri_src; 199 rp->rcb_faddr = &COMPATNAME(route_info).ri_dst; 200 } 201 splx(s); 202 203 if (error) { 204 kmem_free(rp, sizeof(*rp)); 205 so->so_pcb = NULL; 206 return error; 207 } 208 209 soisconnected(so); 210 so->so_options |= SO_USELOOPBACK; 211 KASSERT(solocked(so)); 212 213 return error; 214 } 215 216 static void 217 COMPATNAME(route_detach)(struct socket *so) 218 { 219 struct rawcb *rp = sotorawcb(so); 220 int s; 221 222 KASSERT(rp != NULL); 223 KASSERT(solocked(so)); 224 225 s = splsoftnet(); 226 rt_adjustcount(rp->rcb_proto.sp_protocol, -1); 227 raw_detach(so); 228 splx(s); 229 } 230 231 static int 232 COMPATNAME(route_accept)(struct socket *so, struct sockaddr *nam) 233 { 234 KASSERT(solocked(so)); 235 236 panic("route_accept"); 237 238 return EOPNOTSUPP; 239 } 240 241 static int 242 COMPATNAME(route_bind)(struct socket *so, struct sockaddr *nam, struct lwp *l) 243 { 244 KASSERT(solocked(so)); 245 246 return EOPNOTSUPP; 247 } 248 249 static int 250 COMPATNAME(route_listen)(struct socket *so, struct lwp *l) 251 { 252 KASSERT(solocked(so)); 253 254 return EOPNOTSUPP; 255 } 256 257 static int 258 COMPATNAME(route_connect)(struct socket *so, struct sockaddr *nam, struct lwp *l) 259 { 260 KASSERT(solocked(so)); 261 262 return EOPNOTSUPP; 263 } 264 265 static int 266 COMPATNAME(route_connect2)(struct socket *so, struct socket *so2) 267 { 268 KASSERT(solocked(so)); 269 270 return EOPNOTSUPP; 271 } 272 273 static int 274 COMPATNAME(route_disconnect)(struct socket *so) 275 { 276 struct rawcb *rp = sotorawcb(so); 277 int s; 278 279 KASSERT(solocked(so)); 280 KASSERT(rp != NULL); 281 282 s = splsoftnet(); 283 soisdisconnected(so); 284 raw_disconnect(rp); 285 splx(s); 286 287 return 0; 288 } 289 290 static int 291 COMPATNAME(route_shutdown)(struct socket *so) 292 { 293 int s; 294 295 KASSERT(solocked(so)); 296 297 /* 298 * Mark the connection as being incapable of further input. 299 */ 300 s = splsoftnet(); 301 socantsendmore(so); 302 splx(s); 303 return 0; 304 } 305 306 static int 307 COMPATNAME(route_abort)(struct socket *so) 308 { 309 KASSERT(solocked(so)); 310 311 panic("route_abort"); 312 313 return EOPNOTSUPP; 314 } 315 316 static int 317 COMPATNAME(route_ioctl)(struct socket *so, u_long cmd, void *nam, 318 struct ifnet * ifp) 319 { 320 return EOPNOTSUPP; 321 } 322 323 static int 324 COMPATNAME(route_stat)(struct socket *so, struct stat *ub) 325 { 326 KASSERT(solocked(so)); 327 328 return 0; 329 } 330 331 static int 332 COMPATNAME(route_peeraddr)(struct socket *so, struct sockaddr *nam) 333 { 334 struct rawcb *rp = sotorawcb(so); 335 336 KASSERT(solocked(so)); 337 KASSERT(rp != NULL); 338 KASSERT(nam != NULL); 339 340 if (rp->rcb_faddr == NULL) 341 return ENOTCONN; 342 343 raw_setpeeraddr(rp, nam); 344 return 0; 345 } 346 347 static int 348 COMPATNAME(route_sockaddr)(struct socket *so, struct sockaddr *nam) 349 { 350 struct rawcb *rp = sotorawcb(so); 351 352 KASSERT(solocked(so)); 353 KASSERT(rp != NULL); 354 KASSERT(nam != NULL); 355 356 if (rp->rcb_faddr == NULL) 357 return ENOTCONN; 358 359 raw_setsockaddr(rp, nam); 360 return 0; 361 } 362 363 static int 364 COMPATNAME(route_rcvd)(struct socket *so, int flags, struct lwp *l) 365 { 366 KASSERT(solocked(so)); 367 368 return EOPNOTSUPP; 369 } 370 371 static int 372 COMPATNAME(route_recvoob)(struct socket *so, struct mbuf *m, int flags) 373 { 374 KASSERT(solocked(so)); 375 376 return EOPNOTSUPP; 377 } 378 379 static int 380 COMPATNAME(route_send)(struct socket *so, struct mbuf *m, 381 struct sockaddr *nam, struct mbuf *control, struct lwp *l) 382 { 383 int error = 0; 384 int s; 385 386 KASSERT(solocked(so)); 387 388 s = splsoftnet(); 389 error = raw_send(so, m, nam, control, l); 390 splx(s); 391 392 return error; 393 } 394 395 static int 396 COMPATNAME(route_sendoob)(struct socket *so, struct mbuf *m, 397 struct mbuf *control) 398 { 399 KASSERT(solocked(so)); 400 401 m_freem(m); 402 m_freem(control); 403 404 return EOPNOTSUPP; 405 } 406 static int 407 COMPATNAME(route_purgeif)(struct socket *so, struct ifnet *ifp) 408 { 409 410 panic("route_purgeif"); 411 412 return EOPNOTSUPP; 413 } 414 415 /*ARGSUSED*/ 416 int 417 COMPATNAME(route_output)(struct mbuf *m, ...) 418 { 419 struct sockproto proto = { .sp_family = PF_XROUTE, }; 420 struct rt_xmsghdr *rtm = NULL; 421 struct rt_xmsghdr *old_rtm = NULL; 422 struct rtentry *rt = NULL; 423 struct rtentry *saved_nrt = NULL; 424 struct rt_addrinfo info; 425 int len, error = 0; 426 struct ifnet *ifp = NULL; 427 struct ifaddr *ifa = NULL; 428 struct socket *so; 429 va_list ap; 430 sa_family_t family; 431 432 va_start(ap, m); 433 so = va_arg(ap, struct socket *); 434 va_end(ap); 435 436 #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0) 437 if (m == NULL || ((m->m_len < sizeof(int32_t)) && 438 (m = m_pullup(m, sizeof(int32_t))) == NULL)) 439 return ENOBUFS; 440 if ((m->m_flags & M_PKTHDR) == 0) 441 panic("%s", __func__); 442 len = m->m_pkthdr.len; 443 if (len < sizeof(*rtm) || 444 len != mtod(m, struct rt_xmsghdr *)->rtm_msglen) { 445 info.rti_info[RTAX_DST] = NULL; 446 senderr(EINVAL); 447 } 448 R_Malloc(rtm, struct rt_xmsghdr *, len); 449 if (rtm == NULL) { 450 info.rti_info[RTAX_DST] = NULL; 451 senderr(ENOBUFS); 452 } 453 m_copydata(m, 0, len, rtm); 454 if (rtm->rtm_version != RTM_XVERSION) { 455 info.rti_info[RTAX_DST] = NULL; 456 senderr(EPROTONOSUPPORT); 457 } 458 rtm->rtm_pid = curproc->p_pid; 459 memset(&info, 0, sizeof(info)); 460 info.rti_addrs = rtm->rtm_addrs; 461 if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm, 462 &info)) { 463 senderr(EINVAL); 464 } 465 info.rti_flags = rtm->rtm_flags; 466 #ifdef RTSOCK_DEBUG 467 if (info.rti_info[RTAX_DST]->sa_family == AF_INET) { 468 char abuf[INET_ADDRSTRLEN]; 469 printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__, 470 RT_IN_PRINT(abuf, RTAX_DST)); 471 } 472 #endif /* RTSOCK_DEBUG */ 473 if (info.rti_info[RTAX_DST] == NULL || 474 (info.rti_info[RTAX_DST]->sa_family >= AF_MAX)) { 475 senderr(EINVAL); 476 } 477 if (info.rti_info[RTAX_GATEWAY] != NULL && 478 (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) { 479 senderr(EINVAL); 480 } 481 482 /* 483 * Verify that the caller has the appropriate privilege; RTM_GET 484 * is the only operation the non-superuser is allowed. 485 */ 486 if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE, 487 0, rtm, NULL, NULL) != 0) 488 senderr(EACCES); 489 490 switch (rtm->rtm_type) { 491 492 case RTM_ADD: 493 if (info.rti_info[RTAX_GATEWAY] == NULL) { 494 senderr(EINVAL); 495 } 496 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 497 if (error == 0) { 498 rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt); 499 rtfree(saved_nrt); 500 } 501 break; 502 503 case RTM_DELETE: 504 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 505 if (error == 0) { 506 rt = saved_nrt; 507 goto report; 508 } 509 break; 510 511 case RTM_GET: 512 case RTM_CHANGE: 513 case RTM_LOCK: 514 /* XXX This will mask info.rti_info[RTAX_DST] with 515 * info.rti_info[RTAX_NETMASK] before 516 * searching. It did not used to do that. --dyoung 517 */ 518 rt = NULL; 519 error = rtrequest1(RTM_GET, &info, &rt); 520 if (error != 0) 521 senderr(error); 522 if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */ 523 if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt), 524 info.rti_info[RTAX_DST]->sa_len) != 0) 525 senderr(ESRCH); 526 if (info.rti_info[RTAX_NETMASK] == NULL && 527 rt_mask(rt) != NULL) 528 senderr(ETOOMANYREFS); 529 } 530 531 switch (rtm->rtm_type) { 532 case RTM_GET: 533 report: 534 info.rti_info[RTAX_DST] = rt_getkey(rt); 535 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 536 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 537 info.rti_info[RTAX_TAG] = rt_gettag(rt); 538 if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0) 539 ; 540 else if ((ifp = rt->rt_ifp) != NULL) { 541 const struct ifaddr *rtifa; 542 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 543 /* rtifa used to be simply rt->rt_ifa. 544 * If rt->rt_ifa != NULL, then 545 * rt_get_ifa() != NULL. So this 546 * ought to still be safe. --dyoung 547 */ 548 rtifa = rt_get_ifa(rt); 549 info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 550 #ifdef RTSOCK_DEBUG 551 if (info.rti_info[RTAX_IFA]->sa_family == 552 AF_INET) { 553 char ibuf[INET_ADDRSTRLEN]; 554 char abuf[INET_ADDRSTRLEN]; 555 printf("%s: copying out RTAX_IFA %s " 556 "for info.rti_info[RTAX_DST] %s " 557 "ifa_getifa %p ifa_seqno %p\n", 558 __func__, 559 RT_IN_PRINT(ibuf, RTAX_IFA), 560 RT_IN_PRINT(abuf, RTAX_DST), 561 (void *)rtifa->ifa_getifa, 562 rtifa->ifa_seqno); 563 } 564 #endif /* RTSOCK_DEBUG */ 565 if (ifp->if_flags & IFF_POINTOPOINT) { 566 info.rti_info[RTAX_BRD] = 567 rtifa->ifa_dstaddr; 568 } else 569 info.rti_info[RTAX_BRD] = NULL; 570 rtm->rtm_index = ifp->if_index; 571 } else { 572 info.rti_info[RTAX_IFP] = NULL; 573 info.rti_info[RTAX_IFA] = NULL; 574 } 575 (void)rt_msg2(rtm->rtm_type, &info, NULL, NULL, &len); 576 if (len > rtm->rtm_msglen) { 577 old_rtm = rtm; 578 R_Malloc(rtm, struct rt_xmsghdr *, len); 579 if (rtm == NULL) 580 senderr(ENOBUFS); 581 (void)memcpy(rtm, old_rtm, old_rtm->rtm_msglen); 582 } 583 (void)rt_msg2(rtm->rtm_type, &info, rtm, NULL, 0); 584 rtm->rtm_flags = rt->rt_flags; 585 rtm_setmetrics(rt, rtm); 586 rtm->rtm_addrs = info.rti_addrs; 587 break; 588 589 case RTM_CHANGE: 590 /* 591 * new gateway could require new ifaddr, ifp; 592 * flags may also be different; ifp may be specified 593 * by ll sockaddr when protocol address is ambiguous 594 */ 595 if ((error = rt_getifa(&info)) != 0) 596 senderr(error); 597 if (info.rti_info[RTAX_GATEWAY] && 598 rt_setgate(rt, info.rti_info[RTAX_GATEWAY])) 599 senderr(EDQUOT); 600 if (info.rti_info[RTAX_TAG]) 601 rt_settag(rt, info.rti_info[RTAX_TAG]); 602 /* new gateway could require new ifaddr, ifp; 603 flags may also be different; ifp may be specified 604 by ll sockaddr when protocol address is ambiguous */ 605 if (info.rti_info[RTAX_IFP] && 606 (ifa = ifa_ifwithnet(info.rti_info[RTAX_IFP])) && 607 (ifp = ifa->ifa_ifp) && (info.rti_info[RTAX_IFA] || 608 info.rti_info[RTAX_GATEWAY])) { 609 if (info.rti_info[RTAX_IFA] == NULL || 610 (ifa = ifa_ifwithaddr( 611 info.rti_info[RTAX_IFA])) == NULL) 612 ifa = ifaof_ifpforaddr( 613 info.rti_info[RTAX_IFA] ? 614 info.rti_info[RTAX_IFA] : 615 info.rti_info[RTAX_GATEWAY], ifp); 616 } else if ((info.rti_info[RTAX_IFA] && 617 (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) || 618 (info.rti_info[RTAX_GATEWAY] && 619 (ifa = ifa_ifwithroute(rt->rt_flags, 620 rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) { 621 ifp = ifa->ifa_ifp; 622 } 623 if (ifa) { 624 struct ifaddr *oifa = rt->rt_ifa; 625 if (oifa != ifa) { 626 if (oifa && oifa->ifa_rtrequest) { 627 oifa->ifa_rtrequest(RTM_DELETE, 628 rt, &info); 629 } 630 rt_replace_ifa(rt, ifa); 631 rt->rt_ifp = ifp; 632 } 633 } 634 if (ifp && rt->rt_ifp != ifp) 635 rt->rt_ifp = ifp; 636 rt_setmetrics(rtm->rtm_inits, rtm, rt); 637 if (rt->rt_flags != info.rti_flags) 638 rt->rt_flags = (info.rti_flags & ~PRESERVED_RTF) 639 | (rt->rt_flags & PRESERVED_RTF); 640 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 641 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 642 /*FALLTHROUGH*/ 643 case RTM_LOCK: 644 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 645 rt->rt_rmx.rmx_locks |= 646 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 647 break; 648 } 649 break; 650 651 default: 652 senderr(EOPNOTSUPP); 653 } 654 655 flush: 656 if (rtm) { 657 if (error) 658 rtm->rtm_errno = error; 659 else 660 rtm->rtm_flags |= RTF_DONE; 661 } 662 family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : 663 0; 664 /* We cannot free old_rtm until we have stopped using the 665 * pointers in info, some of which may point to sockaddrs 666 * in old_rtm. 667 */ 668 if (old_rtm != NULL) 669 Free(old_rtm); 670 if (rt) 671 rtfree(rt); 672 { 673 struct rawcb *rp = NULL; 674 /* 675 * Check to see if we don't want our own messages. 676 */ 677 if ((so->so_options & SO_USELOOPBACK) == 0) { 678 if (COMPATNAME(route_info).ri_cb.any_count <= 1) { 679 if (rtm) 680 Free(rtm); 681 m_freem(m); 682 return error; 683 } 684 /* There is another listener, so construct message */ 685 rp = sotorawcb(so); 686 } 687 if (rtm) { 688 m_copyback(m, 0, rtm->rtm_msglen, rtm); 689 if (m->m_pkthdr.len < rtm->rtm_msglen) { 690 m_freem(m); 691 m = NULL; 692 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 693 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 694 Free(rtm); 695 } 696 if (rp) 697 rp->rcb_proto.sp_family = 0; /* Avoid us */ 698 if (family) 699 proto.sp_protocol = family; 700 if (m) 701 raw_input(m, &proto, &COMPATNAME(route_info).ri_src, 702 &COMPATNAME(route_info).ri_dst); 703 if (rp) 704 rp->rcb_proto.sp_family = PF_XROUTE; 705 } 706 return error; 707 } 708 709 static void 710 rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out) 711 { 712 #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e; 713 metric(RTV_RPIPE, rmx_recvpipe); 714 metric(RTV_SPIPE, rmx_sendpipe); 715 metric(RTV_SSTHRESH, rmx_ssthresh); 716 metric(RTV_RTT, rmx_rtt); 717 metric(RTV_RTTVAR, rmx_rttvar); 718 metric(RTV_HOPCOUNT, rmx_hopcount); 719 metric(RTV_MTU, rmx_mtu); 720 #undef metric 721 if (which & RTV_EXPIRE) { 722 out->rt_rmx.rmx_expire = in->rtm_rmx.rmx_expire ? 723 time_wall_to_mono(in->rtm_rmx.rmx_expire) : 0; 724 } 725 } 726 727 static void 728 rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out) 729 { 730 #define metric(e) out->rtm_rmx.e = in->rt_rmx.e; 731 metric(rmx_recvpipe); 732 metric(rmx_sendpipe); 733 metric(rmx_ssthresh); 734 metric(rmx_rtt); 735 metric(rmx_rttvar); 736 metric(rmx_hopcount); 737 metric(rmx_mtu); 738 #undef metric 739 out->rtm_rmx.rmx_expire = in->rt_rmx.rmx_expire ? 740 time_mono_to_wall(in->rt_rmx.rmx_expire) : 0; 741 } 742 743 static int 744 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, 745 struct rt_addrinfo *rtinfo) 746 { 747 const struct sockaddr *sa = NULL; /* Quell compiler warning */ 748 int i; 749 750 for (i = 0; i < RTAX_MAX && cp < cplim; i++) { 751 if ((rtinfo->rti_addrs & (1 << i)) == 0) 752 continue; 753 rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; 754 RT_XADVANCE(cp, sa); 755 } 756 757 /* 758 * Check for extra addresses specified, except RTM_GET asking 759 * for interface info. 760 */ 761 if (rtmtype == RTM_GET) { 762 if (((rtinfo->rti_addrs & 763 (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0) 764 return 1; 765 } else if ((rtinfo->rti_addrs & (~0 << i)) != 0) 766 return 1; 767 /* Check for bad data length. */ 768 if (cp != cplim) { 769 if (i == RTAX_NETMASK + 1 && sa != NULL && 770 cp - RT_XROUNDUP(sa->sa_len) + sa->sa_len == cplim) 771 /* 772 * The last sockaddr was info.rti_info[RTAX_NETMASK]. 773 * We accept this for now for the sake of old 774 * binaries or third party softwares. 775 */ 776 ; 777 else 778 return 1; 779 } 780 return 0; 781 } 782 783 static int 784 rt_getlen(int type) 785 { 786 #ifndef COMPAT_RTSOCK 787 CTASSERT(__alignof(struct ifa_msghdr) >= sizeof(uint64_t)); 788 CTASSERT(__alignof(struct if_msghdr) >= sizeof(uint64_t)); 789 CTASSERT(__alignof(struct if_announcemsghdr) >= sizeof(uint64_t)); 790 CTASSERT(__alignof(struct rt_msghdr) >= sizeof(uint64_t)); 791 #endif 792 793 switch (type) { 794 case RTM_DELADDR: 795 case RTM_NEWADDR: 796 case RTM_CHGADDR: 797 return sizeof(struct ifa_xmsghdr); 798 799 case RTM_OOIFINFO: 800 #ifdef COMPAT_14 801 return sizeof(struct if_msghdr14); 802 #else 803 #ifdef DIAGNOSTIC 804 printf("RTM_OOIFINFO\n"); 805 #endif 806 return -1; 807 #endif 808 case RTM_OIFINFO: 809 #ifdef COMPAT_50 810 return sizeof(struct if_msghdr50); 811 #else 812 #ifdef DIAGNOSTIC 813 printf("RTM_OIFINFO\n"); 814 #endif 815 return -1; 816 #endif 817 818 case RTM_IFINFO: 819 return sizeof(struct if_xmsghdr); 820 821 case RTM_IFANNOUNCE: 822 case RTM_IEEE80211: 823 return sizeof(struct if_xannouncemsghdr); 824 825 default: 826 return sizeof(struct rt_xmsghdr); 827 } 828 } 829 830 831 struct mbuf * 832 COMPATNAME(rt_msg1)(int type, struct rt_addrinfo *rtinfo, void *data, int datalen) 833 { 834 struct rt_xmsghdr *rtm; 835 struct mbuf *m; 836 int i; 837 const struct sockaddr *sa; 838 int len, dlen; 839 840 m = m_gethdr(M_DONTWAIT, MT_DATA); 841 if (m == NULL) 842 return m; 843 MCLAIM(m, &COMPATNAME(routedomain).dom_mowner); 844 845 if ((len = rt_getlen(type)) == -1) 846 goto out; 847 if (len > MHLEN + MLEN) 848 panic("%s: message too long", __func__); 849 else if (len > MHLEN) { 850 m->m_next = m_get(M_DONTWAIT, MT_DATA); 851 if (m->m_next == NULL) 852 goto out; 853 MCLAIM(m->m_next, m->m_owner); 854 m->m_pkthdr.len = len; 855 m->m_len = MHLEN; 856 m->m_next->m_len = len - MHLEN; 857 } else { 858 m->m_pkthdr.len = m->m_len = len; 859 } 860 m->m_pkthdr.rcvif = NULL; 861 m_copyback(m, 0, datalen, data); 862 if (len > datalen) 863 (void)memset(mtod(m, char *) + datalen, 0, len - datalen); 864 rtm = mtod(m, struct rt_xmsghdr *); 865 for (i = 0; i < RTAX_MAX; i++) { 866 if ((sa = rtinfo->rti_info[i]) == NULL) 867 continue; 868 rtinfo->rti_addrs |= (1 << i); 869 dlen = RT_XROUNDUP(sa->sa_len); 870 m_copyback(m, len, sa->sa_len, sa); 871 if (dlen != sa->sa_len) { 872 /* 873 * Up to 6 + 1 nul's since roundup is to 874 * sizeof(uint64_t) (8 bytes) 875 */ 876 m_copyback(m, len + sa->sa_len, 877 dlen - sa->sa_len, "\0\0\0\0\0\0"); 878 } 879 len += dlen; 880 } 881 if (m->m_pkthdr.len != len) 882 goto out; 883 rtm->rtm_msglen = len; 884 rtm->rtm_version = RTM_XVERSION; 885 rtm->rtm_type = type; 886 return m; 887 out: 888 m_freem(m); 889 return NULL; 890 } 891 892 /* 893 * rt_msg2 894 * 895 * fills 'cp' or 'w'.w_tmem with the routing socket message and 896 * returns the length of the message in 'lenp'. 897 * 898 * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold 899 * the message 900 * otherwise walkarg's w_needed is updated and if the user buffer is 901 * specified and w_needed indicates space exists the information is copied 902 * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, 903 * if the allocation fails ENOBUFS is returned. 904 */ 905 static int 906 rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, 907 int *lenp) 908 { 909 int i; 910 int len, dlen, second_time = 0; 911 char *cp0, *cp = cpv; 912 913 rtinfo->rti_addrs = 0; 914 again: 915 if ((len = rt_getlen(type)) == -1) 916 return EINVAL; 917 918 if ((cp0 = cp) != NULL) 919 cp += len; 920 for (i = 0; i < RTAX_MAX; i++) { 921 const struct sockaddr *sa; 922 923 if ((sa = rtinfo->rti_info[i]) == NULL) 924 continue; 925 rtinfo->rti_addrs |= (1 << i); 926 dlen = RT_XROUNDUP(sa->sa_len); 927 if (cp) { 928 int diff = dlen - sa->sa_len; 929 (void)memcpy(cp, sa, (size_t)sa->sa_len); 930 cp += sa->sa_len; 931 if (diff > 0) { 932 (void)memset(cp, 0, (size_t)diff); 933 cp += diff; 934 } 935 } 936 len += dlen; 937 } 938 if (cp == NULL && w != NULL && !second_time) { 939 struct rt_walkarg *rw = w; 940 941 rw->w_needed += len; 942 if (rw->w_needed <= 0 && rw->w_where) { 943 if (rw->w_tmemsize < len) { 944 if (rw->w_tmem) 945 free(rw->w_tmem, M_RTABLE); 946 rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT); 947 if (rw->w_tmem) 948 rw->w_tmemsize = len; 949 else 950 rw->w_tmemsize = 0; 951 } 952 if (rw->w_tmem) { 953 cp = rw->w_tmem; 954 second_time = 1; 955 goto again; 956 } else { 957 rw->w_tmemneeded = len; 958 return ENOBUFS; 959 } 960 } 961 } 962 if (cp) { 963 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)cp0; 964 965 rtm->rtm_version = RTM_XVERSION; 966 rtm->rtm_type = type; 967 rtm->rtm_msglen = len; 968 } 969 if (lenp) 970 *lenp = len; 971 return 0; 972 } 973 974 /* 975 * This routine is called to generate a message from the routing 976 * socket indicating that a redirect has occurred, a routing lookup 977 * has failed, or that a protocol has detected timeouts to a particular 978 * destination. 979 */ 980 void 981 COMPATNAME(rt_missmsg)(int type, const struct rt_addrinfo *rtinfo, int flags, 982 int error) 983 { 984 struct rt_xmsghdr rtm; 985 struct mbuf *m; 986 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 987 struct rt_addrinfo info = *rtinfo; 988 989 COMPATCALL(rt_missmsg, (type, rtinfo, flags, error)); 990 if (COMPATNAME(route_info).ri_cb.any_count == 0) 991 return; 992 memset(&rtm, 0, sizeof(rtm)); 993 rtm.rtm_flags = RTF_DONE | flags; 994 rtm.rtm_errno = error; 995 m = COMPATNAME(rt_msg1)(type, &info, &rtm, sizeof(rtm)); 996 if (m == NULL) 997 return; 998 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; 999 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); 1000 } 1001 1002 /* 1003 * This routine is called to generate a message from the routing 1004 * socket indicating that the status of a network interface has changed. 1005 */ 1006 void 1007 COMPATNAME(rt_ifmsg)(struct ifnet *ifp) 1008 { 1009 struct if_xmsghdr ifm; 1010 struct mbuf *m; 1011 struct rt_addrinfo info; 1012 1013 COMPATCALL(rt_ifmsg, (ifp)); 1014 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1015 return; 1016 (void)memset(&info, 0, sizeof(info)); 1017 (void)memset(&ifm, 0, sizeof(ifm)); 1018 ifm.ifm_index = ifp->if_index; 1019 ifm.ifm_flags = ifp->if_flags; 1020 ifm.ifm_data = ifp->if_data; 1021 ifm.ifm_addrs = 0; 1022 m = COMPATNAME(rt_msg1)(RTM_IFINFO, &info, &ifm, sizeof(ifm)); 1023 if (m == NULL) 1024 return; 1025 COMPATNAME(route_enqueue)(m, 0); 1026 #ifdef COMPAT_14 1027 compat_14_rt_oifmsg(ifp); 1028 #endif 1029 #ifdef COMPAT_50 1030 compat_50_rt_oifmsg(ifp); 1031 #endif 1032 } 1033 1034 1035 /* 1036 * This is called to generate messages from the routing socket 1037 * indicating a network interface has had addresses associated with it. 1038 * if we ever reverse the logic and replace messages TO the routing 1039 * socket indicate a request to configure interfaces, then it will 1040 * be unnecessary as the routing socket will automatically generate 1041 * copies of it. 1042 */ 1043 void 1044 COMPATNAME(rt_newaddrmsg)(int cmd, struct ifaddr *ifa, int error, 1045 struct rtentry *rt) 1046 { 1047 #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass)) 1048 struct rt_addrinfo info; 1049 const struct sockaddr *sa; 1050 int pass; 1051 struct mbuf *m; 1052 struct ifnet *ifp; 1053 struct rt_xmsghdr rtm; 1054 struct ifa_xmsghdr ifam; 1055 int ncmd; 1056 1057 KASSERT(ifa != NULL); 1058 ifp = ifa->ifa_ifp; 1059 COMPATCALL(rt_newaddrmsg, (cmd, ifa, error, rt)); 1060 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1061 return; 1062 for (pass = 1; pass < 3; pass++) { 1063 memset(&info, 0, sizeof(info)); 1064 switch (cmdpass(cmd, pass)) { 1065 case cmdpass(RTM_ADD, 1): 1066 case cmdpass(RTM_CHANGE, 1): 1067 case cmdpass(RTM_DELETE, 2): 1068 case cmdpass(RTM_NEWADDR, 1): 1069 case cmdpass(RTM_DELADDR, 1): 1070 case cmdpass(RTM_CHGADDR, 1): 1071 switch (cmd) { 1072 case RTM_ADD: 1073 ncmd = RTM_NEWADDR; 1074 break; 1075 case RTM_DELETE: 1076 ncmd = RTM_DELADDR; 1077 break; 1078 case RTM_CHANGE: 1079 ncmd = RTM_CHGADDR; 1080 break; 1081 default: 1082 ncmd = cmd; 1083 } 1084 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; 1085 KASSERT(ifp->if_dl != NULL); 1086 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 1087 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1088 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1089 memset(&ifam, 0, sizeof(ifam)); 1090 ifam.ifam_index = ifp->if_index; 1091 ifam.ifam_metric = ifa->ifa_metric; 1092 ifam.ifam_flags = ifa->ifa_flags; 1093 m = COMPATNAME(rt_msg1)(ncmd, &info, &ifam, sizeof(ifam)); 1094 if (m == NULL) 1095 continue; 1096 mtod(m, struct ifa_xmsghdr *)->ifam_addrs = 1097 info.rti_addrs; 1098 break; 1099 case cmdpass(RTM_ADD, 2): 1100 case cmdpass(RTM_CHANGE, 2): 1101 case cmdpass(RTM_DELETE, 1): 1102 if (rt == NULL) 1103 continue; 1104 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1105 info.rti_info[RTAX_DST] = sa = rt_getkey(rt); 1106 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1107 memset(&rtm, 0, sizeof(rtm)); 1108 rtm.rtm_index = ifp->if_index; 1109 rtm.rtm_flags |= rt->rt_flags; 1110 rtm.rtm_errno = error; 1111 m = COMPATNAME(rt_msg1)(cmd, &info, &rtm, sizeof(rtm)); 1112 if (m == NULL) 1113 continue; 1114 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; 1115 break; 1116 default: 1117 continue; 1118 } 1119 #ifdef DIAGNOSTIC 1120 if (m == NULL) 1121 panic("%s: called with wrong command", __func__); 1122 #endif 1123 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); 1124 } 1125 #undef cmdpass 1126 } 1127 1128 static struct mbuf * 1129 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, 1130 struct rt_addrinfo *info) 1131 { 1132 struct if_xannouncemsghdr ifan; 1133 1134 memset(info, 0, sizeof(*info)); 1135 memset(&ifan, 0, sizeof(ifan)); 1136 ifan.ifan_index = ifp->if_index; 1137 strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); 1138 ifan.ifan_what = what; 1139 return COMPATNAME(rt_msg1)(type, info, &ifan, sizeof(ifan)); 1140 } 1141 1142 /* 1143 * This is called to generate routing socket messages indicating 1144 * network interface arrival and departure. 1145 */ 1146 void 1147 COMPATNAME(rt_ifannouncemsg)(struct ifnet *ifp, int what) 1148 { 1149 struct mbuf *m; 1150 struct rt_addrinfo info; 1151 1152 COMPATCALL(rt_ifannouncemsg, (ifp, what)); 1153 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1154 return; 1155 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info); 1156 if (m == NULL) 1157 return; 1158 COMPATNAME(route_enqueue)(m, 0); 1159 } 1160 1161 /* 1162 * This is called to generate routing socket messages indicating 1163 * IEEE80211 wireless events. 1164 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way. 1165 */ 1166 void 1167 COMPATNAME(rt_ieee80211msg)(struct ifnet *ifp, int what, void *data, 1168 size_t data_len) 1169 { 1170 struct mbuf *m; 1171 struct rt_addrinfo info; 1172 1173 COMPATCALL(rt_ieee80211msg, (ifp, what, data, data_len)); 1174 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1175 return; 1176 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info); 1177 if (m == NULL) 1178 return; 1179 /* 1180 * Append the ieee80211 data. Try to stick it in the 1181 * mbuf containing the ifannounce msg; otherwise allocate 1182 * a new mbuf and append. 1183 * 1184 * NB: we assume m is a single mbuf. 1185 */ 1186 if (data_len > M_TRAILINGSPACE(m)) { 1187 struct mbuf *n = m_get(M_NOWAIT, MT_DATA); 1188 if (n == NULL) { 1189 m_freem(m); 1190 return; 1191 } 1192 (void)memcpy(mtod(n, void *), data, data_len); 1193 n->m_len = data_len; 1194 m->m_next = n; 1195 } else if (data_len > 0) { 1196 (void)memcpy(mtod(m, uint8_t *) + m->m_len, data, data_len); 1197 m->m_len += data_len; 1198 } 1199 if (m->m_flags & M_PKTHDR) 1200 m->m_pkthdr.len += data_len; 1201 mtod(m, struct if_xannouncemsghdr *)->ifan_msglen += data_len; 1202 COMPATNAME(route_enqueue)(m, 0); 1203 } 1204 1205 /* 1206 * This is used in dumping the kernel table via sysctl(). 1207 */ 1208 static int 1209 sysctl_dumpentry(struct rtentry *rt, void *v) 1210 { 1211 struct rt_walkarg *w = v; 1212 int error = 0, size; 1213 struct rt_addrinfo info; 1214 1215 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 1216 return 0; 1217 memset(&info, 0, sizeof(info)); 1218 info.rti_info[RTAX_DST] = rt_getkey(rt); 1219 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1220 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1221 info.rti_info[RTAX_TAG] = rt_gettag(rt); 1222 if (rt->rt_ifp) { 1223 const struct ifaddr *rtifa; 1224 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr; 1225 /* rtifa used to be simply rt->rt_ifa. If rt->rt_ifa != NULL, 1226 * then rt_get_ifa() != NULL. So this ought to still be safe. 1227 * --dyoung 1228 */ 1229 rtifa = rt_get_ifa(rt); 1230 info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 1231 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 1232 info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; 1233 } 1234 if ((error = rt_msg2(RTM_GET, &info, 0, w, &size))) 1235 return error; 1236 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1237 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)w->w_tmem; 1238 1239 rtm->rtm_flags = rt->rt_flags; 1240 rtm->rtm_use = rt->rt_use; 1241 rtm_setmetrics(rt, rtm); 1242 KASSERT(rt->rt_ifp != NULL); 1243 rtm->rtm_index = rt->rt_ifp->if_index; 1244 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 1245 rtm->rtm_addrs = info.rti_addrs; 1246 if ((error = copyout(rtm, w->w_where, size)) != 0) 1247 w->w_where = NULL; 1248 else 1249 w->w_where = (char *)w->w_where + size; 1250 } 1251 return error; 1252 } 1253 1254 static int 1255 sysctl_iflist(int af, struct rt_walkarg *w, int type) 1256 { 1257 struct ifnet *ifp; 1258 struct ifaddr *ifa; 1259 struct rt_addrinfo info; 1260 int len, error = 0; 1261 1262 memset(&info, 0, sizeof(info)); 1263 IFNET_FOREACH(ifp) { 1264 if (w->w_arg && w->w_arg != ifp->if_index) 1265 continue; 1266 if (IFADDR_EMPTY(ifp)) 1267 continue; 1268 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 1269 switch (type) { 1270 case NET_RT_IFLIST: 1271 error = rt_msg2(RTM_IFINFO, &info, NULL, w, &len); 1272 break; 1273 #ifdef COMPAT_14 1274 case NET_RT_OOIFLIST: 1275 error = rt_msg2(RTM_OOIFINFO, &info, NULL, w, &len); 1276 break; 1277 #endif 1278 #ifdef COMPAT_50 1279 case NET_RT_OIFLIST: 1280 error = rt_msg2(RTM_OIFINFO, &info, NULL, w, &len); 1281 break; 1282 #endif 1283 default: 1284 panic("sysctl_iflist(1)"); 1285 } 1286 if (error) 1287 return error; 1288 info.rti_info[RTAX_IFP] = NULL; 1289 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1290 switch (type) { 1291 case NET_RT_IFLIST: { 1292 struct if_xmsghdr *ifm; 1293 1294 ifm = (struct if_xmsghdr *)w->w_tmem; 1295 ifm->ifm_index = ifp->if_index; 1296 ifm->ifm_flags = ifp->if_flags; 1297 ifm->ifm_data = ifp->if_data; 1298 ifm->ifm_addrs = info.rti_addrs; 1299 error = copyout(ifm, w->w_where, len); 1300 if (error) 1301 return error; 1302 w->w_where = (char *)w->w_where + len; 1303 break; 1304 } 1305 1306 #ifdef COMPAT_14 1307 case NET_RT_OOIFLIST: 1308 error = compat_14_iflist(ifp, w, &info, len); 1309 if (error) 1310 return error; 1311 break; 1312 #endif 1313 #ifdef COMPAT_50 1314 case NET_RT_OIFLIST: 1315 error = compat_50_iflist(ifp, w, &info, len); 1316 if (error) 1317 return error; 1318 break; 1319 #endif 1320 default: 1321 panic("sysctl_iflist(2)"); 1322 } 1323 } 1324 IFADDR_FOREACH(ifa, ifp) { 1325 if (af && af != ifa->ifa_addr->sa_family) 1326 continue; 1327 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1328 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1329 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1330 if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len))) 1331 return error; 1332 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1333 struct ifa_xmsghdr *ifam; 1334 1335 ifam = (struct ifa_xmsghdr *)w->w_tmem; 1336 ifam->ifam_index = ifa->ifa_ifp->if_index; 1337 ifam->ifam_flags = ifa->ifa_flags; 1338 ifam->ifam_metric = ifa->ifa_metric; 1339 ifam->ifam_addrs = info.rti_addrs; 1340 error = copyout(w->w_tmem, w->w_where, len); 1341 if (error) 1342 return error; 1343 w->w_where = (char *)w->w_where + len; 1344 } 1345 } 1346 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 1347 info.rti_info[RTAX_BRD] = NULL; 1348 } 1349 return 0; 1350 } 1351 1352 static int 1353 sysctl_rtable(SYSCTLFN_ARGS) 1354 { 1355 void *where = oldp; 1356 size_t *given = oldlenp; 1357 int i, s, error = EINVAL; 1358 u_char af; 1359 struct rt_walkarg w; 1360 1361 if (namelen == 1 && name[0] == CTL_QUERY) 1362 return sysctl_query(SYSCTLFN_CALL(rnode)); 1363 1364 if (newp) 1365 return EPERM; 1366 if (namelen != 3) 1367 return EINVAL; 1368 af = name[0]; 1369 w.w_tmemneeded = 0; 1370 w.w_tmemsize = 0; 1371 w.w_tmem = NULL; 1372 again: 1373 /* we may return here if a later [re]alloc of the t_mem buffer fails */ 1374 if (w.w_tmemneeded) { 1375 w.w_tmem = malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK); 1376 w.w_tmemsize = w.w_tmemneeded; 1377 w.w_tmemneeded = 0; 1378 } 1379 w.w_op = name[1]; 1380 w.w_arg = name[2]; 1381 w.w_given = *given; 1382 w.w_needed = 0 - w.w_given; 1383 w.w_where = where; 1384 1385 s = splsoftnet(); 1386 switch (w.w_op) { 1387 1388 case NET_RT_DUMP: 1389 case NET_RT_FLAGS: 1390 for (i = 1; i <= AF_MAX; i++) 1391 if ((af == 0 || af == i) && 1392 (error = rt_walktree(i, sysctl_dumpentry, &w))) 1393 break; 1394 break; 1395 1396 #ifdef COMPAT_14 1397 case NET_RT_OOIFLIST: 1398 error = sysctl_iflist(af, &w, w.w_op); 1399 break; 1400 #endif 1401 #ifdef COMPAT_50 1402 case NET_RT_OIFLIST: 1403 error = sysctl_iflist(af, &w, w.w_op); 1404 break; 1405 #endif 1406 case NET_RT_IFLIST: 1407 error = sysctl_iflist(af, &w, w.w_op); 1408 break; 1409 } 1410 splx(s); 1411 1412 /* check to see if we couldn't allocate memory with NOWAIT */ 1413 if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded) 1414 goto again; 1415 1416 if (w.w_tmem) 1417 free(w.w_tmem, M_RTABLE); 1418 w.w_needed += w.w_given; 1419 if (where) { 1420 *given = (char *)w.w_where - (char *)where; 1421 if (*given < w.w_needed) 1422 return ENOMEM; 1423 } else { 1424 *given = (11 * w.w_needed) / 10; 1425 } 1426 return error; 1427 } 1428 1429 /* 1430 * Routing message software interrupt routine 1431 */ 1432 static void 1433 COMPATNAME(route_intr)(void *cookie) 1434 { 1435 struct sockproto proto = { .sp_family = PF_XROUTE, }; 1436 struct route_info * const ri = &COMPATNAME(route_info); 1437 struct mbuf *m; 1438 int s; 1439 1440 mutex_enter(softnet_lock); 1441 KERNEL_LOCK(1, NULL); 1442 while (!IF_IS_EMPTY(&ri->ri_intrq)) { 1443 s = splnet(); 1444 IF_DEQUEUE(&ri->ri_intrq, m); 1445 splx(s); 1446 if (m == NULL) 1447 break; 1448 proto.sp_protocol = M_GETCTX(m, uintptr_t); 1449 raw_input(m, &proto, &ri->ri_src, &ri->ri_dst); 1450 } 1451 KERNEL_UNLOCK_ONE(NULL); 1452 mutex_exit(softnet_lock); 1453 } 1454 1455 /* 1456 * Enqueue a message to the software interrupt routine. 1457 */ 1458 void 1459 COMPATNAME(route_enqueue)(struct mbuf *m, int family) 1460 { 1461 struct route_info * const ri = &COMPATNAME(route_info); 1462 int s, wasempty; 1463 1464 s = splnet(); 1465 if (IF_QFULL(&ri->ri_intrq)) { 1466 IF_DROP(&ri->ri_intrq); 1467 m_freem(m); 1468 } else { 1469 wasempty = IF_IS_EMPTY(&ri->ri_intrq); 1470 M_SETCTX(m, (uintptr_t)family); 1471 IF_ENQUEUE(&ri->ri_intrq, m); 1472 if (wasempty) 1473 softint_schedule(ri->ri_sih); 1474 } 1475 splx(s); 1476 } 1477 1478 static void 1479 COMPATNAME(route_init)(void) 1480 { 1481 struct route_info * const ri = &COMPATNAME(route_info); 1482 1483 #ifndef COMPAT_RTSOCK 1484 rt_init(); 1485 #endif 1486 1487 sysctl_net_route_setup(NULL); 1488 ri->ri_intrq.ifq_maxlen = ri->ri_maxqlen; 1489 ri->ri_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, 1490 COMPATNAME(route_intr), NULL); 1491 } 1492 1493 /* 1494 * Definitions of protocols supported in the ROUTE domain. 1495 */ 1496 #ifndef COMPAT_RTSOCK 1497 PR_WRAP_USRREQS(route); 1498 #else 1499 PR_WRAP_USRREQS(compat_50_route); 1500 #endif 1501 1502 static const struct pr_usrreqs route_usrreqs = { 1503 .pr_attach = COMPATNAME(route_attach_wrapper), 1504 .pr_detach = COMPATNAME(route_detach_wrapper), 1505 .pr_accept = COMPATNAME(route_accept_wrapper), 1506 .pr_bind = COMPATNAME(route_bind_wrapper), 1507 .pr_listen = COMPATNAME(route_listen_wrapper), 1508 .pr_connect = COMPATNAME(route_connect_wrapper), 1509 .pr_connect2 = COMPATNAME(route_connect2_wrapper), 1510 .pr_disconnect = COMPATNAME(route_disconnect_wrapper), 1511 .pr_shutdown = COMPATNAME(route_shutdown_wrapper), 1512 .pr_abort = COMPATNAME(route_abort_wrapper), 1513 .pr_ioctl = COMPATNAME(route_ioctl_wrapper), 1514 .pr_stat = COMPATNAME(route_stat_wrapper), 1515 .pr_peeraddr = COMPATNAME(route_peeraddr_wrapper), 1516 .pr_sockaddr = COMPATNAME(route_sockaddr_wrapper), 1517 .pr_rcvd = COMPATNAME(route_rcvd_wrapper), 1518 .pr_recvoob = COMPATNAME(route_recvoob_wrapper), 1519 .pr_send = COMPATNAME(route_send_wrapper), 1520 .pr_sendoob = COMPATNAME(route_sendoob_wrapper), 1521 .pr_purgeif = COMPATNAME(route_purgeif_wrapper), 1522 }; 1523 1524 static const struct protosw COMPATNAME(route_protosw)[] = { 1525 { 1526 .pr_type = SOCK_RAW, 1527 .pr_domain = &COMPATNAME(routedomain), 1528 .pr_flags = PR_ATOMIC|PR_ADDR, 1529 .pr_input = raw_input, 1530 .pr_output = COMPATNAME(route_output), 1531 .pr_ctlinput = raw_ctlinput, 1532 .pr_usrreqs = &route_usrreqs, 1533 .pr_init = raw_init, 1534 }, 1535 }; 1536 1537 struct domain COMPATNAME(routedomain) = { 1538 .dom_family = PF_XROUTE, 1539 .dom_name = DOMAINNAME, 1540 .dom_init = COMPATNAME(route_init), 1541 .dom_protosw = COMPATNAME(route_protosw), 1542 .dom_protoswNPROTOSW = 1543 &COMPATNAME(route_protosw)[__arraycount(COMPATNAME(route_protosw))], 1544 }; 1545 1546 static void 1547 sysctl_net_route_setup(struct sysctllog **clog) 1548 { 1549 const struct sysctlnode *rnode = NULL; 1550 1551 sysctl_createv(clog, 0, NULL, &rnode, 1552 CTLFLAG_PERMANENT, 1553 CTLTYPE_NODE, DOMAINNAME, 1554 SYSCTL_DESCR("PF_ROUTE information"), 1555 NULL, 0, NULL, 0, 1556 CTL_NET, PF_XROUTE, CTL_EOL); 1557 1558 sysctl_createv(clog, 0, NULL, NULL, 1559 CTLFLAG_PERMANENT, 1560 CTLTYPE_NODE, "rtable", 1561 SYSCTL_DESCR("Routing table information"), 1562 sysctl_rtable, 0, NULL, 0, 1563 CTL_NET, PF_XROUTE, 0 /* any protocol */, CTL_EOL); 1564 1565 sysctl_createv(clog, 0, &rnode, NULL, 1566 CTLFLAG_PERMANENT, 1567 CTLTYPE_STRUCT, "stats", 1568 SYSCTL_DESCR("Routing statistics"), 1569 NULL, 0, &rtstat, sizeof(rtstat), 1570 CTL_CREATE, CTL_EOL); 1571 } 1572