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