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