|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1982, 1986, 1988, 1993
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
55: */
56:
57: #include <sys/param.h>
58: #include <sys/systm.h>
59: #include <sys/kernel.h>
60: #include <sys/malloc.h>
61: #include <sys/mbuf.h>
62: #include <sys/proc.h>
63: #include <sys/protosw.h>
64: #include <sys/socket.h>
65: #include <sys/socketvar.h>
66: #include <sys/sysctl.h>
67:
68: #if ISFB31
69: #include <vm/vm_zone.h>
70: #endif
71:
72: #include <net/if.h>
73: #include <net/route.h>
74:
75: #define _IP_VHL
76: #include <netinet/in.h>
77: #include <netinet/in_systm.h>
78: #include <netinet/ip.h>
79: #include <netinet/in_pcb.h>
80: #include <netinet/in_var.h>
81: #include <netinet/ip_var.h>
82: #include <netinet/ip_mroute.h>
83:
84: #include <netinet/ip_fw.h>
85:
86: #if ISFB31
87: #include "opt_ipdn.h"
88: #endif
89:
90: #if DUMMYNET
91: #include <netinet/ip_dummynet.h>
92: #endif
93: #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
94: #undef COMPAT_IPFW
95: #define COMPAT_IPFW 1
96: #else
97: #undef COMPAT_IPFW
98: #endif
99:
100: static struct inpcbhead ripcb;
101: static struct inpcbinfo ripcbinfo;
102:
103: /*
104: * Nominal space allocated to a raw ip socket.
105: */
106: #define RIPSNDQ 8192
107: #define RIPRCVQ 8192
108:
109: /*
110: * Raw interface to IP protocol.
111: */
112:
113: /*
114: * Initialize raw connection block q.
115: */
116: void
117: rip_init()
118: {
119: LIST_INIT(&ripcb);
120: ripcbinfo.listhead = &ripcb;
121: /*
122: * XXX We don't use the hash list for raw IP, but it's easier
123: * to allocate a one entry hash list than it is to check all
124: * over the place for hashbase == NULL.
125: */
126: ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
127: ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);
128:
129: ripcbinfo.ipi_zone = (void *) zinit(sizeof(struct inpcb),
130: (4096 * sizeof(struct inpcb)),
131: 4096, "ripzone");
132:
133: }
134:
135: static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
136: /*
137: * Setup generic address and protocol structures
138: * for raw_input routine, then pass them along with
139: * mbuf chain.
140: */
141: void
142: rip_input(m, iphlen)
143: struct mbuf *m;
144: int iphlen;
145: {
146: register struct ip *ip = mtod(m, struct ip *);
147: register struct inpcb *inp;
148: struct inpcb *last = 0;
149: struct mbuf *opts = 0;
150:
151: ripsrc.sin_addr = ip->ip_src;
152: for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
153: if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p)
154: continue;
155: if (inp->inp_laddr.s_addr &&
156: inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
157: continue;
158: if (inp->inp_faddr.s_addr &&
159: inp->inp_faddr.s_addr != ip->ip_src.s_addr)
160: continue;
161: if (last) {
162: struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
163: if (n) {
164: if (last->inp_flags & INP_CONTROLOPTS ||
165: last->inp_socket->so_options & SO_TIMESTAMP)
166: ip_savecontrol(last, &opts, ip, n);
167: if (last->inp_flags & INP_STRIPHDR) {
168: n->m_len -= iphlen;
169: n->m_pkthdr.len -= iphlen;
170: n->m_data += iphlen;
171: }
172: if (sbappendaddr(&last->inp_socket->so_rcv,
173: (struct sockaddr *)&ripsrc, n,
174: opts) == 0) {
175: /* should notify about lost packet */
176: kprintf("rip_input can't append to socket\n");
177: m_freem(n);
178: if (opts)
179: m_freem(opts);
180: } else {
181: /* kprintf("rip_input calling sorwakeup\n"); */
182: sorwakeup(last->inp_socket);
183: }
184: opts = 0;
185: }
186: }
187: last = inp;
188: }
189: if (last) {
190: if (last->inp_flags & INP_CONTROLOPTS ||
191: last->inp_socket->so_options & SO_TIMESTAMP)
192: ip_savecontrol(last, &opts, ip, m);
193: if (last->inp_flags & INP_STRIPHDR) {
194: m->m_len -= iphlen;
195: m->m_pkthdr.len -= iphlen;
196: m->m_data += iphlen;
197: }
198: if (sbappendaddr(&last->inp_socket->so_rcv,
199: (struct sockaddr *)&ripsrc, m, opts) == 0) {
200: kprintf("rip_input(2) can't append to socket\n");
201: m_freem(m);
202: if (opts)
203: m_freem(opts);
204: } else {
205: /* kprintf("rip_input calling sorwakeup\n"); */
206: sorwakeup(last->inp_socket);
207: }
208: } else {
209: m_freem(m);
210: ipstat.ips_noproto++;
211: ipstat.ips_delivered--;
212: }
213: }
214:
215: /*
216: * Generate IP header and pass packet to ip_output.
217: * Tack on options user may have setup with control call.
218: */
219: int
220: rip_output(m, so, dst)
221: register struct mbuf *m;
222: struct socket *so;
223: u_long dst;
224: {
225: register struct ip *ip;
226: register struct inpcb *inp = sotoinpcb(so);
227: int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
228:
229: /*
230: * If the user handed us a complete IP packet, use it.
231: * Otherwise, allocate an mbuf for a header and fill it in.
232: */
233: if ((inp->inp_flags & INP_HDRINCL) == 0) {
234: if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
235: m_freem(m);
236: return(EMSGSIZE);
237: }
238: M_PREPEND(m, sizeof(struct ip), M_WAIT);
239: ip = mtod(m, struct ip *);
240: ip->ip_tos = 0;
241: ip->ip_off = 0;
242: ip->ip_p = inp->inp_ip_p;
243: ip->ip_len = m->m_pkthdr.len;
244: ip->ip_src = inp->inp_laddr;
245: ip->ip_dst.s_addr = dst;
246: ip->ip_ttl = MAXTTL;
247: } else {
248: if (m->m_pkthdr.len > IP_MAXPACKET) {
249: m_freem(m);
250: return(EMSGSIZE);
251: }
252: ip = mtod(m, struct ip *);
253: /* don't allow both user specified and setsockopt options,
254: and don't allow packet length sizes that will crash */
255: if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
256: && inp->inp_options)
257: || (ip->ip_len > m->m_pkthdr.len)
258: || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
259: m_freem(m);
260: return EINVAL;
261: }
262: if (ip->ip_id == 0)
263: ip->ip_id = htons(ip_id++);
264: /* XXX prevent ip_output from overwriting header fields */
265: flags |= IP_RAWOUTPUT;
266: ipstat.ips_rawout++;
267: }
268: return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
269: inp->inp_moptions));
270: }
271:
272: /*
273: * Raw IP socket option processing.
274: */
275: int
276: rip_ctloutput(so, sopt)
277: struct socket *so;
278: struct sockopt *sopt;
279: {
280: struct inpcb *inp = sotoinpcb(so);
281: int error, optval;
282:
283: if (sopt->sopt_level != IPPROTO_IP)
284: return (EINVAL);
285:
286: error = 0;
287:
288: switch (sopt->sopt_dir) {
289: case SOPT_GET:
290: switch (sopt->sopt_name) {
291: case IP_HDRINCL:
292: optval = inp->inp_flags & INP_HDRINCL;
293: error = sooptcopyout(sopt, &optval, sizeof optval);
294: break;
295:
296: case IP_STRIPHDR:
297: optval = inp->inp_flags & INP_STRIPHDR;
298: error = sooptcopyout(sopt, &optval, sizeof optval);
299: break;
300:
301: #if COMPAT_IPFW
302: case IP_FW_GET:
303: if (ip_fw_ctl_ptr == 0)
304: error = ENOPROTOOPT;
305: else
306: error = ip_fw_ctl_ptr(sopt);
307: break;
308:
309: case IP_NAT:
310: if (ip_nat_ctl_ptr == 0)
311: error = ENOPROTOOPT;
312: else
313: error = ip_nat_ctl_ptr(sopt);
314: break;
315: #if DUMMYNET
316: case IP_DUMMYNET_GET:
317: if (ip_dn_ctl_ptr == NULL)
318: error = ENOPROTOOPT ;
319: else
320: error = ip_dn_ctl_ptr(sopt);
321: break ;
322: #endif /* DUMMYNET */
323: #endif /* COMPAT_IPFW */
324:
325: case MRT_INIT:
326: case MRT_DONE:
327: case MRT_ADD_VIF:
328: case MRT_DEL_VIF:
329: case MRT_ADD_MFC:
330: case MRT_DEL_MFC:
331: case MRT_VERSION:
332: case MRT_ASSERT:
333: error = ip_mrouter_get(so, sopt);
334: break;
335:
336: default:
337: error = ip_ctloutput(so, sopt);
338: break;
339: }
340: break;
341:
342: case SOPT_SET:
343: switch (sopt->sopt_name) {
344: case IP_HDRINCL:
345: error = sooptcopyin(sopt, &optval, sizeof optval,
346: sizeof optval);
347: if (error)
348: break;
349: if (optval)
350: inp->inp_flags |= INP_HDRINCL;
351: else
352: inp->inp_flags &= ~INP_HDRINCL;
353: break;
354:
355: case IP_STRIPHDR:
356: error = sooptcopyin(sopt, &optval, sizeof optval,
357: sizeof optval);
358: if (error)
359: break;
360: if (optval)
361: inp->inp_flags |= INP_STRIPHDR;
362: else
363: inp->inp_flags &= ~INP_STRIPHDR;
364: break;
365:
366:
367: #if COMPAT_IPFW
368: case IP_FW_ADD:
369: case IP_FW_DEL:
370: case IP_FW_FLUSH:
371: case IP_FW_ZERO:
372: if (ip_fw_ctl_ptr == 0)
373: error = ENOPROTOOPT;
374: else
375: error = ip_fw_ctl_ptr(sopt);
376: break;
377:
378: case IP_NAT:
379: if (ip_nat_ctl_ptr == 0)
380: error = ENOPROTOOPT;
381: else
382: error = ip_nat_ctl_ptr(sopt);
383: break;
384: #if DUMMYNET
385: case IP_DUMMYNET_CONFIGURE:
386: case IP_DUMMYNET_DEL:
387: case IP_DUMMYNET_FLUSH:
388: if (ip_dn_ctl_ptr == NULL)
389: error = ENOPROTOOPT ;
390: else
391: error = ip_dn_ctl_ptr(sopt);
392: break ;
393: #endif
394: #endif /* COMPAT_IPFW */
395:
396: case IP_RSVP_ON:
397: error = ip_rsvp_init(so);
398: break;
399:
400: case IP_RSVP_OFF:
401: error = ip_rsvp_done();
402: break;
403:
404: /* XXX - should be combined */
405: case IP_RSVP_VIF_ON:
406: error = ip_rsvp_vif_init(so, sopt);
407: break;
408:
409: case IP_RSVP_VIF_OFF:
410: error = ip_rsvp_vif_done(so, sopt);
411: break;
412:
413: case MRT_INIT:
414: case MRT_DONE:
415: case MRT_ADD_VIF:
416: case MRT_DEL_VIF:
417: case MRT_ADD_MFC:
418: case MRT_DEL_MFC:
419: case MRT_VERSION:
420: case MRT_ASSERT:
421: error = ip_mrouter_set(so, sopt);
422: break;
423:
424: default:
425: error = ip_ctloutput(so, sopt);
426: break;
427: }
428: break;
429: }
430:
431: return (error);
432: }
433:
434: /*
435: * This function exists solely to receive the PRC_IFDOWN messages which
436: * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa,
437: * and calls in_ifadown() to remove all routes corresponding to that address.
438: * It also receives the PRC_IFUP messages from if_up() and reinstalls the
439: * interface routes.
440: */
441: void
442: rip_ctlinput(cmd, sa, vip)
443: int cmd;
444: struct sockaddr *sa;
445: void *vip;
446: {
447: struct in_ifaddr *ia;
448: struct ifnet *ifp;
449: int err;
450: int flags;
451:
452: switch (cmd) {
453: case PRC_IFDOWN:
454: for (ia = in_ifaddrhead.tqh_first; ia;
455: ia = ia->ia_link.tqe_next) {
456: if (ia->ia_ifa.ifa_addr == sa
457: && (ia->ia_flags & IFA_ROUTE)) {
458: /*
459: * in_ifscrub kills the interface route.
460: */
461: in_ifscrub(ia->ia_ifp, ia);
462: /*
463: * in_ifadown gets rid of all the rest of
464: * the routes. This is not quite the right
465: * thing to do, but at least if we are running
466: * a routing process they will come back.
467: */
468: in_ifadown(&ia->ia_ifa);
469: break;
470: }
471: }
472: break;
473:
474: case PRC_IFUP:
475: for (ia = in_ifaddrhead.tqh_first; ia;
476: ia = ia->ia_link.tqe_next) {
477: if (ia->ia_ifa.ifa_addr == sa)
478: break;
479: }
480: if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
481: return;
482: flags = RTF_UP;
483: ifp = ia->ia_ifa.ifa_ifp;
484:
485: if ((ifp->if_flags & IFF_LOOPBACK)
486: || (ifp->if_flags & IFF_POINTOPOINT))
487: flags |= RTF_HOST;
488:
489: err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
490: if (err == 0)
491: ia->ia_flags |= IFA_ROUTE;
492: break;
493: }
494: }
495:
496: static u_long rip_sendspace = RIPSNDQ;
497: static u_long rip_recvspace = RIPRCVQ;
498:
499:
500: SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, &rip_sendspace,
501: 0, "");
502: SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, &rip_recvspace,
503: 0, "");
504:
505: static int
506: rip_attach(struct socket *so, int proto, struct proc *p)
507: {
508: struct inpcb *inp;
509: int error, s;
510:
511: inp = sotoinpcb(so);
512: if (inp)
513: panic("rip_attach");
514:
515:
516: #if ISFB31
517: if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
518: return error;
519: #else
520: if ((so->so_state & SS_PRIV) == 0)
521: return (EPERM);
522: #endif
523:
524: s = splnet();
525: error = in_pcballoc(so, &ripcbinfo, p);
526: splx(s);
527: if (error)
528: return error;
529: error = soreserve(so, rip_sendspace, rip_recvspace);
530: if (error)
531: return error;
532: inp = (struct inpcb *)so->so_pcb;
533: inp->inp_ip_p = proto;
534: return 0;
535: }
536:
537: static int
538: rip_detach(struct socket *so)
539: {
540: struct inpcb *inp;
541:
542: inp = sotoinpcb(so);
543: if (inp == 0)
544: panic("rip_detach");
545: if (so == ip_mrouter)
546: ip_mrouter_done();
547: ip_rsvp_force_done(so);
548: if (so == ip_rsvpd)
549: ip_rsvp_done();
550: in_pcbdetach(inp);
551: return 0;
552: }
553:
554: static int
555: rip_abort(struct socket *so)
556: {
557: soisdisconnected(so);
558: return rip_detach(so);
559: }
560:
561: static int
562: rip_disconnect(struct socket *so)
563: {
564: if ((so->so_state & SS_ISCONNECTED) == 0)
565: return ENOTCONN;
566: return rip_abort(so);
567: }
568:
569: static int
570: rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
571: {
572: struct inpcb *inp = sotoinpcb(so);
573: struct sockaddr_in *addr = (struct sockaddr_in *)nam;
574:
575: if (nam->sa_len != sizeof(*addr))
576: return EINVAL;
577:
578: if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) &&
579: (addr->sin_family != AF_IMPLINK)) ||
580: (addr->sin_addr.s_addr &&
581: ifa_ifwithaddr((struct sockaddr *)addr) == 0))
582: return EADDRNOTAVAIL;
583: inp->inp_laddr = addr->sin_addr;
584: return 0;
585: }
586:
587: static int
588: rip_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
589: {
590: struct inpcb *inp = sotoinpcb(so);
591: struct sockaddr_in *addr = (struct sockaddr_in *)nam;
592:
593: if (nam->sa_len != sizeof(*addr))
594: return EINVAL;
595: if (TAILQ_EMPTY(&ifnet))
596: return EADDRNOTAVAIL;
597: if ((addr->sin_family != AF_INET) &&
598: (addr->sin_family != AF_IMPLINK))
599: return EAFNOSUPPORT;
600: inp->inp_faddr = addr->sin_addr;
601: soisconnected(so);
602: return 0;
603: }
604:
605: static int
606: rip_shutdown(struct socket *so)
607: {
608: socantsendmore(so);
609: return 0;
610: }
611:
612: static int
613: rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
614: struct mbuf *control, struct proc *p)
615: {
616: struct inpcb *inp = sotoinpcb(so);
617: register u_long dst;
618:
619: if (so->so_state & SS_ISCONNECTED) {
620: if (nam) {
621: m_freem(m);
622: return EISCONN;
623: }
624: dst = inp->inp_faddr.s_addr;
625: } else {
626: if (nam == NULL) {
627: m_freem(m);
628: return ENOTCONN;
629: }
630: dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
631: }
632: return rip_output(m, so, dst);
633: }
634:
635:
636: static int
637: rip_pcblist SYSCTL_HANDLER_ARGS
638: {
639: int error, i, n, s;
640: struct inpcb *inp, **inp_list;
641: inp_gen_t gencnt;
642: struct xinpgen xig;
643:
644: /*
645: * The process of preparing the TCB list is too time-consuming and
646: * resource-intensive to repeat twice on every request.
647: */
648: if (req->oldptr == 0) {
649: n = ripcbinfo.ipi_count;
650: req->oldidx = 2 * (sizeof xig)
651: + (n + n/8) * sizeof(struct xinpcb);
652: return 0;
653: }
654:
655: if (req->newptr != 0)
656: return EPERM;
657:
658: /*
659: * OK, now we're committed to doing something.
660: */
661: s = splnet();
662: gencnt = ripcbinfo.ipi_gencnt;
663: n = ripcbinfo.ipi_count;
664: splx(s);
665:
666: xig.xig_len = sizeof xig;
667: xig.xig_count = n;
668: xig.xig_gen = gencnt;
669: xig.xig_sogen = so_gencnt;
670: error = SYSCTL_OUT(req, &xig, sizeof xig);
671: if (error)
672: return error;
673:
674: inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
675: if (inp_list == 0)
676: return ENOMEM;
677:
678: s = splnet();
679: for (inp = ripcbinfo.listhead->lh_first, i = 0; inp && i < n;
680: inp = inp->inp_list.le_next) {
681: if (inp->inp_gencnt <= gencnt)
682: inp_list[i++] = inp;
683: }
684: splx(s);
685: n = i;
686:
687: error = 0;
688: for (i = 0; i < n; i++) {
689: inp = inp_list[i];
690: if (inp->inp_gencnt <= gencnt) {
691: struct xinpcb xi;
692: xi.xi_len = sizeof xi;
693: /* XXX should avoid extra copy */
694: bcopy(inp, &xi.xi_inp, sizeof *inp);
695: if (inp->inp_socket)
696: sotoxsocket(inp->inp_socket, &xi.xi_socket);
697: error = SYSCTL_OUT(req, &xi, sizeof xi);
698: }
699: }
700: if (!error) {
701: /*
702: * Give the user an updated idea of our state.
703: * If the generation differs from what we told
704: * her before, she knows that something happened
705: * while we were processing this request, and it
706: * might be necessary to retry.
707: */
708: s = splnet();
709: xig.xig_gen = ripcbinfo.ipi_gencnt;
710: xig.xig_sogen = so_gencnt;
711: xig.xig_count = ripcbinfo.ipi_count;
712: splx(s);
713: error = SYSCTL_OUT(req, &xig, sizeof xig);
714: }
715: FREE(inp_list, M_TEMP);
716: return error;
717: }
718:
719:
720: SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0,
721: rip_pcblist, "S,xinpcb", "List of active raw IP sockets");
722:
723: struct pr_usrreqs rip_usrreqs = {
724: rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,
725: pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
726: pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
727: pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
728: in_setsockaddr, sosend, soreceive, sopoll
729: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.