]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/raw_ip.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet / raw_ip.c
CommitLineData
1c79356b
A
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/ip6.h>
80#include <netinet6/ip6_var.h>
81#include <netinet/in_pcb.h>
82#include <netinet/in_var.h>
83#include <netinet/ip_var.h>
84#include <netinet/ip_mroute.h>
85
86#include <netinet/ip_fw.h>
87
88#if IPSEC
89#include <netinet6/ipsec.h>
90#endif /*IPSEC*/
91
92#if ISFB31
93#include "opt_ipdn.h"
94#endif
95
96#if DUMMYNET
97#include <netinet/ip_dummynet.h>
98#endif
99#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
100#undef COMPAT_IPFW
101#define COMPAT_IPFW 1
102#else
103#undef COMPAT_IPFW
104#endif
105
106struct inpcbhead ripcb;
107struct inpcbinfo ripcbinfo;
108
109/*
110 * Nominal space allocated to a raw ip socket.
111 */
112#define RIPSNDQ 8192
113#define RIPRCVQ 8192
114
115/*
116 * Raw interface to IP protocol.
117 */
118
119/*
120 * Initialize raw connection block q.
121 */
122void
123rip_init()
124{
125 LIST_INIT(&ripcb);
126 ripcbinfo.listhead = &ripcb;
127 /*
128 * XXX We don't use the hash list for raw IP, but it's easier
129 * to allocate a one entry hash list than it is to check all
130 * over the place for hashbase == NULL.
131 */
132 ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
133 ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);
134
135 ripcbinfo.ipi_zone = (void *) zinit(sizeof(struct inpcb),
136 (4096 * sizeof(struct inpcb)),
137 4096, "ripzone");
138
139}
140
141static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
142/*
143 * Setup generic address and protocol structures
144 * for raw_input routine, then pass them along with
145 * mbuf chain.
146 */
147void
148rip_input(m, iphlen)
149 struct mbuf *m;
150 int iphlen;
151{
152 register struct ip *ip = mtod(m, struct ip *);
153 register struct inpcb *inp;
154 struct inpcb *last = 0;
155 struct mbuf *opts = 0;
1c79356b
A
156
157 ripsrc.sin_addr = ip->ip_src;
158 LIST_FOREACH(inp, &ripcb, inp_list) {
159 if ((inp->inp_vflag & INP_IPV4) == NULL)
160 continue;
161#warning do something about this
162 if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p)
163 continue;
164 if (inp->inp_laddr.s_addr &&
165 inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
166 continue;
167 if (inp->inp_faddr.s_addr &&
168 inp->inp_faddr.s_addr != ip->ip_src.s_addr)
169 continue;
170 if (last) {
171 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
172 if (n) {
173 if (last->inp_flags & INP_CONTROLOPTS ||
174 last->inp_socket->so_options & SO_TIMESTAMP)
175 ip_savecontrol(last, &opts, ip, n);
176 if (last->inp_flags & INP_STRIPHDR) {
177 n->m_len -= iphlen;
178 n->m_pkthdr.len -= iphlen;
179 n->m_data += iphlen;
180 }
181 if (sbappendaddr(&last->inp_socket->so_rcv,
182 (struct sockaddr *)&ripsrc, n,
183 opts) == 0) {
184 /* should notify about lost packet */
185 kprintf("rip_input can't append to socket\n");
186 m_freem(n);
187 if (opts)
188 m_freem(opts);
189 } else {
190 /* kprintf("rip_input calling sorwakeup\n"); */
0b4e3aa0 191 sorwakeup(last->inp_socket);
1c79356b
A
192 }
193 opts = 0;
194 }
195 }
196 last = inp;
197 }
198 if (last) {
199 if (last->inp_flags & INP_CONTROLOPTS ||
200 last->inp_socket->so_options & SO_TIMESTAMP)
201 ip_savecontrol(last, &opts, ip, m);
202 if (last->inp_flags & INP_STRIPHDR) {
203 m->m_len -= iphlen;
204 m->m_pkthdr.len -= iphlen;
205 m->m_data += iphlen;
206 }
207 if (sbappendaddr(&last->inp_socket->so_rcv,
208 (struct sockaddr *)&ripsrc, m, opts) == 0) {
209 kprintf("rip_input(2) can't append to socket\n");
210 m_freem(m);
211 if (opts)
212 m_freem(opts);
213 } else {
214 /* kprintf("rip_input calling sorwakeup\n"); */
0b4e3aa0 215 sorwakeup(last->inp_socket);
1c79356b
A
216 }
217 } else {
218 m_freem(m);
219 ipstat.ips_noproto++;
220 ipstat.ips_delivered--;
221 }
1c79356b
A
222}
223
224/*
225 * Generate IP header and pass packet to ip_output.
226 * Tack on options user may have setup with control call.
227 */
228int
229rip_output(m, so, dst)
230 register struct mbuf *m;
231 struct socket *so;
232 u_long dst;
233{
234 register struct ip *ip;
235 register struct inpcb *inp = sotoinpcb(so);
236 int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
237
238 /*
239 * If the user handed us a complete IP packet, use it.
240 * Otherwise, allocate an mbuf for a header and fill it in.
241 */
242 if ((inp->inp_flags & INP_HDRINCL) == 0) {
243 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
244 m_freem(m);
245 return(EMSGSIZE);
246 }
247 M_PREPEND(m, sizeof(struct ip), M_WAIT);
248 ip = mtod(m, struct ip *);
249 ip->ip_tos = 0;
250 ip->ip_off = 0;
251 ip->ip_p = inp->inp_ip_p;
252 ip->ip_len = m->m_pkthdr.len;
253 ip->ip_src = inp->inp_laddr;
254 ip->ip_dst.s_addr = dst;
255 ip->ip_ttl = MAXTTL;
256 } else {
257 if (m->m_pkthdr.len > IP_MAXPACKET) {
258 m_freem(m);
259 return(EMSGSIZE);
260 }
261 ip = mtod(m, struct ip *);
262 /* don't allow both user specified and setsockopt options,
263 and don't allow packet length sizes that will crash */
264 if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
265 && inp->inp_options)
266 || (ip->ip_len > m->m_pkthdr.len)
267 || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
268 m_freem(m);
269 return EINVAL;
270 }
271 if (ip->ip_id == 0)
272 ip->ip_id = htons(ip_id++);
273 /* XXX prevent ip_output from overwriting header fields */
274 flags |= IP_RAWOUTPUT;
275 ipstat.ips_rawout++;
276 }
277
278#if IPSEC
279 m->m_pkthdr.rcvif = (struct ifnet *)so; /*XXX*/
280#endif /*IPSEC*/
281
282 return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
283 inp->inp_moptions));
284}
285
286/*
287 * Raw IP socket option processing.
288 */
289int
290rip_ctloutput(so, sopt)
291 struct socket *so;
292 struct sockopt *sopt;
293{
294 struct inpcb *inp = sotoinpcb(so);
295 int error, optval;
296
297 if (sopt->sopt_level != IPPROTO_IP)
298 return (EINVAL);
299
300 error = 0;
301
302 switch (sopt->sopt_dir) {
303 case SOPT_GET:
304 switch (sopt->sopt_name) {
305 case IP_HDRINCL:
306 optval = inp->inp_flags & INP_HDRINCL;
307 error = sooptcopyout(sopt, &optval, sizeof optval);
308 break;
309
310 case IP_STRIPHDR:
311 optval = inp->inp_flags & INP_STRIPHDR;
312 error = sooptcopyout(sopt, &optval, sizeof optval);
313 break;
314
315#if COMPAT_IPFW
316 case IP_FW_GET:
317 if (ip_fw_ctl_ptr == 0)
318 error = ENOPROTOOPT;
319 else
320 error = ip_fw_ctl_ptr(sopt);
321 break;
322
323 case IP_NAT:
324 if (ip_nat_ctl_ptr == 0)
325 error = ENOPROTOOPT;
326 else
327 error = ip_nat_ctl_ptr(sopt);
328 break;
329#if DUMMYNET
330 case IP_DUMMYNET_GET:
331 if (ip_dn_ctl_ptr == NULL)
332 error = ENOPROTOOPT ;
333 else
334 error = ip_dn_ctl_ptr(sopt);
335 break ;
336#endif /* DUMMYNET */
337#endif /* COMPAT_IPFW */
338
339 case MRT_INIT:
340 case MRT_DONE:
341 case MRT_ADD_VIF:
342 case MRT_DEL_VIF:
343 case MRT_ADD_MFC:
344 case MRT_DEL_MFC:
345 case MRT_VERSION:
346 case MRT_ASSERT:
347 error = ip_mrouter_get(so, sopt);
348 break;
349
350 default:
351 error = ip_ctloutput(so, sopt);
352 break;
353 }
354 break;
355
356 case SOPT_SET:
357 switch (sopt->sopt_name) {
358 case IP_HDRINCL:
359 error = sooptcopyin(sopt, &optval, sizeof optval,
360 sizeof optval);
361 if (error)
362 break;
363 if (optval)
364 inp->inp_flags |= INP_HDRINCL;
365 else
366 inp->inp_flags &= ~INP_HDRINCL;
367 break;
368
369 case IP_STRIPHDR:
370 error = sooptcopyin(sopt, &optval, sizeof optval,
371 sizeof optval);
372 if (error)
373 break;
374 if (optval)
375 inp->inp_flags |= INP_STRIPHDR;
376 else
377 inp->inp_flags &= ~INP_STRIPHDR;
378 break;
379
380
381#if COMPAT_IPFW
382 case IP_FW_ADD:
383 case IP_FW_DEL:
384 case IP_FW_FLUSH:
385 case IP_FW_ZERO:
386 if (ip_fw_ctl_ptr == 0)
387 error = ENOPROTOOPT;
388 else
389 error = ip_fw_ctl_ptr(sopt);
390 break;
391
392 case IP_NAT:
393 if (ip_nat_ctl_ptr == 0)
394 error = ENOPROTOOPT;
395 else
396 error = ip_nat_ctl_ptr(sopt);
397 break;
398#if DUMMYNET
399 case IP_DUMMYNET_CONFIGURE:
400 case IP_DUMMYNET_DEL:
401 case IP_DUMMYNET_FLUSH:
402 if (ip_dn_ctl_ptr == NULL)
403 error = ENOPROTOOPT ;
404 else
405 error = ip_dn_ctl_ptr(sopt);
406 break ;
407#endif
408#endif /* COMPAT_IPFW */
409
410 case IP_RSVP_ON:
411 error = ip_rsvp_init(so);
412 break;
413
414 case IP_RSVP_OFF:
415 error = ip_rsvp_done();
416 break;
417
418 /* XXX - should be combined */
419 case IP_RSVP_VIF_ON:
420 error = ip_rsvp_vif_init(so, sopt);
421 break;
422
423 case IP_RSVP_VIF_OFF:
424 error = ip_rsvp_vif_done(so, sopt);
425 break;
426
427 case MRT_INIT:
428 case MRT_DONE:
429 case MRT_ADD_VIF:
430 case MRT_DEL_VIF:
431 case MRT_ADD_MFC:
432 case MRT_DEL_MFC:
433 case MRT_VERSION:
434 case MRT_ASSERT:
435 error = ip_mrouter_set(so, sopt);
436 break;
437
438 default:
439 error = ip_ctloutput(so, sopt);
440 break;
441 }
442 break;
443 }
444
445 return (error);
446}
447
448/*
449 * This function exists solely to receive the PRC_IFDOWN messages which
450 * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa,
451 * and calls in_ifadown() to remove all routes corresponding to that address.
452 * It also receives the PRC_IFUP messages from if_up() and reinstalls the
453 * interface routes.
454 */
455void
456rip_ctlinput(cmd, sa, vip)
457 int cmd;
458 struct sockaddr *sa;
459 void *vip;
460{
461 struct in_ifaddr *ia;
462 struct ifnet *ifp;
463 int err;
464 int flags;
465
466 switch (cmd) {
467 case PRC_IFDOWN:
468 for (ia = in_ifaddrhead.tqh_first; ia;
469 ia = ia->ia_link.tqe_next) {
470 if (ia->ia_ifa.ifa_addr == sa
471 && (ia->ia_flags & IFA_ROUTE)) {
472 /*
473 * in_ifscrub kills the interface route.
474 */
475 in_ifscrub(ia->ia_ifp, ia);
476 /*
477 * in_ifadown gets rid of all the rest of
478 * the routes. This is not quite the right
479 * thing to do, but at least if we are running
480 * a routing process they will come back.
481 */
482 in_ifadown(&ia->ia_ifa);
483 break;
484 }
485 }
486 break;
487
488 case PRC_IFUP:
489 for (ia = in_ifaddrhead.tqh_first; ia;
490 ia = ia->ia_link.tqe_next) {
491 if (ia->ia_ifa.ifa_addr == sa)
492 break;
493 }
494 if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
495 return;
496 flags = RTF_UP;
497 ifp = ia->ia_ifa.ifa_ifp;
498
499 if ((ifp->if_flags & IFF_LOOPBACK)
500 || (ifp->if_flags & IFF_POINTOPOINT))
501 flags |= RTF_HOST;
502
503 err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
504 if (err == 0)
505 ia->ia_flags |= IFA_ROUTE;
506 break;
507 }
508}
509
510u_long rip_sendspace = RIPSNDQ;
511u_long rip_recvspace = RIPRCVQ;
512
513SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW, &rip_sendspace,
514 0, "");
515SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW, &rip_recvspace,
516 0, "");
517
518static int
519rip_attach(struct socket *so, int proto, struct proc *p)
520{
521 struct inpcb *inp;
522 int error, s;
523
524 inp = sotoinpcb(so);
525 if (inp)
526 panic("rip_attach");
527
528
529#if ISFB31
530 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
531 return error;
532#else
533 if ((so->so_state & SS_PRIV) == 0)
534 return (EPERM);
535#endif
536
537 s = splnet();
538 error = in_pcballoc(so, &ripcbinfo, p);
539 splx(s);
540 if (error)
541 return error;
542 error = soreserve(so, rip_sendspace, rip_recvspace);
543 if (error)
544 return error;
545 inp = (struct inpcb *)so->so_pcb;
546 inp->inp_vflag |= INP_IPV4;
547 inp->inp_ip_p = proto;
548#if IPSEC
549 error = ipsec_init_policy(so, &inp->inp_sp);
550 if (error != 0) {
551 in_pcbdetach(inp);
552 return error;
553 }
554#endif /*IPSEC*/
555
556 return 0;
557}
558
559static int
560rip_detach(struct socket *so)
561{
562 struct inpcb *inp;
563
564 inp = sotoinpcb(so);
565 if (inp == 0)
566 panic("rip_detach");
567 if (so == ip_mrouter)
568 ip_mrouter_done();
569 ip_rsvp_force_done(so);
570 if (so == ip_rsvpd)
571 ip_rsvp_done();
572 in_pcbdetach(inp);
573 return 0;
574}
575
576static int
577rip_abort(struct socket *so)
578{
579 soisdisconnected(so);
580 return rip_detach(so);
581}
582
583static int
584rip_disconnect(struct socket *so)
585{
586 if ((so->so_state & SS_ISCONNECTED) == 0)
587 return ENOTCONN;
588 return rip_abort(so);
589}
590
591static int
592rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
593{
594 struct inpcb *inp = sotoinpcb(so);
595 struct sockaddr_in *addr = (struct sockaddr_in *)nam;
596
597 if (nam->sa_len != sizeof(*addr))
598 return EINVAL;
599
600 if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) &&
601 (addr->sin_family != AF_IMPLINK)) ||
602 (addr->sin_addr.s_addr &&
603 ifa_ifwithaddr((struct sockaddr *)addr) == 0))
604 return EADDRNOTAVAIL;
605 inp->inp_laddr = addr->sin_addr;
606 return 0;
607}
608
609static int
610rip_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
611{
612 struct inpcb *inp = sotoinpcb(so);
613 struct sockaddr_in *addr = (struct sockaddr_in *)nam;
614
615 if (nam->sa_len != sizeof(*addr))
616 return EINVAL;
617 if (TAILQ_EMPTY(&ifnet))
618 return EADDRNOTAVAIL;
619 if ((addr->sin_family != AF_INET) &&
620 (addr->sin_family != AF_IMPLINK))
621 return EAFNOSUPPORT;
622 inp->inp_faddr = addr->sin_addr;
623 soisconnected(so);
624 return 0;
625}
626
627static int
628rip_shutdown(struct socket *so)
629{
630 socantsendmore(so);
631 return 0;
632}
633
634static int
635rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
636 struct mbuf *control, struct proc *p)
637{
638 struct inpcb *inp = sotoinpcb(so);
639 register u_long dst;
640
641 if (so->so_state & SS_ISCONNECTED) {
642 if (nam) {
643 m_freem(m);
644 return EISCONN;
645 }
646 dst = inp->inp_faddr.s_addr;
647 } else {
648 if (nam == NULL) {
649 m_freem(m);
650 return ENOTCONN;
651 }
652 dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
653 }
654 return rip_output(m, so, dst);
655}
656
657
658static int
659rip_pcblist SYSCTL_HANDLER_ARGS
660{
661 int error, i, n, s;
662 struct inpcb *inp, **inp_list;
663 inp_gen_t gencnt;
664 struct xinpgen xig;
665
666 /*
667 * The process of preparing the TCB list is too time-consuming and
668 * resource-intensive to repeat twice on every request.
669 */
670 if (req->oldptr == 0) {
671 n = ripcbinfo.ipi_count;
672 req->oldidx = 2 * (sizeof xig)
673 + (n + n/8) * sizeof(struct xinpcb);
674 return 0;
675 }
676
677 if (req->newptr != 0)
678 return EPERM;
679
680 /*
681 * OK, now we're committed to doing something.
682 */
683 s = splnet();
684 gencnt = ripcbinfo.ipi_gencnt;
685 n = ripcbinfo.ipi_count;
686 splx(s);
687
688 xig.xig_len = sizeof xig;
689 xig.xig_count = n;
690 xig.xig_gen = gencnt;
691 xig.xig_sogen = so_gencnt;
692 error = SYSCTL_OUT(req, &xig, sizeof xig);
693 if (error)
694 return error;
0b4e3aa0
A
695 /*
696 * We are done if there is no pcb
697 */
698 if (n == 0)
699 return 0;
1c79356b
A
700
701 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
702 if (inp_list == 0)
703 return ENOMEM;
704
705 s = splnet();
706 for (inp = ripcbinfo.listhead->lh_first, i = 0; inp && i < n;
707 inp = inp->inp_list.le_next) {
708 if (inp->inp_gencnt <= gencnt)
709 inp_list[i++] = inp;
710 }
711 splx(s);
712 n = i;
713
714 error = 0;
715 for (i = 0; i < n; i++) {
716 inp = inp_list[i];
717 if (inp->inp_gencnt <= gencnt) {
718 struct xinpcb xi;
719 xi.xi_len = sizeof xi;
720 /* XXX should avoid extra copy */
721 bcopy(inp, &xi.xi_inp, sizeof *inp);
722 if (inp->inp_socket)
723 sotoxsocket(inp->inp_socket, &xi.xi_socket);
724 error = SYSCTL_OUT(req, &xi, sizeof xi);
725 }
726 }
727 if (!error) {
728 /*
729 * Give the user an updated idea of our state.
730 * If the generation differs from what we told
731 * her before, she knows that something happened
732 * while we were processing this request, and it
733 * might be necessary to retry.
734 */
735 s = splnet();
736 xig.xig_gen = ripcbinfo.ipi_gencnt;
737 xig.xig_sogen = so_gencnt;
738 xig.xig_count = ripcbinfo.ipi_count;
739 splx(s);
740 error = SYSCTL_OUT(req, &xig, sizeof xig);
741 }
742 FREE(inp_list, M_TEMP);
743 return error;
744}
745
746
747SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0,
748 rip_pcblist, "S,xinpcb", "List of active raw IP sockets");
749
750struct pr_usrreqs rip_usrreqs = {
751 rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,
752 pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
753 pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
754 pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
755 in_setsockaddr, sosend, soreceive, sopoll
756};