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