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