1 /* $NetBSD: raw_ip.c,v 1.117 2013/11/23 14:20:21 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.117 2013/11/23 14:20:21 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 #ifdef IPSEC 98 #include <netipsec/ipsec.h> 99 #include <netipsec/ipsec_var.h> 100 #include <netipsec/ipsec_private.h> 101 #endif /* 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 TAILQ_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(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(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_hdr *inph, *ninph; 251 int nmatch; 252 253 nmatch = 0; 254 TAILQ_FOREACH_SAFE(inph, &table->inpt_queue, inph_queue, ninph) { 255 struct inpcb *inp = (struct inpcb *)inph; 256 if (inp->inp_af != AF_INET) 257 continue; 258 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto) 259 continue; 260 if (in_hosteq(inp->inp_faddr, faddr) && 261 in_hosteq(inp->inp_laddr, laddr)) { 262 (*notify)(inp, errno); 263 nmatch++; 264 } 265 } 266 267 return nmatch; 268 } 269 270 void * 271 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v) 272 { 273 struct ip *ip = v; 274 void (*notify)(struct inpcb *, int) = in_rtchange; 275 int errno; 276 277 if (sa->sa_family != AF_INET || 278 sa->sa_len != sizeof(struct sockaddr_in)) 279 return NULL; 280 if ((unsigned)cmd >= PRC_NCMDS) 281 return NULL; 282 errno = inetctlerrmap[cmd]; 283 if (PRC_IS_REDIRECT(cmd)) 284 notify = in_rtchange, ip = 0; 285 else if (cmd == PRC_HOSTDEAD) 286 ip = 0; 287 else if (errno == 0) 288 return NULL; 289 if (ip) { 290 rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr, 291 ip->ip_src, ip->ip_p, errno, notify); 292 293 /* XXX mapped address case */ 294 } else 295 in_pcbnotifyall(&rawcbtable, satocsin(sa)->sin_addr, errno, 296 notify); 297 return NULL; 298 } 299 300 /* 301 * Generate IP header and pass packet to ip_output. 302 * Tack on options user may have setup with control call. 303 */ 304 int 305 rip_output(struct mbuf *m, ...) 306 { 307 struct inpcb *inp; 308 struct ip *ip; 309 struct mbuf *opts; 310 int flags; 311 va_list ap; 312 313 va_start(ap, m); 314 inp = va_arg(ap, struct inpcb *); 315 va_end(ap); 316 317 flags = 318 (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST 319 | IP_RETURNMTU; 320 321 /* 322 * If the user handed us a complete IP packet, use it. 323 * Otherwise, allocate an mbuf for a header and fill it in. 324 */ 325 if ((inp->inp_flags & INP_HDRINCL) == 0) { 326 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { 327 m_freem(m); 328 return (EMSGSIZE); 329 } 330 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 331 if (!m) 332 return (ENOBUFS); 333 ip = mtod(m, struct ip *); 334 ip->ip_tos = 0; 335 ip->ip_off = htons(0); 336 ip->ip_p = inp->inp_ip.ip_p; 337 ip->ip_len = htons(m->m_pkthdr.len); 338 ip->ip_src = inp->inp_laddr; 339 ip->ip_dst = inp->inp_faddr; 340 ip->ip_ttl = MAXTTL; 341 opts = inp->inp_options; 342 } else { 343 if (m->m_pkthdr.len > IP_MAXPACKET) { 344 m_freem(m); 345 return (EMSGSIZE); 346 } 347 ip = mtod(m, struct ip *); 348 349 /* 350 * If the mbuf is read-only, we need to allocate 351 * a new mbuf for the header, since we need to 352 * modify the header. 353 */ 354 if (M_READONLY(m)) { 355 int hlen = ip->ip_hl << 2; 356 357 m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3); 358 if (m == NULL) 359 return (ENOMEM); /* XXX */ 360 ip = mtod(m, struct ip *); 361 } 362 363 /* XXX userland passes ip_len and ip_off in host order */ 364 if (m->m_pkthdr.len != ip->ip_len) { 365 m_freem(m); 366 return (EINVAL); 367 } 368 HTONS(ip->ip_len); 369 HTONS(ip->ip_off); 370 if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE) 371 flags |= IP_NOIPNEWID; 372 opts = NULL; 373 /* XXX prevent ip_output from overwriting header fields */ 374 flags |= IP_RAWOUTPUT; 375 IP_STATINC(IP_STAT_RAWOUT); 376 } 377 return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, 378 inp->inp_socket, &inp->inp_errormtu)); 379 } 380 381 /* 382 * Raw IP socket option processing. 383 */ 384 int 385 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt) 386 { 387 struct inpcb *inp = sotoinpcb(so); 388 int error = 0; 389 int optval; 390 391 if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { 392 if (op == PRCO_GETOPT) { 393 optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0; 394 error = sockopt_set(sopt, &optval, sizeof(optval)); 395 } else if (op == PRCO_SETOPT) { 396 error = sockopt_getint(sopt, &optval); 397 if (error) 398 goto out; 399 if (optval) { 400 inp->inp_flags &= ~INP_HDRINCL; 401 inp->inp_flags |= INP_NOHEADER; 402 } else 403 inp->inp_flags &= ~INP_NOHEADER; 404 } 405 goto out; 406 } else if (sopt->sopt_level != IPPROTO_IP) 407 return ip_ctloutput(op, so, sopt); 408 409 switch (op) { 410 411 case PRCO_SETOPT: 412 switch (sopt->sopt_name) { 413 case IP_HDRINCL: 414 error = sockopt_getint(sopt, &optval); 415 if (error) 416 break; 417 if (optval) 418 inp->inp_flags |= INP_HDRINCL; 419 else 420 inp->inp_flags &= ~INP_HDRINCL; 421 break; 422 423 #ifdef MROUTING 424 case MRT_INIT: 425 case MRT_DONE: 426 case MRT_ADD_VIF: 427 case MRT_DEL_VIF: 428 case MRT_ADD_MFC: 429 case MRT_DEL_MFC: 430 case MRT_ASSERT: 431 case MRT_API_CONFIG: 432 case MRT_ADD_BW_UPCALL: 433 case MRT_DEL_BW_UPCALL: 434 error = ip_mrouter_set(so, sopt); 435 break; 436 #endif 437 438 default: 439 error = ip_ctloutput(op, so, sopt); 440 break; 441 } 442 break; 443 444 case PRCO_GETOPT: 445 switch (sopt->sopt_name) { 446 case IP_HDRINCL: 447 optval = inp->inp_flags & INP_HDRINCL; 448 error = sockopt_set(sopt, &optval, sizeof(optval)); 449 break; 450 451 #ifdef MROUTING 452 case MRT_VERSION: 453 case MRT_ASSERT: 454 case MRT_API_SUPPORT: 455 case MRT_API_CONFIG: 456 error = ip_mrouter_get(so, sopt); 457 break; 458 #endif 459 460 default: 461 error = ip_ctloutput(op, so, sopt); 462 break; 463 } 464 break; 465 } 466 out: 467 return error; 468 } 469 470 int 471 rip_bind(struct inpcb *inp, struct mbuf *nam) 472 { 473 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 474 475 if (nam->m_len != sizeof(*addr)) 476 return (EINVAL); 477 if (TAILQ_FIRST(&ifnet) == 0) 478 return (EADDRNOTAVAIL); 479 if (addr->sin_family != AF_INET) 480 return (EAFNOSUPPORT); 481 if (!in_nullhost(addr->sin_addr) && 482 ifa_ifwithaddr(sintosa(addr)) == 0) 483 return (EADDRNOTAVAIL); 484 inp->inp_laddr = addr->sin_addr; 485 return (0); 486 } 487 488 int 489 rip_connect(struct inpcb *inp, struct mbuf *nam) 490 { 491 struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); 492 493 if (nam->m_len != sizeof(*addr)) 494 return (EINVAL); 495 if (TAILQ_FIRST(&ifnet) == 0) 496 return (EADDRNOTAVAIL); 497 if (addr->sin_family != AF_INET) 498 return (EAFNOSUPPORT); 499 inp->inp_faddr = addr->sin_addr; 500 return (0); 501 } 502 503 void 504 rip_disconnect(struct inpcb *inp) 505 { 506 507 inp->inp_faddr = zeroin_addr; 508 } 509 510 u_long rip_sendspace = RIPSNDQ; 511 u_long rip_recvspace = RIPRCVQ; 512 513 /*ARGSUSED*/ 514 int 515 rip_usrreq(struct socket *so, int req, 516 struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l) 517 { 518 struct inpcb *inp; 519 int s; 520 int error = 0; 521 #ifdef MROUTING 522 extern struct socket *ip_mrouter; 523 #endif 524 525 if (req == PRU_CONTROL) 526 return in_control(so, (long)m, nam, (struct ifnet *)control, l); 527 528 s = splsoftnet(); 529 530 if (req == PRU_PURGEIF) { 531 mutex_enter(softnet_lock); 532 in_pcbpurgeif0(&rawcbtable, (struct ifnet *)control); 533 in_purgeif((struct ifnet *)control); 534 in_pcbpurgeif(&rawcbtable, (struct ifnet *)control); 535 mutex_exit(softnet_lock); 536 splx(s); 537 return (0); 538 } 539 540 inp = sotoinpcb(so); 541 #ifdef DIAGNOSTIC 542 if (req != PRU_SEND && req != PRU_SENDOOB && control) 543 panic("rip_usrreq: unexpected control mbuf"); 544 #endif 545 if (inp == NULL && req != PRU_ATTACH) { 546 error = EINVAL; 547 goto release; 548 } 549 550 switch (req) { 551 552 case PRU_ATTACH: 553 sosetlock(so); 554 if (inp != 0) { 555 error = EISCONN; 556 break; 557 } 558 559 if (l == NULL) { 560 error = EACCES; 561 break; 562 } 563 564 /* XXX: raw socket permissions are checked in socreate() */ 565 566 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 567 error = soreserve(so, rip_sendspace, rip_recvspace); 568 if (error) 569 break; 570 } 571 error = in_pcballoc(so, &rawcbtable); 572 if (error) 573 break; 574 inp = sotoinpcb(so); 575 inp->inp_ip.ip_p = (long)nam; 576 break; 577 578 case PRU_DETACH: 579 #ifdef MROUTING 580 if (so == ip_mrouter) 581 ip_mrouter_done(); 582 #endif 583 in_pcbdetach(inp); 584 break; 585 586 case PRU_BIND: 587 error = rip_bind(inp, nam); 588 break; 589 590 case PRU_LISTEN: 591 error = EOPNOTSUPP; 592 break; 593 594 case PRU_CONNECT: 595 error = rip_connect(inp, nam); 596 if (error) 597 break; 598 soisconnected(so); 599 break; 600 601 case PRU_CONNECT2: 602 error = EOPNOTSUPP; 603 break; 604 605 case PRU_DISCONNECT: 606 soisdisconnected(so); 607 rip_disconnect(inp); 608 break; 609 610 /* 611 * Mark the connection as being incapable of further input. 612 */ 613 case PRU_SHUTDOWN: 614 socantsendmore(so); 615 break; 616 617 case PRU_RCVD: 618 error = EOPNOTSUPP; 619 break; 620 621 /* 622 * Ship a packet out. The appropriate raw output 623 * routine handles any massaging necessary. 624 */ 625 case PRU_SEND: 626 if (control && control->m_len) { 627 m_freem(control); 628 m_freem(m); 629 error = EINVAL; 630 break; 631 } 632 { 633 if (nam) { 634 if ((so->so_state & SS_ISCONNECTED) != 0) { 635 error = EISCONN; 636 goto die; 637 } 638 error = rip_connect(inp, nam); 639 if (error) { 640 die: 641 m_freem(m); 642 break; 643 } 644 } else { 645 if ((so->so_state & SS_ISCONNECTED) == 0) { 646 error = ENOTCONN; 647 goto die; 648 } 649 } 650 error = rip_output(m, inp); 651 if (nam) 652 rip_disconnect(inp); 653 } 654 break; 655 656 case PRU_SENSE: 657 /* 658 * stat: don't bother with a blocksize. 659 */ 660 splx(s); 661 return (0); 662 663 case PRU_RCVOOB: 664 error = EOPNOTSUPP; 665 break; 666 667 case PRU_SENDOOB: 668 m_freem(control); 669 m_freem(m); 670 error = EOPNOTSUPP; 671 break; 672 673 case PRU_SOCKADDR: 674 in_setsockaddr(inp, nam); 675 break; 676 677 case PRU_PEERADDR: 678 in_setpeeraddr(inp, nam); 679 break; 680 681 default: 682 panic("rip_usrreq"); 683 } 684 685 release: 686 splx(s); 687 return (error); 688 } 689 690 static void 691 sysctl_net_inet_raw_setup(struct sysctllog **clog) 692 { 693 694 sysctl_createv(clog, 0, NULL, NULL, 695 CTLFLAG_PERMANENT, 696 CTLTYPE_NODE, "net", NULL, 697 NULL, 0, NULL, 0, 698 CTL_NET, CTL_EOL); 699 sysctl_createv(clog, 0, NULL, NULL, 700 CTLFLAG_PERMANENT, 701 CTLTYPE_NODE, "inet", NULL, 702 NULL, 0, NULL, 0, 703 CTL_NET, PF_INET, CTL_EOL); 704 sysctl_createv(clog, 0, NULL, NULL, 705 CTLFLAG_PERMANENT, 706 CTLTYPE_NODE, "raw", 707 SYSCTL_DESCR("Raw IPv4 settings"), 708 NULL, 0, NULL, 0, 709 CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL); 710 711 sysctl_createv(clog, 0, NULL, NULL, 712 CTLFLAG_PERMANENT, 713 CTLTYPE_STRUCT, "pcblist", 714 SYSCTL_DESCR("Raw IPv4 control block list"), 715 sysctl_inpcblist, 0, &rawcbtable, 0, 716 CTL_NET, PF_INET, IPPROTO_RAW, 717 CTL_CREATE, CTL_EOL); 718 } 719