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