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