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