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