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