1 /* $NetBSD: rtsock.c,v 1.168 2015/04/06 06:26:21 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.168 2015/04/06 06:26:21 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 mbuf *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 mbuf *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 mbuf *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 mbuf *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 mbuf *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 static int 416 COMPATNAME(route_usrreq)(struct socket *so, int req, struct mbuf *m, 417 struct mbuf *nam, struct mbuf *control, struct lwp *l) 418 { 419 int s, error = 0; 420 421 KASSERT(req != PRU_ATTACH); 422 KASSERT(req != PRU_DETACH); 423 KASSERT(req != PRU_ACCEPT); 424 KASSERT(req != PRU_BIND); 425 KASSERT(req != PRU_LISTEN); 426 KASSERT(req != PRU_CONNECT); 427 KASSERT(req != PRU_CONNECT2); 428 KASSERT(req != PRU_DISCONNECT); 429 KASSERT(req != PRU_SHUTDOWN); 430 KASSERT(req != PRU_ABORT); 431 KASSERT(req != PRU_CONTROL); 432 KASSERT(req != PRU_SENSE); 433 KASSERT(req != PRU_PEERADDR); 434 KASSERT(req != PRU_SOCKADDR); 435 KASSERT(req != PRU_RCVD); 436 KASSERT(req != PRU_RCVOOB); 437 KASSERT(req != PRU_SEND); 438 KASSERT(req != PRU_SENDOOB); 439 KASSERT(req != PRU_PURGEIF); 440 441 s = splsoftnet(); 442 error = raw_usrreq(so, req, m, nam, control, l); 443 splx(s); 444 445 return error; 446 } 447 448 /*ARGSUSED*/ 449 int 450 COMPATNAME(route_output)(struct mbuf *m, ...) 451 { 452 struct sockproto proto = { .sp_family = PF_XROUTE, }; 453 struct rt_xmsghdr *rtm = NULL; 454 struct rt_xmsghdr *old_rtm = NULL; 455 struct rtentry *rt = NULL; 456 struct rtentry *saved_nrt = NULL; 457 struct rt_addrinfo info; 458 int len, error = 0; 459 struct ifnet *ifp = NULL; 460 struct ifaddr *ifa = NULL; 461 struct socket *so; 462 va_list ap; 463 sa_family_t family; 464 465 va_start(ap, m); 466 so = va_arg(ap, struct socket *); 467 va_end(ap); 468 469 #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0) 470 if (m == NULL || ((m->m_len < sizeof(int32_t)) && 471 (m = m_pullup(m, sizeof(int32_t))) == NULL)) 472 return ENOBUFS; 473 if ((m->m_flags & M_PKTHDR) == 0) 474 panic("%s", __func__); 475 len = m->m_pkthdr.len; 476 if (len < sizeof(*rtm) || 477 len != mtod(m, struct rt_xmsghdr *)->rtm_msglen) { 478 info.rti_info[RTAX_DST] = NULL; 479 senderr(EINVAL); 480 } 481 R_Malloc(rtm, struct rt_xmsghdr *, len); 482 if (rtm == NULL) { 483 info.rti_info[RTAX_DST] = NULL; 484 senderr(ENOBUFS); 485 } 486 m_copydata(m, 0, len, rtm); 487 if (rtm->rtm_version != RTM_XVERSION) { 488 info.rti_info[RTAX_DST] = NULL; 489 senderr(EPROTONOSUPPORT); 490 } 491 rtm->rtm_pid = curproc->p_pid; 492 memset(&info, 0, sizeof(info)); 493 info.rti_addrs = rtm->rtm_addrs; 494 if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm, 495 &info)) { 496 senderr(EINVAL); 497 } 498 info.rti_flags = rtm->rtm_flags; 499 #ifdef RTSOCK_DEBUG 500 if (info.rti_info[RTAX_DST]->sa_family == AF_INET) { 501 char abuf[INET_ADDRSTRLEN]; 502 printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__, 503 RT_IN_PRINT(abuf, RTAX_DST)); 504 } 505 #endif /* RTSOCK_DEBUG */ 506 if (info.rti_info[RTAX_DST] == NULL || 507 (info.rti_info[RTAX_DST]->sa_family >= AF_MAX)) { 508 senderr(EINVAL); 509 } 510 if (info.rti_info[RTAX_GATEWAY] != NULL && 511 (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) { 512 senderr(EINVAL); 513 } 514 515 /* 516 * Verify that the caller has the appropriate privilege; RTM_GET 517 * is the only operation the non-superuser is allowed. 518 */ 519 if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE, 520 0, rtm, NULL, NULL) != 0) 521 senderr(EACCES); 522 523 switch (rtm->rtm_type) { 524 525 case RTM_ADD: 526 if (info.rti_info[RTAX_GATEWAY] == NULL) { 527 senderr(EINVAL); 528 } 529 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 530 if (error == 0 && saved_nrt) { 531 rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt); 532 saved_nrt->rt_refcnt--; 533 } 534 break; 535 536 case RTM_DELETE: 537 error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); 538 if (error == 0) { 539 (rt = saved_nrt)->rt_refcnt++; 540 goto report; 541 } 542 break; 543 544 case RTM_GET: 545 case RTM_CHANGE: 546 case RTM_LOCK: 547 /* XXX This will mask info.rti_info[RTAX_DST] with 548 * info.rti_info[RTAX_NETMASK] before 549 * searching. It did not used to do that. --dyoung 550 */ 551 error = rtrequest1(RTM_GET, &info, &rt); 552 if (error != 0) 553 senderr(error); 554 if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */ 555 if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt), 556 info.rti_info[RTAX_DST]->sa_len) != 0) 557 senderr(ESRCH); 558 if (info.rti_info[RTAX_NETMASK] == NULL && 559 rt_mask(rt) != NULL) 560 senderr(ETOOMANYREFS); 561 } 562 563 switch (rtm->rtm_type) { 564 case RTM_GET: 565 report: 566 info.rti_info[RTAX_DST] = rt_getkey(rt); 567 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 568 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 569 info.rti_info[RTAX_TAG] = rt_gettag(rt); 570 if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0) 571 ; 572 else if ((ifp = rt->rt_ifp) != NULL) { 573 const struct ifaddr *rtifa; 574 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 575 /* rtifa used to be simply rt->rt_ifa. 576 * If rt->rt_ifa != NULL, then 577 * rt_get_ifa() != NULL. So this 578 * ought to still be safe. --dyoung 579 */ 580 rtifa = rt_get_ifa(rt); 581 info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 582 #ifdef RTSOCK_DEBUG 583 if (info.rti_info[RTAX_IFA]->sa_family == 584 AF_INET) { 585 char ibuf[INET_ADDRSTRLEN]; 586 char abuf[INET_ADDRSTRLEN]; 587 printf("%s: copying out RTAX_IFA %s " 588 "for info.rti_info[RTAX_DST] %s " 589 "ifa_getifa %p ifa_seqno %p\n", 590 __func__, 591 RT_IN_PRINT(ibuf, RTAX_IFA), 592 RT_IN_PRINT(abuf, RTAX_DST), 593 (void *)rtifa->ifa_getifa, 594 rtifa->ifa_seqno); 595 } 596 #endif /* RTSOCK_DEBUG */ 597 if (ifp->if_flags & IFF_POINTOPOINT) { 598 info.rti_info[RTAX_BRD] = 599 rtifa->ifa_dstaddr; 600 } else 601 info.rti_info[RTAX_BRD] = NULL; 602 rtm->rtm_index = ifp->if_index; 603 } else { 604 info.rti_info[RTAX_IFP] = NULL; 605 info.rti_info[RTAX_IFA] = NULL; 606 } 607 (void)rt_msg2(rtm->rtm_type, &info, NULL, NULL, &len); 608 if (len > rtm->rtm_msglen) { 609 old_rtm = rtm; 610 R_Malloc(rtm, struct rt_xmsghdr *, len); 611 if (rtm == NULL) 612 senderr(ENOBUFS); 613 (void)memcpy(rtm, old_rtm, old_rtm->rtm_msglen); 614 } 615 (void)rt_msg2(rtm->rtm_type, &info, rtm, NULL, 0); 616 rtm->rtm_flags = rt->rt_flags; 617 rtm_setmetrics(rt, rtm); 618 rtm->rtm_addrs = info.rti_addrs; 619 break; 620 621 case RTM_CHANGE: 622 /* 623 * new gateway could require new ifaddr, ifp; 624 * flags may also be different; ifp may be specified 625 * by ll sockaddr when protocol address is ambiguous 626 */ 627 if ((error = rt_getifa(&info)) != 0) 628 senderr(error); 629 if (info.rti_info[RTAX_GATEWAY] && 630 rt_setgate(rt, info.rti_info[RTAX_GATEWAY])) 631 senderr(EDQUOT); 632 if (info.rti_info[RTAX_TAG]) 633 rt_settag(rt, info.rti_info[RTAX_TAG]); 634 /* new gateway could require new ifaddr, ifp; 635 flags may also be different; ifp may be specified 636 by ll sockaddr when protocol address is ambiguous */ 637 if (info.rti_info[RTAX_IFP] && 638 (ifa = ifa_ifwithnet(info.rti_info[RTAX_IFP])) && 639 (ifp = ifa->ifa_ifp) && (info.rti_info[RTAX_IFA] || 640 info.rti_info[RTAX_GATEWAY])) { 641 if (info.rti_info[RTAX_IFA] == NULL || 642 (ifa = ifa_ifwithaddr( 643 info.rti_info[RTAX_IFA])) == NULL) 644 ifa = ifaof_ifpforaddr( 645 info.rti_info[RTAX_IFA] ? 646 info.rti_info[RTAX_IFA] : 647 info.rti_info[RTAX_GATEWAY], ifp); 648 } else if ((info.rti_info[RTAX_IFA] && 649 (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) || 650 (info.rti_info[RTAX_GATEWAY] && 651 (ifa = ifa_ifwithroute(rt->rt_flags, 652 rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) { 653 ifp = ifa->ifa_ifp; 654 } 655 if (ifa) { 656 struct ifaddr *oifa = rt->rt_ifa; 657 if (oifa != ifa) { 658 if (oifa && oifa->ifa_rtrequest) { 659 oifa->ifa_rtrequest(RTM_DELETE, 660 rt, &info); 661 } 662 rt_replace_ifa(rt, ifa); 663 rt->rt_ifp = ifp; 664 } 665 } 666 if (ifp && rt->rt_ifp != ifp) 667 rt->rt_ifp = ifp; 668 rt_setmetrics(rtm->rtm_inits, rtm, rt); 669 if (rt->rt_flags != info.rti_flags) 670 rt->rt_flags = (info.rti_flags & ~PRESERVED_RTF) 671 | (rt->rt_flags & PRESERVED_RTF); 672 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 673 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 674 /*FALLTHROUGH*/ 675 case RTM_LOCK: 676 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 677 rt->rt_rmx.rmx_locks |= 678 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 679 break; 680 } 681 break; 682 683 default: 684 senderr(EOPNOTSUPP); 685 } 686 687 flush: 688 if (rtm) { 689 if (error) 690 rtm->rtm_errno = error; 691 else 692 rtm->rtm_flags |= RTF_DONE; 693 } 694 family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : 695 0; 696 /* We cannot free old_rtm until we have stopped using the 697 * pointers in info, some of which may point to sockaddrs 698 * in old_rtm. 699 */ 700 if (old_rtm != NULL) 701 Free(old_rtm); 702 if (rt) 703 rtfree(rt); 704 { 705 struct rawcb *rp = NULL; 706 /* 707 * Check to see if we don't want our own messages. 708 */ 709 if ((so->so_options & SO_USELOOPBACK) == 0) { 710 if (COMPATNAME(route_info).ri_cb.any_count <= 1) { 711 if (rtm) 712 Free(rtm); 713 m_freem(m); 714 return error; 715 } 716 /* There is another listener, so construct message */ 717 rp = sotorawcb(so); 718 } 719 if (rtm) { 720 m_copyback(m, 0, rtm->rtm_msglen, rtm); 721 if (m->m_pkthdr.len < rtm->rtm_msglen) { 722 m_freem(m); 723 m = NULL; 724 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 725 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 726 Free(rtm); 727 } 728 if (rp) 729 rp->rcb_proto.sp_family = 0; /* Avoid us */ 730 if (family) 731 proto.sp_protocol = family; 732 if (m) 733 raw_input(m, &proto, &COMPATNAME(route_info).ri_src, 734 &COMPATNAME(route_info).ri_dst); 735 if (rp) 736 rp->rcb_proto.sp_family = PF_XROUTE; 737 } 738 return error; 739 } 740 741 static void 742 rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out) 743 { 744 #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e; 745 metric(RTV_RPIPE, rmx_recvpipe); 746 metric(RTV_SPIPE, rmx_sendpipe); 747 metric(RTV_SSTHRESH, rmx_ssthresh); 748 metric(RTV_RTT, rmx_rtt); 749 metric(RTV_RTTVAR, rmx_rttvar); 750 metric(RTV_HOPCOUNT, rmx_hopcount); 751 metric(RTV_MTU, rmx_mtu); 752 metric(RTV_EXPIRE, rmx_expire); 753 #undef metric 754 } 755 756 static void 757 rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out) 758 { 759 #define metric(e) out->rtm_rmx.e = in->rt_rmx.e; 760 metric(rmx_recvpipe); 761 metric(rmx_sendpipe); 762 metric(rmx_ssthresh); 763 metric(rmx_rtt); 764 metric(rmx_rttvar); 765 metric(rmx_hopcount); 766 metric(rmx_mtu); 767 metric(rmx_expire); 768 #undef metric 769 } 770 771 static int 772 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, 773 struct rt_addrinfo *rtinfo) 774 { 775 const struct sockaddr *sa = NULL; /* Quell compiler warning */ 776 int i; 777 778 for (i = 0; i < RTAX_MAX && cp < cplim; i++) { 779 if ((rtinfo->rti_addrs & (1 << i)) == 0) 780 continue; 781 rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; 782 RT_XADVANCE(cp, sa); 783 } 784 785 /* 786 * Check for extra addresses specified, except RTM_GET asking 787 * for interface info. 788 */ 789 if (rtmtype == RTM_GET) { 790 if (((rtinfo->rti_addrs & 791 (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0) 792 return 1; 793 } else if ((rtinfo->rti_addrs & (~0 << i)) != 0) 794 return 1; 795 /* Check for bad data length. */ 796 if (cp != cplim) { 797 if (i == RTAX_NETMASK + 1 && sa != NULL && 798 cp - RT_XROUNDUP(sa->sa_len) + sa->sa_len == cplim) 799 /* 800 * The last sockaddr was info.rti_info[RTAX_NETMASK]. 801 * We accept this for now for the sake of old 802 * binaries or third party softwares. 803 */ 804 ; 805 else 806 return 1; 807 } 808 return 0; 809 } 810 811 static int 812 rt_getlen(int type) 813 { 814 #ifndef COMPAT_RTSOCK 815 CTASSERT(__alignof(struct ifa_msghdr) >= sizeof(uint64_t)); 816 CTASSERT(__alignof(struct if_msghdr) >= sizeof(uint64_t)); 817 CTASSERT(__alignof(struct if_announcemsghdr) >= sizeof(uint64_t)); 818 CTASSERT(__alignof(struct rt_msghdr) >= sizeof(uint64_t)); 819 #endif 820 821 switch (type) { 822 case RTM_DELADDR: 823 case RTM_NEWADDR: 824 case RTM_CHGADDR: 825 return sizeof(struct ifa_xmsghdr); 826 827 case RTM_OOIFINFO: 828 #ifdef COMPAT_14 829 return sizeof(struct if_msghdr14); 830 #else 831 #ifdef DIAGNOSTIC 832 printf("RTM_OOIFINFO\n"); 833 #endif 834 return -1; 835 #endif 836 case RTM_OIFINFO: 837 #ifdef COMPAT_50 838 return sizeof(struct if_msghdr50); 839 #else 840 #ifdef DIAGNOSTIC 841 printf("RTM_OIFINFO\n"); 842 #endif 843 return -1; 844 #endif 845 846 case RTM_IFINFO: 847 return sizeof(struct if_xmsghdr); 848 849 case RTM_IFANNOUNCE: 850 case RTM_IEEE80211: 851 return sizeof(struct if_xannouncemsghdr); 852 853 default: 854 return sizeof(struct rt_xmsghdr); 855 } 856 } 857 858 859 struct mbuf * 860 COMPATNAME(rt_msg1)(int type, struct rt_addrinfo *rtinfo, void *data, int datalen) 861 { 862 struct rt_xmsghdr *rtm; 863 struct mbuf *m; 864 int i; 865 const struct sockaddr *sa; 866 int len, dlen; 867 868 m = m_gethdr(M_DONTWAIT, MT_DATA); 869 if (m == NULL) 870 return m; 871 MCLAIM(m, &COMPATNAME(routedomain).dom_mowner); 872 873 if ((len = rt_getlen(type)) == -1) 874 goto out; 875 if (len > MHLEN + MLEN) 876 panic("%s: message too long", __func__); 877 else if (len > MHLEN) { 878 m->m_next = m_get(M_DONTWAIT, MT_DATA); 879 if (m->m_next == NULL) 880 goto out; 881 MCLAIM(m->m_next, m->m_owner); 882 m->m_pkthdr.len = len; 883 m->m_len = MHLEN; 884 m->m_next->m_len = len - MHLEN; 885 } else { 886 m->m_pkthdr.len = m->m_len = len; 887 } 888 m->m_pkthdr.rcvif = NULL; 889 m_copyback(m, 0, datalen, data); 890 if (len > datalen) 891 (void)memset(mtod(m, char *) + datalen, 0, len - datalen); 892 rtm = mtod(m, struct rt_xmsghdr *); 893 for (i = 0; i < RTAX_MAX; i++) { 894 if ((sa = rtinfo->rti_info[i]) == NULL) 895 continue; 896 rtinfo->rti_addrs |= (1 << i); 897 dlen = RT_XROUNDUP(sa->sa_len); 898 m_copyback(m, len, sa->sa_len, sa); 899 if (dlen != sa->sa_len) { 900 /* 901 * Up to 6 + 1 nul's since roundup is to 902 * sizeof(uint64_t) (8 bytes) 903 */ 904 m_copyback(m, len + sa->sa_len, 905 dlen - sa->sa_len, "\0\0\0\0\0\0"); 906 } 907 len += dlen; 908 } 909 if (m->m_pkthdr.len != len) 910 goto out; 911 rtm->rtm_msglen = len; 912 rtm->rtm_version = RTM_XVERSION; 913 rtm->rtm_type = type; 914 return m; 915 out: 916 m_freem(m); 917 return NULL; 918 } 919 920 /* 921 * rt_msg2 922 * 923 * fills 'cp' or 'w'.w_tmem with the routing socket message and 924 * returns the length of the message in 'lenp'. 925 * 926 * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold 927 * the message 928 * otherwise walkarg's w_needed is updated and if the user buffer is 929 * specified and w_needed indicates space exists the information is copied 930 * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, 931 * if the allocation fails ENOBUFS is returned. 932 */ 933 static int 934 rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, 935 int *lenp) 936 { 937 int i; 938 int len, dlen, second_time = 0; 939 char *cp0, *cp = cpv; 940 941 rtinfo->rti_addrs = 0; 942 again: 943 if ((len = rt_getlen(type)) == -1) 944 return EINVAL; 945 946 if ((cp0 = cp) != NULL) 947 cp += len; 948 for (i = 0; i < RTAX_MAX; i++) { 949 const struct sockaddr *sa; 950 951 if ((sa = rtinfo->rti_info[i]) == NULL) 952 continue; 953 rtinfo->rti_addrs |= (1 << i); 954 dlen = RT_XROUNDUP(sa->sa_len); 955 if (cp) { 956 int diff = dlen - sa->sa_len; 957 (void)memcpy(cp, sa, (size_t)sa->sa_len); 958 cp += sa->sa_len; 959 if (diff > 0) { 960 (void)memset(cp, 0, (size_t)diff); 961 cp += diff; 962 } 963 } 964 len += dlen; 965 } 966 if (cp == NULL && w != NULL && !second_time) { 967 struct rt_walkarg *rw = w; 968 969 rw->w_needed += len; 970 if (rw->w_needed <= 0 && rw->w_where) { 971 if (rw->w_tmemsize < len) { 972 if (rw->w_tmem) 973 free(rw->w_tmem, M_RTABLE); 974 rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT); 975 if (rw->w_tmem) 976 rw->w_tmemsize = len; 977 else 978 rw->w_tmemsize = 0; 979 } 980 if (rw->w_tmem) { 981 cp = rw->w_tmem; 982 second_time = 1; 983 goto again; 984 } else { 985 rw->w_tmemneeded = len; 986 return ENOBUFS; 987 } 988 } 989 } 990 if (cp) { 991 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)cp0; 992 993 rtm->rtm_version = RTM_XVERSION; 994 rtm->rtm_type = type; 995 rtm->rtm_msglen = len; 996 } 997 if (lenp) 998 *lenp = len; 999 return 0; 1000 } 1001 1002 /* 1003 * This routine is called to generate a message from the routing 1004 * socket indicating that a redirect has occurred, a routing lookup 1005 * has failed, or that a protocol has detected timeouts to a particular 1006 * destination. 1007 */ 1008 void 1009 COMPATNAME(rt_missmsg)(int type, const struct rt_addrinfo *rtinfo, int flags, 1010 int error) 1011 { 1012 struct rt_xmsghdr rtm; 1013 struct mbuf *m; 1014 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 1015 struct rt_addrinfo info = *rtinfo; 1016 1017 COMPATCALL(rt_missmsg, (type, rtinfo, flags, error)); 1018 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1019 return; 1020 memset(&rtm, 0, sizeof(rtm)); 1021 rtm.rtm_flags = RTF_DONE | flags; 1022 rtm.rtm_errno = error; 1023 m = COMPATNAME(rt_msg1)(type, &info, &rtm, sizeof(rtm)); 1024 if (m == NULL) 1025 return; 1026 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; 1027 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); 1028 } 1029 1030 /* 1031 * This routine is called to generate a message from the routing 1032 * socket indicating that the status of a network interface has changed. 1033 */ 1034 void 1035 COMPATNAME(rt_ifmsg)(struct ifnet *ifp) 1036 { 1037 struct if_xmsghdr ifm; 1038 struct mbuf *m; 1039 struct rt_addrinfo info; 1040 1041 COMPATCALL(rt_ifmsg, (ifp)); 1042 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1043 return; 1044 (void)memset(&info, 0, sizeof(info)); 1045 (void)memset(&ifm, 0, sizeof(ifm)); 1046 ifm.ifm_index = ifp->if_index; 1047 ifm.ifm_flags = ifp->if_flags; 1048 ifm.ifm_data = ifp->if_data; 1049 ifm.ifm_addrs = 0; 1050 m = COMPATNAME(rt_msg1)(RTM_IFINFO, &info, &ifm, sizeof(ifm)); 1051 if (m == NULL) 1052 return; 1053 COMPATNAME(route_enqueue)(m, 0); 1054 #ifdef COMPAT_14 1055 compat_14_rt_oifmsg(ifp); 1056 #endif 1057 #ifdef COMPAT_50 1058 compat_50_rt_oifmsg(ifp); 1059 #endif 1060 } 1061 1062 1063 /* 1064 * This is called to generate messages from the routing socket 1065 * indicating a network interface has had addresses associated with it. 1066 * if we ever reverse the logic and replace messages TO the routing 1067 * socket indicate a request to configure interfaces, then it will 1068 * be unnecessary as the routing socket will automatically generate 1069 * copies of it. 1070 */ 1071 void 1072 COMPATNAME(rt_newaddrmsg)(int cmd, struct ifaddr *ifa, int error, 1073 struct rtentry *rt) 1074 { 1075 #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass)) 1076 struct rt_addrinfo info; 1077 const struct sockaddr *sa; 1078 int pass; 1079 struct mbuf *m; 1080 struct ifnet *ifp; 1081 struct rt_xmsghdr rtm; 1082 struct ifa_xmsghdr ifam; 1083 int ncmd; 1084 1085 KASSERT(ifa != NULL); 1086 ifp = ifa->ifa_ifp; 1087 COMPATCALL(rt_newaddrmsg, (cmd, ifa, error, rt)); 1088 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1089 return; 1090 for (pass = 1; pass < 3; pass++) { 1091 memset(&info, 0, sizeof(info)); 1092 switch (cmdpass(cmd, pass)) { 1093 case cmdpass(RTM_ADD, 1): 1094 case cmdpass(RTM_CHANGE, 1): 1095 case cmdpass(RTM_DELETE, 2): 1096 case cmdpass(RTM_NEWADDR, 1): 1097 case cmdpass(RTM_DELADDR, 1): 1098 case cmdpass(RTM_CHGADDR, 1): 1099 switch (cmd) { 1100 case RTM_ADD: 1101 ncmd = RTM_NEWADDR; 1102 break; 1103 case RTM_DELETE: 1104 ncmd = RTM_DELADDR; 1105 break; 1106 case RTM_CHANGE: 1107 ncmd = RTM_CHGADDR; 1108 break; 1109 default: 1110 ncmd = cmd; 1111 } 1112 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; 1113 KASSERT(ifp->if_dl != NULL); 1114 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 1115 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1116 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1117 memset(&ifam, 0, sizeof(ifam)); 1118 ifam.ifam_index = ifp->if_index; 1119 ifam.ifam_metric = ifa->ifa_metric; 1120 ifam.ifam_flags = ifa->ifa_flags; 1121 m = COMPATNAME(rt_msg1)(ncmd, &info, &ifam, sizeof(ifam)); 1122 if (m == NULL) 1123 continue; 1124 mtod(m, struct ifa_xmsghdr *)->ifam_addrs = 1125 info.rti_addrs; 1126 break; 1127 case cmdpass(RTM_ADD, 2): 1128 case cmdpass(RTM_CHANGE, 2): 1129 case cmdpass(RTM_DELETE, 1): 1130 if (rt == NULL) 1131 continue; 1132 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1133 info.rti_info[RTAX_DST] = sa = rt_getkey(rt); 1134 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1135 memset(&rtm, 0, sizeof(rtm)); 1136 rtm.rtm_index = ifp->if_index; 1137 rtm.rtm_flags |= rt->rt_flags; 1138 rtm.rtm_errno = error; 1139 m = COMPATNAME(rt_msg1)(cmd, &info, &rtm, sizeof(rtm)); 1140 if (m == NULL) 1141 continue; 1142 mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; 1143 break; 1144 default: 1145 continue; 1146 } 1147 #ifdef DIAGNOSTIC 1148 if (m == NULL) 1149 panic("%s: called with wrong command", __func__); 1150 #endif 1151 COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); 1152 } 1153 #undef cmdpass 1154 } 1155 1156 static struct mbuf * 1157 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, 1158 struct rt_addrinfo *info) 1159 { 1160 struct if_xannouncemsghdr ifan; 1161 1162 memset(info, 0, sizeof(*info)); 1163 memset(&ifan, 0, sizeof(ifan)); 1164 ifan.ifan_index = ifp->if_index; 1165 strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); 1166 ifan.ifan_what = what; 1167 return COMPATNAME(rt_msg1)(type, info, &ifan, sizeof(ifan)); 1168 } 1169 1170 /* 1171 * This is called to generate routing socket messages indicating 1172 * network interface arrival and departure. 1173 */ 1174 void 1175 COMPATNAME(rt_ifannouncemsg)(struct ifnet *ifp, int what) 1176 { 1177 struct mbuf *m; 1178 struct rt_addrinfo info; 1179 1180 COMPATCALL(rt_ifannouncemsg, (ifp, what)); 1181 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1182 return; 1183 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info); 1184 if (m == NULL) 1185 return; 1186 COMPATNAME(route_enqueue)(m, 0); 1187 } 1188 1189 /* 1190 * This is called to generate routing socket messages indicating 1191 * IEEE80211 wireless events. 1192 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way. 1193 */ 1194 void 1195 COMPATNAME(rt_ieee80211msg)(struct ifnet *ifp, int what, void *data, 1196 size_t data_len) 1197 { 1198 struct mbuf *m; 1199 struct rt_addrinfo info; 1200 1201 COMPATCALL(rt_ieee80211msg, (ifp, what, data, data_len)); 1202 if (COMPATNAME(route_info).ri_cb.any_count == 0) 1203 return; 1204 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info); 1205 if (m == NULL) 1206 return; 1207 /* 1208 * Append the ieee80211 data. Try to stick it in the 1209 * mbuf containing the ifannounce msg; otherwise allocate 1210 * a new mbuf and append. 1211 * 1212 * NB: we assume m is a single mbuf. 1213 */ 1214 if (data_len > M_TRAILINGSPACE(m)) { 1215 struct mbuf *n = m_get(M_NOWAIT, MT_DATA); 1216 if (n == NULL) { 1217 m_freem(m); 1218 return; 1219 } 1220 (void)memcpy(mtod(n, void *), data, data_len); 1221 n->m_len = data_len; 1222 m->m_next = n; 1223 } else if (data_len > 0) { 1224 (void)memcpy(mtod(m, uint8_t *) + m->m_len, data, data_len); 1225 m->m_len += data_len; 1226 } 1227 if (m->m_flags & M_PKTHDR) 1228 m->m_pkthdr.len += data_len; 1229 mtod(m, struct if_xannouncemsghdr *)->ifan_msglen += data_len; 1230 COMPATNAME(route_enqueue)(m, 0); 1231 } 1232 1233 /* 1234 * This is used in dumping the kernel table via sysctl(). 1235 */ 1236 static int 1237 sysctl_dumpentry(struct rtentry *rt, void *v) 1238 { 1239 struct rt_walkarg *w = v; 1240 int error = 0, size; 1241 struct rt_addrinfo info; 1242 1243 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 1244 return 0; 1245 memset(&info, 0, sizeof(info)); 1246 info.rti_info[RTAX_DST] = rt_getkey(rt); 1247 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1248 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1249 info.rti_info[RTAX_TAG] = rt_gettag(rt); 1250 if (rt->rt_ifp) { 1251 const struct ifaddr *rtifa; 1252 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr; 1253 /* rtifa used to be simply rt->rt_ifa. If rt->rt_ifa != NULL, 1254 * then rt_get_ifa() != NULL. So this ought to still be safe. 1255 * --dyoung 1256 */ 1257 rtifa = rt_get_ifa(rt); 1258 info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 1259 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 1260 info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; 1261 } 1262 if ((error = rt_msg2(RTM_GET, &info, 0, w, &size))) 1263 return error; 1264 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1265 struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)w->w_tmem; 1266 1267 rtm->rtm_flags = rt->rt_flags; 1268 rtm->rtm_use = rt->rt_use; 1269 rtm_setmetrics(rt, rtm); 1270 KASSERT(rt->rt_ifp != NULL); 1271 rtm->rtm_index = rt->rt_ifp->if_index; 1272 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 1273 rtm->rtm_addrs = info.rti_addrs; 1274 if ((error = copyout(rtm, w->w_where, size)) != 0) 1275 w->w_where = NULL; 1276 else 1277 w->w_where = (char *)w->w_where + size; 1278 } 1279 return error; 1280 } 1281 1282 static int 1283 sysctl_iflist(int af, struct rt_walkarg *w, int type) 1284 { 1285 struct ifnet *ifp; 1286 struct ifaddr *ifa; 1287 struct rt_addrinfo info; 1288 int len, error = 0; 1289 1290 memset(&info, 0, sizeof(info)); 1291 IFNET_FOREACH(ifp) { 1292 if (w->w_arg && w->w_arg != ifp->if_index) 1293 continue; 1294 if (IFADDR_EMPTY(ifp)) 1295 continue; 1296 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 1297 switch (type) { 1298 case NET_RT_IFLIST: 1299 error = rt_msg2(RTM_IFINFO, &info, NULL, w, &len); 1300 break; 1301 #ifdef COMPAT_14 1302 case NET_RT_OOIFLIST: 1303 error = rt_msg2(RTM_OOIFINFO, &info, NULL, w, &len); 1304 break; 1305 #endif 1306 #ifdef COMPAT_50 1307 case NET_RT_OIFLIST: 1308 error = rt_msg2(RTM_OIFINFO, &info, NULL, w, &len); 1309 break; 1310 #endif 1311 default: 1312 panic("sysctl_iflist(1)"); 1313 } 1314 if (error) 1315 return error; 1316 info.rti_info[RTAX_IFP] = NULL; 1317 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1318 switch (type) { 1319 case NET_RT_IFLIST: { 1320 struct if_xmsghdr *ifm; 1321 1322 ifm = (struct if_xmsghdr *)w->w_tmem; 1323 ifm->ifm_index = ifp->if_index; 1324 ifm->ifm_flags = ifp->if_flags; 1325 ifm->ifm_data = ifp->if_data; 1326 ifm->ifm_addrs = info.rti_addrs; 1327 error = copyout(ifm, w->w_where, len); 1328 if (error) 1329 return error; 1330 w->w_where = (char *)w->w_where + len; 1331 break; 1332 } 1333 1334 #ifdef COMPAT_14 1335 case NET_RT_OOIFLIST: 1336 error = compat_14_iflist(ifp, w, &info, len); 1337 if (error) 1338 return error; 1339 break; 1340 #endif 1341 #ifdef COMPAT_50 1342 case NET_RT_OIFLIST: 1343 error = compat_50_iflist(ifp, w, &info, len); 1344 if (error) 1345 return error; 1346 break; 1347 #endif 1348 default: 1349 panic("sysctl_iflist(2)"); 1350 } 1351 } 1352 IFADDR_FOREACH(ifa, ifp) { 1353 if (af && af != ifa->ifa_addr->sa_family) 1354 continue; 1355 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1356 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1357 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1358 if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len))) 1359 return error; 1360 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1361 struct ifa_xmsghdr *ifam; 1362 1363 ifam = (struct ifa_xmsghdr *)w->w_tmem; 1364 ifam->ifam_index = ifa->ifa_ifp->if_index; 1365 ifam->ifam_flags = ifa->ifa_flags; 1366 ifam->ifam_metric = ifa->ifa_metric; 1367 ifam->ifam_addrs = info.rti_addrs; 1368 error = copyout(w->w_tmem, w->w_where, len); 1369 if (error) 1370 return error; 1371 w->w_where = (char *)w->w_where + len; 1372 } 1373 } 1374 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 1375 info.rti_info[RTAX_BRD] = NULL; 1376 } 1377 return 0; 1378 } 1379 1380 static int 1381 sysctl_rtable(SYSCTLFN_ARGS) 1382 { 1383 void *where = oldp; 1384 size_t *given = oldlenp; 1385 int i, s, error = EINVAL; 1386 u_char af; 1387 struct rt_walkarg w; 1388 1389 if (namelen == 1 && name[0] == CTL_QUERY) 1390 return sysctl_query(SYSCTLFN_CALL(rnode)); 1391 1392 if (newp) 1393 return EPERM; 1394 if (namelen != 3) 1395 return EINVAL; 1396 af = name[0]; 1397 w.w_tmemneeded = 0; 1398 w.w_tmemsize = 0; 1399 w.w_tmem = NULL; 1400 again: 1401 /* we may return here if a later [re]alloc of the t_mem buffer fails */ 1402 if (w.w_tmemneeded) { 1403 w.w_tmem = malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK); 1404 w.w_tmemsize = w.w_tmemneeded; 1405 w.w_tmemneeded = 0; 1406 } 1407 w.w_op = name[1]; 1408 w.w_arg = name[2]; 1409 w.w_given = *given; 1410 w.w_needed = 0 - w.w_given; 1411 w.w_where = where; 1412 1413 s = splsoftnet(); 1414 switch (w.w_op) { 1415 1416 case NET_RT_DUMP: 1417 case NET_RT_FLAGS: 1418 for (i = 1; i <= AF_MAX; i++) 1419 if ((af == 0 || af == i) && 1420 (error = rt_walktree(i, sysctl_dumpentry, &w))) 1421 break; 1422 break; 1423 1424 #ifdef COMPAT_14 1425 case NET_RT_OOIFLIST: 1426 error = sysctl_iflist(af, &w, w.w_op); 1427 break; 1428 #endif 1429 #ifdef COMPAT_50 1430 case NET_RT_OIFLIST: 1431 error = sysctl_iflist(af, &w, w.w_op); 1432 break; 1433 #endif 1434 case NET_RT_IFLIST: 1435 error = sysctl_iflist(af, &w, w.w_op); 1436 break; 1437 } 1438 splx(s); 1439 1440 /* check to see if we couldn't allocate memory with NOWAIT */ 1441 if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded) 1442 goto again; 1443 1444 if (w.w_tmem) 1445 free(w.w_tmem, M_RTABLE); 1446 w.w_needed += w.w_given; 1447 if (where) { 1448 *given = (char *)w.w_where - (char *)where; 1449 if (*given < w.w_needed) 1450 return ENOMEM; 1451 } else { 1452 *given = (11 * w.w_needed) / 10; 1453 } 1454 return error; 1455 } 1456 1457 /* 1458 * Routing message software interrupt routine 1459 */ 1460 static void 1461 COMPATNAME(route_intr)(void *cookie) 1462 { 1463 struct sockproto proto = { .sp_family = PF_XROUTE, }; 1464 struct route_info * const ri = &COMPATNAME(route_info); 1465 struct mbuf *m; 1466 int s; 1467 1468 mutex_enter(softnet_lock); 1469 KERNEL_LOCK(1, NULL); 1470 while (!IF_IS_EMPTY(&ri->ri_intrq)) { 1471 s = splnet(); 1472 IF_DEQUEUE(&ri->ri_intrq, m); 1473 splx(s); 1474 if (m == NULL) 1475 break; 1476 proto.sp_protocol = M_GETCTX(m, uintptr_t); 1477 raw_input(m, &proto, &ri->ri_src, &ri->ri_dst); 1478 } 1479 KERNEL_UNLOCK_ONE(NULL); 1480 mutex_exit(softnet_lock); 1481 } 1482 1483 /* 1484 * Enqueue a message to the software interrupt routine. 1485 */ 1486 void 1487 COMPATNAME(route_enqueue)(struct mbuf *m, int family) 1488 { 1489 struct route_info * const ri = &COMPATNAME(route_info); 1490 int s, wasempty; 1491 1492 s = splnet(); 1493 if (IF_QFULL(&ri->ri_intrq)) { 1494 IF_DROP(&ri->ri_intrq); 1495 m_freem(m); 1496 } else { 1497 wasempty = IF_IS_EMPTY(&ri->ri_intrq); 1498 M_SETCTX(m, (uintptr_t)family); 1499 IF_ENQUEUE(&ri->ri_intrq, m); 1500 if (wasempty) 1501 softint_schedule(ri->ri_sih); 1502 } 1503 splx(s); 1504 } 1505 1506 static void 1507 COMPATNAME(route_init)(void) 1508 { 1509 struct route_info * const ri = &COMPATNAME(route_info); 1510 1511 #ifndef COMPAT_RTSOCK 1512 rt_init(); 1513 #endif 1514 1515 sysctl_net_route_setup(NULL); 1516 ri->ri_intrq.ifq_maxlen = ri->ri_maxqlen; 1517 ri->ri_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, 1518 COMPATNAME(route_intr), NULL); 1519 } 1520 1521 /* 1522 * Definitions of protocols supported in the ROUTE domain. 1523 */ 1524 #ifndef COMPAT_RTSOCK 1525 PR_WRAP_USRREQS(route); 1526 #else 1527 PR_WRAP_USRREQS(compat_50_route); 1528 #endif 1529 1530 static const struct pr_usrreqs route_usrreqs = { 1531 .pr_attach = COMPATNAME(route_attach_wrapper), 1532 .pr_detach = COMPATNAME(route_detach_wrapper), 1533 .pr_accept = COMPATNAME(route_accept_wrapper), 1534 .pr_bind = COMPATNAME(route_bind_wrapper), 1535 .pr_listen = COMPATNAME(route_listen_wrapper), 1536 .pr_connect = COMPATNAME(route_connect_wrapper), 1537 .pr_connect2 = COMPATNAME(route_connect2_wrapper), 1538 .pr_disconnect = COMPATNAME(route_disconnect_wrapper), 1539 .pr_shutdown = COMPATNAME(route_shutdown_wrapper), 1540 .pr_abort = COMPATNAME(route_abort_wrapper), 1541 .pr_ioctl = COMPATNAME(route_ioctl_wrapper), 1542 .pr_stat = COMPATNAME(route_stat_wrapper), 1543 .pr_peeraddr = COMPATNAME(route_peeraddr_wrapper), 1544 .pr_sockaddr = COMPATNAME(route_sockaddr_wrapper), 1545 .pr_rcvd = COMPATNAME(route_rcvd_wrapper), 1546 .pr_recvoob = COMPATNAME(route_recvoob_wrapper), 1547 .pr_send = COMPATNAME(route_send_wrapper), 1548 .pr_sendoob = COMPATNAME(route_sendoob_wrapper), 1549 .pr_purgeif = COMPATNAME(route_purgeif_wrapper), 1550 .pr_generic = COMPATNAME(route_usrreq_wrapper), 1551 }; 1552 1553 static const struct protosw COMPATNAME(route_protosw)[] = { 1554 { 1555 .pr_type = SOCK_RAW, 1556 .pr_domain = &COMPATNAME(routedomain), 1557 .pr_flags = PR_ATOMIC|PR_ADDR, 1558 .pr_input = raw_input, 1559 .pr_output = COMPATNAME(route_output), 1560 .pr_ctlinput = raw_ctlinput, 1561 .pr_usrreqs = &route_usrreqs, 1562 .pr_init = raw_init, 1563 }, 1564 }; 1565 1566 struct domain COMPATNAME(routedomain) = { 1567 .dom_family = PF_XROUTE, 1568 .dom_name = DOMAINNAME, 1569 .dom_init = COMPATNAME(route_init), 1570 .dom_protosw = COMPATNAME(route_protosw), 1571 .dom_protoswNPROTOSW = 1572 &COMPATNAME(route_protosw)[__arraycount(COMPATNAME(route_protosw))], 1573 }; 1574 1575 static void 1576 sysctl_net_route_setup(struct sysctllog **clog) 1577 { 1578 const struct sysctlnode *rnode = NULL; 1579 1580 sysctl_createv(clog, 0, NULL, &rnode, 1581 CTLFLAG_PERMANENT, 1582 CTLTYPE_NODE, DOMAINNAME, 1583 SYSCTL_DESCR("PF_ROUTE information"), 1584 NULL, 0, NULL, 0, 1585 CTL_NET, PF_XROUTE, CTL_EOL); 1586 1587 sysctl_createv(clog, 0, NULL, NULL, 1588 CTLFLAG_PERMANENT, 1589 CTLTYPE_NODE, "rtable", 1590 SYSCTL_DESCR("Routing table information"), 1591 sysctl_rtable, 0, NULL, 0, 1592 CTL_NET, PF_XROUTE, 0 /* any protocol */, CTL_EOL); 1593 1594 sysctl_createv(clog, 0, &rnode, NULL, 1595 CTLFLAG_PERMANENT, 1596 CTLTYPE_STRUCT, "stats", 1597 SYSCTL_DESCR("Routing statistics"), 1598 NULL, 0, &rtstat, sizeof(rtstat), 1599 CTL_CREATE, CTL_EOL); 1600 } 1601