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