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