1 /* $NetBSD: rtsock.c,v 1.127 2009/09/16 15:23:04 pooka 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.127 2009/09/16 15:23:04 pooka 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 ifa = ifaof_ifpforaddr(info.rti_info[RTAX_IFA] ? 414 info.rti_info[RTAX_IFA] : 415 info.rti_info[RTAX_GATEWAY], ifp); 416 } else if ((info.rti_info[RTAX_IFA] && 417 (ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]))) || 418 (info.rti_info[RTAX_GATEWAY] && 419 (ifa = ifa_ifwithroute(rt->rt_flags, 420 rt_getkey(rt), info.rti_info[RTAX_GATEWAY])))) { 421 ifp = ifa->ifa_ifp; 422 } 423 if (ifa) { 424 struct ifaddr *oifa = rt->rt_ifa; 425 if (oifa != ifa) { 426 if (oifa && oifa->ifa_rtrequest) { 427 oifa->ifa_rtrequest(RTM_DELETE, 428 rt, &info); 429 } 430 rt_replace_ifa(rt, ifa); 431 rt->rt_ifp = ifp; 432 } 433 } 434 rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, 435 &rt->rt_rmx); 436 if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) 437 rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info); 438 /*FALLTHROUGH*/ 439 case RTM_LOCK: 440 rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); 441 rt->rt_rmx.rmx_locks |= 442 (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); 443 break; 444 } 445 break; 446 447 default: 448 senderr(EOPNOTSUPP); 449 } 450 451 flush: 452 if (rtm) { 453 if (error) 454 rtm->rtm_errno = error; 455 else 456 rtm->rtm_flags |= RTF_DONE; 457 } 458 family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : 459 0; 460 /* We cannot free old_rtm until we have stopped using the 461 * pointers in info, some of which may point to sockaddrs 462 * in old_rtm. 463 */ 464 if (old_rtm != NULL) 465 Free(old_rtm); 466 if (rt) 467 rtfree(rt); 468 { 469 struct rawcb *rp = NULL; 470 /* 471 * Check to see if we don't want our own messages. 472 */ 473 if ((so->so_options & SO_USELOOPBACK) == 0) { 474 if (route_cb.any_count <= 1) { 475 if (rtm) 476 Free(rtm); 477 m_freem(m); 478 return error; 479 } 480 /* There is another listener, so construct message */ 481 rp = sotorawcb(so); 482 } 483 if (rtm) { 484 m_copyback(m, 0, rtm->rtm_msglen, rtm); 485 if (m->m_pkthdr.len < rtm->rtm_msglen) { 486 m_freem(m); 487 m = NULL; 488 } else if (m->m_pkthdr.len > rtm->rtm_msglen) 489 m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); 490 Free(rtm); 491 } 492 if (rp) 493 rp->rcb_proto.sp_family = 0; /* Avoid us */ 494 if (family) 495 proto.sp_protocol = family; 496 if (m) 497 raw_input(m, &proto, &route_src, &route_dst); 498 if (rp) 499 rp->rcb_proto.sp_family = PF_ROUTE; 500 } 501 return error; 502 } 503 504 void 505 rt_setmetrics(u_long which, const struct rt_metrics *in, struct nrt_metrics *out) 506 { 507 #define metric(f, e) if (which & (f)) out->e = in->e; 508 metric(RTV_RPIPE, rmx_recvpipe); 509 metric(RTV_SPIPE, rmx_sendpipe); 510 metric(RTV_SSTHRESH, rmx_ssthresh); 511 metric(RTV_RTT, rmx_rtt); 512 metric(RTV_RTTVAR, rmx_rttvar); 513 metric(RTV_HOPCOUNT, rmx_hopcount); 514 metric(RTV_MTU, rmx_mtu); 515 /* XXX time_t: Will not work after February 2145 (u_long time) */ 516 metric(RTV_EXPIRE, rmx_expire); 517 #undef metric 518 } 519 520 static int 521 rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, 522 struct rt_addrinfo *rtinfo) 523 { 524 const struct sockaddr *sa = NULL; /* Quell compiler warning */ 525 int i; 526 527 for (i = 0; i < RTAX_MAX && cp < cplim; i++) { 528 if ((rtinfo->rti_addrs & (1 << i)) == 0) 529 continue; 530 rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; 531 RT_ADVANCE(cp, sa); 532 } 533 534 /* 535 * Check for extra addresses specified, except RTM_GET asking 536 * for interface info. 537 */ 538 if (rtmtype == RTM_GET) { 539 if (((rtinfo->rti_addrs & 540 (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0 << i)) != 0) 541 return 1; 542 } else if ((rtinfo->rti_addrs & (~0 << i)) != 0) 543 return 1; 544 /* Check for bad data length. */ 545 if (cp != cplim) { 546 if (i == RTAX_NETMASK + 1 && sa != NULL && 547 cp - RT_ROUNDUP(sa->sa_len) + sa->sa_len == cplim) 548 /* 549 * The last sockaddr was info.rti_info[RTAX_NETMASK]. 550 * We accept this for now for the sake of old 551 * binaries or third party softwares. 552 */ 553 ; 554 else 555 return 1; 556 } 557 return 0; 558 } 559 560 struct mbuf * 561 rt_msg1(int type, struct rt_addrinfo *rtinfo, void *data, int datalen) 562 { 563 struct rt_msghdr *rtm; 564 struct mbuf *m; 565 int i; 566 const struct sockaddr *sa; 567 int len, dlen; 568 569 m = m_gethdr(M_DONTWAIT, MT_DATA); 570 if (m == NULL) 571 return m; 572 MCLAIM(m, &routedomain.dom_mowner); 573 switch (type) { 574 575 case RTM_DELADDR: 576 case RTM_NEWADDR: 577 len = sizeof(struct ifa_msghdr); 578 break; 579 580 #ifdef COMPAT_14 581 case RTM_OOIFINFO: 582 len = sizeof(struct if_msghdr14); 583 break; 584 #endif 585 #ifdef COMPAT_50 586 case RTM_OIFINFO: 587 len = sizeof(struct if_msghdr50); 588 break; 589 #endif 590 591 case RTM_IFINFO: 592 len = sizeof(struct if_msghdr); 593 break; 594 595 case RTM_IFANNOUNCE: 596 case RTM_IEEE80211: 597 len = sizeof(struct if_announcemsghdr); 598 break; 599 600 default: 601 len = sizeof(struct rt_msghdr); 602 } 603 if (len > MHLEN + MLEN) 604 panic("rt_msg1: message too long"); 605 else if (len > MHLEN) { 606 m->m_next = m_get(M_DONTWAIT, MT_DATA); 607 if (m->m_next == NULL) { 608 m_freem(m); 609 return NULL; 610 } 611 MCLAIM(m->m_next, m->m_owner); 612 m->m_pkthdr.len = len; 613 m->m_len = MHLEN; 614 m->m_next->m_len = len - MHLEN; 615 } else { 616 m->m_pkthdr.len = m->m_len = len; 617 } 618 m->m_pkthdr.rcvif = NULL; 619 m_copyback(m, 0, datalen, data); 620 if (len > datalen) 621 (void)memset(mtod(m, char *) + datalen, 0, len - datalen); 622 rtm = mtod(m, struct rt_msghdr *); 623 for (i = 0; i < RTAX_MAX; i++) { 624 if ((sa = rtinfo->rti_info[i]) == NULL) 625 continue; 626 rtinfo->rti_addrs |= (1 << i); 627 dlen = RT_ROUNDUP(sa->sa_len); 628 m_copyback(m, len, dlen, sa); 629 len += dlen; 630 } 631 if (m->m_pkthdr.len != len) { 632 m_freem(m); 633 return NULL; 634 } 635 rtm->rtm_msglen = len; 636 rtm->rtm_version = RTM_VERSION; 637 rtm->rtm_type = type; 638 return m; 639 } 640 641 /* 642 * rt_msg2 643 * 644 * fills 'cp' or 'w'.w_tmem with the routing socket message and 645 * returns the length of the message in 'lenp'. 646 * 647 * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold 648 * the message 649 * otherwise walkarg's w_needed is updated and if the user buffer is 650 * specified and w_needed indicates space exists the information is copied 651 * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, 652 * if the allocation fails ENOBUFS is returned. 653 */ 654 static int 655 rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, 656 int *lenp) 657 { 658 int i; 659 int len, dlen, second_time = 0; 660 char *cp0, *cp = cpv; 661 662 rtinfo->rti_addrs = 0; 663 again: 664 switch (type) { 665 666 case RTM_DELADDR: 667 case RTM_NEWADDR: 668 len = sizeof(struct ifa_msghdr); 669 break; 670 #ifdef COMPAT_14 671 case RTM_OOIFINFO: 672 len = sizeof(struct if_msghdr14); 673 break; 674 #endif 675 #ifdef COMPAT_50 676 case RTM_OIFINFO: 677 len = sizeof(struct if_msghdr50); 678 break; 679 #endif 680 681 case RTM_IFINFO: 682 len = sizeof(struct if_msghdr); 683 break; 684 685 default: 686 len = sizeof(struct rt_msghdr); 687 } 688 if ((cp0 = cp) != NULL) 689 cp += len; 690 for (i = 0; i < RTAX_MAX; i++) { 691 const struct sockaddr *sa; 692 693 if ((sa = rtinfo->rti_info[i]) == NULL) 694 continue; 695 rtinfo->rti_addrs |= (1 << i); 696 dlen = RT_ROUNDUP(sa->sa_len); 697 if (cp) { 698 (void)memcpy(cp, sa, (size_t)dlen); 699 cp += dlen; 700 } 701 len += dlen; 702 } 703 if (cp == NULL && w != NULL && !second_time) { 704 struct rt_walkarg *rw = w; 705 706 rw->w_needed += len; 707 if (rw->w_needed <= 0 && rw->w_where) { 708 if (rw->w_tmemsize < len) { 709 if (rw->w_tmem) 710 free(rw->w_tmem, M_RTABLE); 711 rw->w_tmem = malloc(len, M_RTABLE, M_NOWAIT); 712 if (rw->w_tmem) 713 rw->w_tmemsize = len; 714 else 715 rw->w_tmemsize = 0; 716 } 717 if (rw->w_tmem) { 718 cp = rw->w_tmem; 719 second_time = 1; 720 goto again; 721 } else { 722 rw->w_tmemneeded = len; 723 return ENOBUFS; 724 } 725 } 726 } 727 if (cp) { 728 struct rt_msghdr *rtm = (struct rt_msghdr *)cp0; 729 730 rtm->rtm_version = RTM_VERSION; 731 rtm->rtm_type = type; 732 rtm->rtm_msglen = len; 733 } 734 if (lenp) 735 *lenp = len; 736 return 0; 737 } 738 739 /* 740 * This routine is called to generate a message from the routing 741 * socket indicating that a redirect has occurred, a routing lookup 742 * has failed, or that a protocol has detected timeouts to a particular 743 * destination. 744 */ 745 void 746 rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error) 747 { 748 struct rt_msghdr rtm; 749 struct mbuf *m; 750 const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; 751 752 if (route_cb.any_count == 0) 753 return; 754 memset(&rtm, 0, sizeof(rtm)); 755 rtm.rtm_flags = RTF_DONE | flags; 756 rtm.rtm_errno = error; 757 m = rt_msg1(type, rtinfo, &rtm, sizeof(rtm)); 758 if (m == NULL) 759 return; 760 mtod(m, struct rt_msghdr *)->rtm_addrs = rtinfo->rti_addrs; 761 route_enqueue(m, sa ? sa->sa_family : 0); 762 } 763 764 /* 765 * This routine is called to generate a message from the routing 766 * socket indicating that the status of a network interface has changed. 767 */ 768 void 769 rt_ifmsg(struct ifnet *ifp) 770 { 771 struct if_msghdr ifm; 772 struct mbuf *m; 773 struct rt_addrinfo info; 774 775 if (route_cb.any_count == 0) 776 return; 777 (void)memset(&info, 0, sizeof(info)); 778 (void)memset(&ifm, 0, sizeof(ifm)); 779 ifm.ifm_index = ifp->if_index; 780 ifm.ifm_flags = ifp->if_flags; 781 ifm.ifm_data = ifp->if_data; 782 ifm.ifm_addrs = 0; 783 m = rt_msg1(RTM_IFINFO, &info, &ifm, sizeof(ifm)); 784 if (m == NULL) 785 return; 786 route_enqueue(m, 0); 787 #ifdef COMPAT_14 788 compat_14_rt_ifmsg(ifp, &ifm); 789 #endif 790 #ifdef COMPAT_50 791 compat_50_rt_ifmsg(ifp, &ifm); 792 #endif 793 } 794 795 796 /* 797 * This is called to generate messages from the routing socket 798 * indicating a network interface has had addresses associated with it. 799 * if we ever reverse the logic and replace messages TO the routing 800 * socket indicate a request to configure interfaces, then it will 801 * be unnecessary as the routing socket will automatically generate 802 * copies of it. 803 */ 804 void 805 rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt) 806 { 807 #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass)) 808 struct rt_addrinfo info; 809 const struct sockaddr *sa; 810 int pass; 811 struct mbuf *m; 812 struct ifnet *ifp = ifa->ifa_ifp; 813 struct rt_msghdr rtm; 814 struct ifa_msghdr ifam; 815 int ncmd; 816 817 if (route_cb.any_count == 0) 818 return; 819 for (pass = 1; pass < 3; pass++) { 820 memset(&info, 0, sizeof(info)); 821 switch (cmdpass(cmd, pass)) { 822 case cmdpass(RTM_ADD, 1): 823 case cmdpass(RTM_CHANGE, 1): 824 case cmdpass(RTM_DELETE, 2): 825 if (cmd == RTM_ADD) 826 ncmd = RTM_NEWADDR; 827 else 828 ncmd = RTM_DELADDR; 829 830 info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; 831 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 832 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 833 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 834 memset(&ifam, 0, sizeof(ifam)); 835 ifam.ifam_index = ifp->if_index; 836 ifam.ifam_metric = ifa->ifa_metric; 837 ifam.ifam_flags = ifa->ifa_flags; 838 m = rt_msg1(ncmd, &info, &ifam, sizeof(ifam)); 839 if (m == NULL) 840 continue; 841 mtod(m, struct ifa_msghdr *)->ifam_addrs = 842 info.rti_addrs; 843 break; 844 case cmdpass(RTM_ADD, 2): 845 case cmdpass(RTM_CHANGE, 2): 846 case cmdpass(RTM_DELETE, 1): 847 if (rt == NULL) 848 continue; 849 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 850 info.rti_info[RTAX_DST] = sa = rt_getkey(rt); 851 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 852 memset(&rtm, 0, sizeof(rtm)); 853 rtm.rtm_index = ifp->if_index; 854 rtm.rtm_flags |= rt->rt_flags; 855 rtm.rtm_errno = error; 856 m = rt_msg1(cmd, &info, &rtm, sizeof(rtm)); 857 if (m == NULL) 858 continue; 859 mtod(m, struct rt_msghdr *)->rtm_addrs = info.rti_addrs; 860 break; 861 default: 862 continue; 863 } 864 #ifdef DIAGNOSTIC 865 if (m == NULL) 866 panic("%s: called with wrong command", __func__); 867 #endif 868 route_enqueue(m, sa ? sa->sa_family : 0); 869 } 870 #undef cmdpass 871 } 872 873 static struct mbuf * 874 rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, 875 struct rt_addrinfo *info) 876 { 877 struct if_announcemsghdr ifan; 878 879 memset(info, 0, sizeof(*info)); 880 memset(&ifan, 0, sizeof(ifan)); 881 ifan.ifan_index = ifp->if_index; 882 strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); 883 ifan.ifan_what = what; 884 return rt_msg1(type, info, &ifan, sizeof(ifan)); 885 } 886 887 /* 888 * This is called to generate routing socket messages indicating 889 * network interface arrival and departure. 890 */ 891 void 892 rt_ifannouncemsg(struct ifnet *ifp, int what) 893 { 894 struct mbuf *m; 895 struct rt_addrinfo info; 896 897 if (route_cb.any_count == 0) 898 return; 899 m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info); 900 if (m == NULL) 901 return; 902 route_enqueue(m, 0); 903 } 904 905 /* 906 * This is called to generate routing socket messages indicating 907 * IEEE80211 wireless events. 908 * XXX we piggyback on the RTM_IFANNOUNCE msg format in a clumsy way. 909 */ 910 void 911 rt_ieee80211msg(struct ifnet *ifp, int what, void *data, size_t data_len) 912 { 913 struct mbuf *m; 914 struct rt_addrinfo info; 915 916 if (route_cb.any_count == 0) 917 return; 918 m = rt_makeifannouncemsg(ifp, RTM_IEEE80211, what, &info); 919 if (m == NULL) 920 return; 921 /* 922 * Append the ieee80211 data. Try to stick it in the 923 * mbuf containing the ifannounce msg; otherwise allocate 924 * a new mbuf and append. 925 * 926 * NB: we assume m is a single mbuf. 927 */ 928 if (data_len > M_TRAILINGSPACE(m)) { 929 struct mbuf *n = m_get(M_NOWAIT, MT_DATA); 930 if (n == NULL) { 931 m_freem(m); 932 return; 933 } 934 (void)memcpy(mtod(n, void *), data, data_len); 935 n->m_len = data_len; 936 m->m_next = n; 937 } else if (data_len > 0) { 938 (void)memcpy(mtod(m, uint8_t *) + m->m_len, data, data_len); 939 m->m_len += data_len; 940 } 941 if (m->m_flags & M_PKTHDR) 942 m->m_pkthdr.len += data_len; 943 mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len; 944 route_enqueue(m, 0); 945 } 946 947 /* 948 * This is used in dumping the kernel table via sysctl(). 949 */ 950 static int 951 sysctl_dumpentry(struct rtentry *rt, void *v) 952 { 953 struct rt_walkarg *w = v; 954 int error = 0, size; 955 struct rt_addrinfo info; 956 957 if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) 958 return 0; 959 memset(&info, 0, sizeof(info)); 960 info.rti_info[RTAX_DST] = rt_getkey(rt); 961 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 962 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 963 if (rt->rt_ifp) { 964 const struct ifaddr *rtifa; 965 info.rti_info[RTAX_IFP] = rt->rt_ifp->if_dl->ifa_addr; 966 /* rtifa used to be simply rt->rt_ifa. If rt->rt_ifa != NULL, 967 * then rt_get_ifa() != NULL. So this ought to still be safe. 968 * --dyoung 969 */ 970 rtifa = rt_get_ifa(rt); 971 info.rti_info[RTAX_IFA] = rtifa->ifa_addr; 972 if (rt->rt_ifp->if_flags & IFF_POINTOPOINT) 973 info.rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; 974 } 975 if ((error = rt_msg2(RTM_GET, &info, 0, w, &size))) 976 return error; 977 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 978 struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem; 979 980 rtm->rtm_flags = rt->rt_flags; 981 rtm->rtm_use = rt->rt_use; 982 cvtmetrics(&rtm->rtm_rmx, &rt->rt_rmx); 983 KASSERT(rt->rt_ifp != NULL); 984 rtm->rtm_index = rt->rt_ifp->if_index; 985 rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; 986 rtm->rtm_addrs = info.rti_addrs; 987 if ((error = copyout(rtm, w->w_where, size)) != 0) 988 w->w_where = NULL; 989 else 990 w->w_where = (char *)w->w_where + size; 991 } 992 return error; 993 } 994 995 static int 996 sysctl_iflist(int af, struct rt_walkarg *w, int type) 997 { 998 struct ifnet *ifp; 999 struct ifaddr *ifa; 1000 struct rt_addrinfo info; 1001 int len, error = 0; 1002 1003 memset(&info, 0, sizeof(info)); 1004 IFNET_FOREACH(ifp) { 1005 if (w->w_arg && w->w_arg != ifp->if_index) 1006 continue; 1007 if (IFADDR_EMPTY(ifp)) 1008 continue; 1009 info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; 1010 switch (type) { 1011 case NET_RT_IFLIST: 1012 error = rt_msg2(RTM_IFINFO, &info, NULL, w, &len); 1013 break; 1014 #ifdef COMPAT_14 1015 case NET_RT_OOIFLIST: 1016 error = rt_msg2(RTM_OOIFINFO, &info, NULL, w, &len); 1017 break; 1018 #endif 1019 #ifdef COMPAT_50 1020 case NET_RT_OIFLIST: 1021 error = rt_msg2(RTM_OIFINFO, &info, NULL, w, &len); 1022 break; 1023 #endif 1024 default: 1025 panic("sysctl_iflist(1)"); 1026 } 1027 if (error) 1028 return error; 1029 info.rti_info[RTAX_IFP] = NULL; 1030 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1031 switch (type) { 1032 case NET_RT_IFLIST: { 1033 struct if_msghdr *ifm; 1034 1035 ifm = (struct if_msghdr *)w->w_tmem; 1036 ifm->ifm_index = ifp->if_index; 1037 ifm->ifm_flags = ifp->if_flags; 1038 ifm->ifm_data = ifp->if_data; 1039 ifm->ifm_addrs = info.rti_addrs; 1040 error = copyout(ifm, w->w_where, len); 1041 if (error) 1042 return error; 1043 w->w_where = (char *)w->w_where + len; 1044 break; 1045 } 1046 1047 #ifdef COMPAT_14 1048 case NET_RT_OOIFLIST: 1049 error = compat_14_iflist(ifp, w, &info, len); 1050 if (error) 1051 return error; 1052 break; 1053 #endif 1054 #ifdef COMPAT_50 1055 case NET_RT_OIFLIST: 1056 error = compat_50_iflist(ifp, w, &info, len); 1057 if (error) 1058 return error; 1059 break; 1060 #endif 1061 default: 1062 panic("sysctl_iflist(2)"); 1063 } 1064 } 1065 IFADDR_FOREACH(ifa, ifp) { 1066 if (af && af != ifa->ifa_addr->sa_family) 1067 continue; 1068 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1069 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1070 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1071 if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len))) 1072 return error; 1073 if (w->w_where && w->w_tmem && w->w_needed <= 0) { 1074 struct ifa_msghdr *ifam; 1075 1076 ifam = (struct ifa_msghdr *)w->w_tmem; 1077 ifam->ifam_index = ifa->ifa_ifp->if_index; 1078 ifam->ifam_flags = ifa->ifa_flags; 1079 ifam->ifam_metric = ifa->ifa_metric; 1080 ifam->ifam_addrs = info.rti_addrs; 1081 error = copyout(w->w_tmem, w->w_where, len); 1082 if (error) 1083 return error; 1084 w->w_where = (char *)w->w_where + len; 1085 } 1086 } 1087 info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = 1088 info.rti_info[RTAX_BRD] = NULL; 1089 } 1090 return 0; 1091 } 1092 1093 static int 1094 sysctl_rtable(SYSCTLFN_ARGS) 1095 { 1096 void *where = oldp; 1097 size_t *given = oldlenp; 1098 const void *new = newp; 1099 int i, s, error = EINVAL; 1100 u_char af; 1101 struct rt_walkarg w; 1102 1103 if (namelen == 1 && name[0] == CTL_QUERY) 1104 return sysctl_query(SYSCTLFN_CALL(rnode)); 1105 1106 if (new) 1107 return EPERM; 1108 if (namelen != 3) 1109 return EINVAL; 1110 af = name[0]; 1111 w.w_tmemneeded = 0; 1112 w.w_tmemsize = 0; 1113 w.w_tmem = NULL; 1114 again: 1115 /* we may return here if a later [re]alloc of the t_mem buffer fails */ 1116 if (w.w_tmemneeded) { 1117 w.w_tmem = malloc(w.w_tmemneeded, M_RTABLE, M_WAITOK); 1118 w.w_tmemsize = w.w_tmemneeded; 1119 w.w_tmemneeded = 0; 1120 } 1121 w.w_op = name[1]; 1122 w.w_arg = name[2]; 1123 w.w_given = *given; 1124 w.w_needed = 0 - w.w_given; 1125 w.w_where = where; 1126 1127 s = splsoftnet(); 1128 switch (w.w_op) { 1129 1130 case NET_RT_DUMP: 1131 case NET_RT_FLAGS: 1132 for (i = 1; i <= AF_MAX; i++) 1133 if ((af == 0 || af == i) && 1134 (error = rt_walktree(i, sysctl_dumpentry, &w))) 1135 break; 1136 break; 1137 1138 #ifdef COMPAT_14 1139 case NET_RT_OOIFLIST: 1140 error = sysctl_iflist(af, &w, w.w_op); 1141 break; 1142 #endif 1143 #ifdef COMPAT_50 1144 case NET_RT_OIFLIST: 1145 error = sysctl_iflist(af, &w, w.w_op); 1146 break; 1147 #endif 1148 1149 case NET_RT_IFLIST: 1150 error = sysctl_iflist(af, &w, w.w_op); 1151 } 1152 splx(s); 1153 1154 /* check to see if we couldn't allocate memory with NOWAIT */ 1155 if (error == ENOBUFS && w.w_tmem == 0 && w.w_tmemneeded) 1156 goto again; 1157 1158 if (w.w_tmem) 1159 free(w.w_tmem, M_RTABLE); 1160 w.w_needed += w.w_given; 1161 if (where) { 1162 *given = (char *)w.w_where - (char *)where; 1163 if (*given < w.w_needed) 1164 return ENOMEM; 1165 } else { 1166 *given = (11 * w.w_needed) / 10; 1167 } 1168 return error; 1169 } 1170 1171 /* 1172 * Routing message software interrupt routine 1173 */ 1174 static void 1175 route_intr(void *cookie) 1176 { 1177 struct sockproto proto = { .sp_family = PF_ROUTE, }; 1178 struct mbuf *m; 1179 int s; 1180 1181 mutex_enter(softnet_lock); 1182 KERNEL_LOCK(1, NULL); 1183 while (!IF_IS_EMPTY(&route_intrq)) { 1184 s = splnet(); 1185 IF_DEQUEUE(&route_intrq, m); 1186 splx(s); 1187 if (m == NULL) 1188 break; 1189 proto.sp_protocol = M_GETCTX(m, uintptr_t); 1190 raw_input(m, &proto, &route_src, &route_dst); 1191 } 1192 KERNEL_UNLOCK_ONE(NULL); 1193 mutex_exit(softnet_lock); 1194 } 1195 1196 /* 1197 * Enqueue a message to the software interrupt routine. 1198 */ 1199 void 1200 route_enqueue(struct mbuf *m, int family) 1201 { 1202 int s, wasempty; 1203 1204 s = splnet(); 1205 if (IF_QFULL(&route_intrq)) { 1206 IF_DROP(&route_intrq); 1207 m_freem(m); 1208 } else { 1209 wasempty = IF_IS_EMPTY(&route_intrq); 1210 M_SETCTX(m, (uintptr_t)family); 1211 IF_ENQUEUE(&route_intrq, m); 1212 if (wasempty) 1213 softint_schedule(route_sih); 1214 } 1215 splx(s); 1216 } 1217 1218 void 1219 rt_init(void) 1220 { 1221 1222 sysctl_net_route_setup(NULL); 1223 route_intrq.ifq_maxlen = route_maxqlen; 1224 route_sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, 1225 route_intr, NULL); 1226 } 1227 1228 /* 1229 * Definitions of protocols supported in the ROUTE domain. 1230 */ 1231 PR_WRAP_USRREQ(route_usrreq) 1232 #define route_usrreq route_usrreq_wrapper 1233 1234 const struct protosw routesw[] = { 1235 { 1236 .pr_type = SOCK_RAW, 1237 .pr_domain = &routedomain, 1238 .pr_flags = PR_ATOMIC|PR_ADDR, 1239 .pr_input = raw_input, 1240 .pr_output = route_output, 1241 .pr_ctlinput = raw_ctlinput, 1242 .pr_usrreq = route_usrreq, 1243 .pr_init = raw_init, 1244 }, 1245 }; 1246 1247 struct domain routedomain = { 1248 .dom_family = PF_ROUTE, 1249 .dom_name = "route", 1250 .dom_init = route_init, 1251 .dom_protosw = routesw, 1252 .dom_protoswNPROTOSW = &routesw[__arraycount(routesw)], 1253 }; 1254 1255 static void 1256 sysctl_net_route_setup(struct sysctllog **clog) 1257 { 1258 const struct sysctlnode *rnode = NULL; 1259 1260 sysctl_createv(clog, 0, NULL, NULL, 1261 CTLFLAG_PERMANENT, 1262 CTLTYPE_NODE, "net", NULL, 1263 NULL, 0, NULL, 0, 1264 CTL_NET, CTL_EOL); 1265 1266 sysctl_createv(clog, 0, NULL, &rnode, 1267 CTLFLAG_PERMANENT, 1268 CTLTYPE_NODE, "route", 1269 SYSCTL_DESCR("PF_ROUTE information"), 1270 NULL, 0, NULL, 0, 1271 CTL_NET, PF_ROUTE, CTL_EOL); 1272 sysctl_createv(clog, 0, NULL, NULL, 1273 CTLFLAG_PERMANENT, 1274 CTLTYPE_NODE, "rtable", 1275 SYSCTL_DESCR("Routing table information"), 1276 sysctl_rtable, 0, NULL, 0, 1277 CTL_NET, PF_ROUTE, 0 /* any protocol */, CTL_EOL); 1278 sysctl_createv(clog, 0, &rnode, NULL, 1279 CTLFLAG_PERMANENT, 1280 CTLTYPE_STRUCT, "stats", 1281 SYSCTL_DESCR("Routing statistics"), 1282 NULL, 0, &rtstat, sizeof(rtstat), 1283 CTL_CREATE, CTL_EOL); 1284 } 1285