1 /* $NetBSD: raw_ip.c,v 1.109 2009/01/19 02:27:57 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) 1982, 1986, 1988, 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 * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.109 2009/01/19 02:27:57 christos Exp $"); 65 66 #include "opt_inet.h" 67 #include "opt_compat_netbsd.h" 68 #include "opt_ipsec.h" 69 #include "opt_mrouting.h" 70 71 #include <sys/param.h> 72 #include <sys/sysctl.h> 73 #include <sys/malloc.h> 74 #include <sys/mbuf.h> 75 #include <sys/socket.h> 76 #include <sys/protosw.h> 77 #include <sys/socketvar.h> 78 #include <sys/errno.h> 79 #include <sys/systm.h> 80 #include <sys/proc.h> 81 #include <sys/kauth.h> 82 83 #include <net/if.h> 84 #include <net/route.h> 85 86 #include <netinet/in.h> 87 #include <netinet/in_systm.h> 88 #include <netinet/ip.h> 89 #include <netinet/ip_var.h> 90 #include <netinet/ip_private.h> 91 #include <netinet/ip_mroute.h> 92 #include <netinet/ip_icmp.h> 93 #include <netinet/in_pcb.h> 94 #include <netinet/in_proto.h> 95 #include <netinet/in_var.h> 96 97 #include <machine/stdarg.h> 98 99 #ifdef IPSEC 100 #include <netinet6/ipsec.h> 101 #include <netinet6/ipsec_private.h> 102 #endif /* IPSEC */ 103 104 #ifdef FAST_IPSEC 105 #include <netipsec/ipsec.h> 106 #include <netipsec/ipsec_var.h> 107 #include <netipsec/ipsec_private.h> 108 #endif /* FAST_IPSEC */ 109 110 #ifdef COMPAT_50 111 #include <compat/sys/socket.h> 112 #endif 113 114 struct inpcbtable rawcbtable; 115 116 int rip_pcbnotify(struct inpcbtable *, struct in_addr, 117 struct in_addr, int, int, void (*)(struct inpcb *, int)); 118 int rip_bind(struct inpcb *, struct mbuf *); 119 int rip_connect(struct inpcb *, struct mbuf *); 120 void rip_disconnect(struct inpcb *); 121 122 /* 123 * Nominal space allocated to a raw ip socket. 124 */ 125 #define RIPSNDQ 8192 126 #define RIPRCVQ 8192 127 128 /* 129 * Raw interface to IP protocol. 130 */ 131 132 /* 133 * Initialize raw connection block q. 134 */ 135 void 136 rip_init(void) 137 { 138 139 in_pcbinit(&rawcbtable, 1, 1); 140 } 141 142 static void 143 rip_sbappendaddr(struct inpcb *last, struct ip *ip, const struct sockaddr *sa, 144 int hlen, struct mbuf *opts, struct mbuf *n) 145 { 146 if (last->inp_flags & INP_NOHEADER) 147 m_adj(n, hlen); 148 if (last->inp_flags & INP_CONTROLOPTS 149 #ifdef SO_OTIMESTAMP 150 || last->inp_socket->so_options & SO_OTIMESTAMP 151 #endif 152 || last->inp_socket->so_options & SO_TIMESTAMP) 153 ip_savecontrol(last, &opts, ip, n); 154 if (sbappendaddr(&last->inp_socket->so_rcv, sa, n, opts) == 0) { 155 /* should notify about lost packet */ 156 m_freem(n); 157 if (opts) 158 m_freem(opts); 159 } else 160 sorwakeup(last->inp_socket); 161 } 162 163 /* 164 * Setup generic address and protocol structures 165 * for raw_input routine, then pass them along with 166 * mbuf chain. 167 */ 168 void 169 rip_input(struct mbuf *m, ...) 170 { 171 int hlen, proto; 172 struct ip *ip = mtod(m, struct ip *); 173 struct inpcb_hdr *inph; 174 struct inpcb *inp; 175 struct inpcb *last = NULL; 176 struct mbuf *n, *opts = NULL; 177 struct sockaddr_in ripsrc; 178 va_list ap; 179 180 va_start(ap, m); 181 (void)va_arg(ap, int); /* ignore value, advance ap */ 182 proto = va_arg(ap, int); 183 va_end(ap); 184 185 sockaddr_in_init(&ripsrc, &ip->ip_src, 0); 186 187 /* 188 * XXX Compatibility: programs using raw IP expect ip_len 189 * XXX to have the header length subtracted, and in host order. 190 * XXX ip_off is also expected to be host order. 191 */ 192 hlen = ip->ip_hl << 2; 193 ip->ip_len = ntohs(ip->ip_len) - hlen; 194 NTOHS(ip->ip_off); 195 196 CIRCLEQ_FOREACH(inph, &rawcbtable.inpt_queue, inph_queue) { 197 inp = (struct inpcb *)inph; 198 if (inp->inp_af != AF_INET) 199 continue; 200 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto) 201 continue; 202 if (!in_nullhost(inp->inp_laddr) && 203 !in_hosteq(inp->inp_laddr, ip->ip_dst)) 204 continue; 205 if (!in_nullhost(inp->inp_faddr) && 206 !in_hosteq(inp->inp_faddr, ip->ip_src)) 207 continue; 208 if (last == NULL) 209 ; 210 #if defined(IPSEC) || defined(FAST_IPSEC) 211 /* check AH/ESP integrity. */ 212 else if (ipsec4_in_reject_so(m, last->inp_socket)) { 213 IPSEC_STATINC(IPSEC_STAT_IN_POLVIO); 214 /* do not inject data to pcb */ 215 } 216 #endif /*IPSEC*/ 217 else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { 218 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, opts, 219 n); 220 opts = NULL; 221 } 222 last = inp; 223 } 224 #if defined(IPSEC) || defined(FAST_IPSEC) 225 /* check AH/ESP integrity. */ 226 if (last != NULL && ipsec4_in_reject_so(m, last->inp_socket)) { 227 m_freem(m); 228 IPSEC_STATINC(IPSEC_STAT_IN_POLVIO); 229 IP_STATDEC(IP_STAT_DELIVERED); 230 /* do not inject data to pcb */ 231 } else 232 #endif /*IPSEC*/ 233 if (last != NULL) 234 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, opts, m); 235 else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) { 236 uint64_t *ips; 237 238 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 239 0, 0); 240 ips = IP_STAT_GETREF(); 241 ips[IP_STAT_NOPROTO]++; 242 ips[IP_STAT_DELIVERED]--; 243 IP_STAT_PUTREF(); 244 } else 245 m_freem(m); 246 return; 247 } 248 249 int 250 rip_pcbnotify(struct inpcbtable *table, 251 struct in_addr faddr, struct in_addr laddr, int proto, int errno, 252 void (*notify)(struct inpcb *, int)) 253 { 254 struct inpcb *inp, *ninp; 255 int nmatch; 256 257 nmatch = 0; 258 for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue); 259 inp != (struct inpcb *)&table->inpt_queue; 260 inp = ninp) { 261 ninp = (struct inpcb *)inp->inp_queue.cqe_next; 262 if (inp->inp_af != AF_INET) 263 continue; 264 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto) 265 continue; 266 if (in_hosteq(inp->inp_faddr, faddr) && 267 in_hosteq(inp->inp_laddr, laddr)) { 268 (*notify)(inp, errno); 269 nmatch++; 270 } 271 } 272 273 return nmatch; 274 } 275 276 void * 277 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v) 278 { 279 struct ip *ip = v; 280 void (*notify)(struct inpcb *, int) = in_rtchange; 281 int errno; 282 283 if (sa->sa_family != AF_INET || 284 sa->sa_len != sizeof(struct sockaddr_in)) 285 return NULL; 286 if ((unsigned)cmd >= PRC_NCMDS) 287 return NULL; 288 errno = inetctlerrmap[cmd]; 289 if (PRC_IS_REDIRECT(cmd)) 290 notify = in_rtchange, ip = 0; 291 else if (cmd == PRC_HOSTDEAD) 292 ip = 0; 293 else if (errno == 0) 294 return NULL; 295 if (ip) { 296 rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr, 297 ip->ip_src, ip->ip_p, errno, notify); 298 299 /* XXX mapped address case */ 300 } else 301 in_pcbnotifyall(&rawcbtable, satocsin(sa)->sin_addr, errno, 302 notify); 303 return NULL; 304 } 305 306 /* 307 * Generate IP header and pass packet to ip_output. 308 * Tack on options user may have setup with control call. 309 */ 310 int 311 rip_output(struct mbuf *m, ...) 312 { 313 struct inpcb *inp; 314 struct ip *ip; 315 struct mbuf *opts; 316 int flags; 317 va_list ap; 318 319 va_start(ap, m); 320 inp = va_arg(ap, struct inpcb *); 321 va_end(ap); 322 323 flags = 324 (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST 325 | IP_RETURNMTU; 326 327 /* 328 * If the user handed us a complete IP packet, use it. 329 * Otherwise, allocate an mbuf for a header and fill it in. 330 */ 331 if ((inp->inp_flags & INP_HDRINCL) == 0) { 332 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { 333 m_freem(m); 334 return (EMSGSIZE); 335 } 336 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 337 if (!m) 338 return (ENOBUFS); 339 ip = mtod(m, struct ip *); 340 ip->ip_tos = 0; 341 ip->ip_off = htons(0); 342 ip->ip_p = inp->inp_ip.ip_p; 343 ip->ip_len = htons(m->m_pkthdr.len); 344 ip->ip_src = inp->inp_laddr; 345 ip->ip_dst = inp->inp_faddr; 346 ip->ip_ttl = MAXTTL; 347 opts = inp->inp_options; 348 } else { 349 if (m->m_pkthdr.len > IP_MAXPACKET) { 350 m_freem(m); 351 return (EMSGSIZE); 352 } 353 ip = mtod(m, struct ip *); 354 355 /* 356 * If the mbuf is read-only, we need to allocate 357 * a new mbuf for the header, since we need to 358 * modify the header. 359 */ 360 if (M_READONLY(m)) { 361 int hlen = ip->ip_hl << 2; 362 363 m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3); 364 if (m == NULL) 365 return (ENOMEM); /* XXX */ 366 ip = mtod(m, struct ip *); 367 } 368 369 /* XXX userland passes ip_len and ip_off in host order */ 370 if (m->m_pkthdr.len != ip->ip_len) { 371 m_freem(m); 372 return (EINVAL); 373 } 374 HTONS(ip->ip_len); 375 HTONS(ip->ip_off); 376 if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE) 377 flags |= IP_NOIPNEWID; 378 opts = NULL; 379 /* XXX prevent ip_output from overwriting header fields */ 380 flags |= IP_RAWOUTPUT; 381 IP_STATINC(IP_STAT_RAWOUT); 382 } 383 return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, 384 inp->inp_socket, &inp->inp_errormtu)); 385 } 386 387 /* 388 * Raw IP socket option processing. 389 */ 390 int 391 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt) 392 { 393 struct inpcb *inp = sotoinpcb(so); 394 int error = 0; 395 int optval; 396 397 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 398 if (op == PRCO_GETOPT) { 399 optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0; 400 error = sockopt_set(sopt, &optval, sizeof(optval)); 401 } else if (op == PRCO_SETOPT) { 402 error = sockopt_getint(sopt, &optval); 403 if (error) 404 goto out; 405 if (optval) { 406 inp->inp_flags &= ~INP_HDRINCL; 407 inp->inp_flags |= INP_NOHEADER; 408 } else 409 inp->inp_flags &= ~INP_NOHEADER; 410 } 411 goto out; 412 } else if (sopt->sopt_level != IPPROTO_IP) 413 return ip_ctloutput(op, so, sopt); 414 415 switch (op) { 416 417 case PRCO_SETOPT: 418 switch (sopt->sopt_name) { 419 case IP_HDRINCL: 420 error = sockopt_getint(sopt, &optval); 421 if (error) 422 break; 423 if (optval) 424 inp->inp_flags |= INP_HDRINCL; 425 else 426 inp->inp_flags &= ~INP_HDRINCL; 427 break; 428 429 #ifdef MROUTING 430 case MRT_INIT: 431 case MRT_DONE: 432 case MRT_ADD_VIF: 433 case MRT_DEL_VIF: 434 case MRT_ADD_MFC: 435 case MRT_DEL_MFC: 436 case MRT_ASSERT: 437 case MRT_API_CONFIG: 438 case MRT_ADD_BW_UPCALL: 439 case MRT_DEL_BW_UPCALL: 440 error = ip_mrouter_set(so, sopt); 441 break; 442 #endif 443 444 default: 445 error = ip_ctloutput(op, so, sopt); 446 break; 447 } 448 break; 449 450 case PRCO_GETOPT: 451 switch (sopt->sopt_name) { 452 case IP_HDRINCL: 453 optval = inp->inp_flags & INP_HDRINCL; 454 error = sockopt_set(sopt, &optval, sizeof(optval)); 455 break; 456 457 #ifdef MROUTING 458 case MRT_VERSION: 459 case MRT_ASSERT: 460 case MRT_API_SUPPORT: 461 case MRT_API_CONFIG: 462 error = ip_mrouter_get(so, sopt); 463 break; 464 #endif 465 466 default: 467 error = ip_ctloutput(op, so, sopt); 468 break; 469 } 470 break; 471 } 472 out: 473 return error; 474 } 475 476 int 477 rip_bind(struct inpcb *inp, struct mbuf *nam) 478 { 479 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 480 481 if (nam->m_len != sizeof(*addr)) 482 return (EINVAL); 483 if (TAILQ_FIRST(&ifnet) == 0) 484 return (EADDRNOTAVAIL); 485 if (addr->sin_family != AF_INET && 486 addr->sin_family != AF_IMPLINK) 487 return (EAFNOSUPPORT); 488 if (!in_nullhost(addr->sin_addr) && 489 ifa_ifwithaddr(sintosa(addr)) == 0) 490 return (EADDRNOTAVAIL); 491 inp->inp_laddr = addr->sin_addr; 492 return (0); 493 } 494 495 int 496 rip_connect(struct inpcb *inp, struct mbuf *nam) 497 { 498 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 499 500 if (nam->m_len != sizeof(*addr)) 501 return (EINVAL); 502 if (TAILQ_FIRST(&ifnet) == 0) 503 return (EADDRNOTAVAIL); 504 if (addr->sin_family != AF_INET && 505 addr->sin_family != AF_IMPLINK) 506 return (EAFNOSUPPORT); 507 inp->inp_faddr = addr->sin_addr; 508 return (0); 509 } 510 511 void 512 rip_disconnect(struct inpcb *inp) 513 { 514 515 inp->inp_faddr = zeroin_addr; 516 } 517 518 u_long rip_sendspace = RIPSNDQ; 519 u_long rip_recvspace = RIPRCVQ; 520 521 /*ARGSUSED*/ 522 int 523 rip_usrreq(struct socket *so, int req, 524 struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l) 525 { 526 struct inpcb *inp; 527 int s; 528 int error = 0; 529 #ifdef MROUTING 530 extern struct socket *ip_mrouter; 531 #endif 532 533 if (req == PRU_CONTROL) 534 return (in_control(so, (long)m, (void *)nam, 535 (struct ifnet *)control, l)); 536 537 s = splsoftnet(); 538 539 if (req == PRU_PURGEIF) { 540 mutex_enter(softnet_lock); 541 in_pcbpurgeif0(&rawcbtable, (struct ifnet *)control); 542 in_purgeif((struct ifnet *)control); 543 in_pcbpurgeif(&rawcbtable, (struct ifnet *)control); 544 mutex_exit(softnet_lock); 545 splx(s); 546 return (0); 547 } 548 549 inp = sotoinpcb(so); 550 #ifdef DIAGNOSTIC 551 if (req != PRU_SEND && req != PRU_SENDOOB && control) 552 panic("rip_usrreq: unexpected control mbuf"); 553 #endif 554 if (inp == 0 && req != PRU_ATTACH) { 555 error = EINVAL; 556 goto release; 557 } 558 559 switch (req) { 560 561 case PRU_ATTACH: 562 sosetlock(so); 563 if (inp != 0) { 564 error = EISCONN; 565 break; 566 } 567 568 if (l == NULL) { 569 error = EACCES; 570 break; 571 } 572 573 /* XXX: raw socket permissions are checked in socreate() */ 574 575 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 576 error = soreserve(so, rip_sendspace, rip_recvspace); 577 if (error) 578 break; 579 } 580 error = in_pcballoc(so, &rawcbtable); 581 if (error) 582 break; 583 inp = sotoinpcb(so); 584 inp->inp_ip.ip_p = (long)nam; 585 break; 586 587 case PRU_DETACH: 588 #ifdef MROUTING 589 if (so == ip_mrouter) 590 ip_mrouter_done(); 591 #endif 592 in_pcbdetach(inp); 593 break; 594 595 case PRU_BIND: 596 error = rip_bind(inp, nam); 597 break; 598 599 case PRU_LISTEN: 600 error = EOPNOTSUPP; 601 break; 602 603 case PRU_CONNECT: 604 error = rip_connect(inp, nam); 605 if (error) 606 break; 607 soisconnected(so); 608 break; 609 610 case PRU_CONNECT2: 611 error = EOPNOTSUPP; 612 break; 613 614 case PRU_DISCONNECT: 615 soisdisconnected(so); 616 rip_disconnect(inp); 617 break; 618 619 /* 620 * Mark the connection as being incapable of further input. 621 */ 622 case PRU_SHUTDOWN: 623 socantsendmore(so); 624 break; 625 626 case PRU_RCVD: 627 error = EOPNOTSUPP; 628 break; 629 630 /* 631 * Ship a packet out. The appropriate raw output 632 * routine handles any massaging necessary. 633 */ 634 case PRU_SEND: 635 if (control && control->m_len) { 636 m_freem(control); 637 m_freem(m); 638 error = EINVAL; 639 break; 640 } 641 { 642 if (nam) { 643 if ((so->so_state & SS_ISCONNECTED) != 0) { 644 error = EISCONN; 645 goto die; 646 } 647 error = rip_connect(inp, nam); 648 if (error) { 649 die: 650 m_freem(m); 651 break; 652 } 653 } else { 654 if ((so->so_state & SS_ISCONNECTED) == 0) { 655 error = ENOTCONN; 656 goto die; 657 } 658 } 659 error = rip_output(m, inp); 660 if (nam) 661 rip_disconnect(inp); 662 } 663 break; 664 665 case PRU_SENSE: 666 /* 667 * stat: don't bother with a blocksize. 668 */ 669 splx(s); 670 return (0); 671 672 case PRU_RCVOOB: 673 error = EOPNOTSUPP; 674 break; 675 676 case PRU_SENDOOB: 677 m_freem(control); 678 m_freem(m); 679 error = EOPNOTSUPP; 680 break; 681 682 case PRU_SOCKADDR: 683 in_setsockaddr(inp, nam); 684 break; 685 686 case PRU_PEERADDR: 687 in_setpeeraddr(inp, nam); 688 break; 689 690 default: 691 panic("rip_usrreq"); 692 } 693 694 release: 695 splx(s); 696 return (error); 697 } 698 699 SYSCTL_SETUP(sysctl_net_inet_raw_setup, "sysctl net.inet.raw subtree setup") 700 { 701 702 sysctl_createv(clog, 0, NULL, NULL, 703 CTLFLAG_PERMANENT, 704 CTLTYPE_NODE, "net", NULL, 705 NULL, 0, NULL, 0, 706 CTL_NET, CTL_EOL); 707 sysctl_createv(clog, 0, NULL, NULL, 708 CTLFLAG_PERMANENT, 709 CTLTYPE_NODE, "inet", NULL, 710 NULL, 0, NULL, 0, 711 CTL_NET, PF_INET, CTL_EOL); 712 sysctl_createv(clog, 0, NULL, NULL, 713 CTLFLAG_PERMANENT, 714 CTLTYPE_NODE, "raw", 715 SYSCTL_DESCR("Raw IPv4 settings"), 716 NULL, 0, NULL, 0, 717 CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL); 718 719 sysctl_createv(clog, 0, NULL, NULL, 720 CTLFLAG_PERMANENT, 721 CTLTYPE_STRUCT, "pcblist", 722 SYSCTL_DESCR("Raw IPv4 control block list"), 723 sysctl_inpcblist, 0, &rawcbtable, 0, 724 CTL_NET, PF_INET, IPPROTO_RAW, 725 CTL_CREATE, CTL_EOL); 726 } 727