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