]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/raw_ip.c
dc552d9e30ac30ffdf703082edbb0bafc1648b9c
[apple/xnu.git] / bsd / netinet / raw_ip.c
1 /*
2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. 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 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
64 * support for mandatory and extensible security protections. This notice
65 * is included in support of clause 2.2 (b) of the Apple Public License,
66 * Version 2.0.
67 */
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/kernel.h>
72 #include <sys/malloc.h>
73 #include <sys/mbuf.h>
74 #include <sys/mcache.h>
75 #include <sys/proc.h>
76 #include <sys/domain.h>
77 #include <sys/protosw.h>
78 #include <sys/socket.h>
79 #include <sys/socketvar.h>
80 #include <sys/sysctl.h>
81 #include <libkern/OSAtomic.h>
82 #include <kern/zalloc.h>
83
84 #include <pexpert/pexpert.h>
85
86 #include <net/if.h>
87 #include <net/net_api_stats.h>
88 #include <net/route.h>
89
90 #define _IP_VHL
91 #include <netinet/in.h>
92 #include <netinet/in_systm.h>
93 #include <netinet/in_tclass.h>
94 #include <netinet/ip.h>
95 #include <netinet/in_pcb.h>
96 #include <netinet/in_var.h>
97 #include <netinet/ip_var.h>
98
99 #if INET6
100 #include <netinet6/in6_pcb.h>
101 #endif /* INET6 */
102
103 #include <netinet/ip_fw.h>
104
105 #if IPSEC
106 #include <netinet6/ipsec.h>
107 #endif /*IPSEC*/
108
109 #if DUMMYNET
110 #include <netinet/ip_dummynet.h>
111 #endif
112
113 #if CONFIG_MACF_NET
114 #include <security/mac_framework.h>
115 #endif /* MAC_NET */
116
117 int load_ipfw(void);
118 int rip_detach(struct socket *);
119 int rip_abort(struct socket *);
120 int rip_disconnect(struct socket *);
121 int rip_bind(struct socket *, struct sockaddr *, struct proc *);
122 int rip_connect(struct socket *, struct sockaddr *, struct proc *);
123 int rip_shutdown(struct socket *);
124
125 struct inpcbhead ripcb;
126 struct inpcbinfo ripcbinfo;
127
128 /* control hooks for ipfw and dummynet */
129 #if IPFIREWALL
130 ip_fw_ctl_t *ip_fw_ctl_ptr;
131 #endif /* IPFIREWALL */
132 #if DUMMYNET
133 ip_dn_ctl_t *ip_dn_ctl_ptr;
134 #endif /* DUMMYNET */
135
136 /*
137 * Nominal space allocated to a raw ip socket.
138 */
139 #define RIPSNDQ 8192
140 #define RIPRCVQ 8192
141
142 /*
143 * Raw interface to IP protocol.
144 */
145
146 /*
147 * Initialize raw connection block q.
148 */
149 void
150 rip_init(struct protosw *pp, struct domain *dp)
151 {
152 #pragma unused(dp)
153 static int rip_initialized = 0;
154 struct inpcbinfo *pcbinfo;
155
156 VERIFY((pp->pr_flags & (PR_INITIALIZED | PR_ATTACHED)) == PR_ATTACHED);
157
158 if (rip_initialized) {
159 return;
160 }
161 rip_initialized = 1;
162
163 LIST_INIT(&ripcb);
164 ripcbinfo.ipi_listhead = &ripcb;
165 /*
166 * XXX We don't use the hash list for raw IP, but it's easier
167 * to allocate a one entry hash list than it is to check all
168 * over the place for ipi_hashbase == NULL.
169 */
170 ripcbinfo.ipi_hashbase = hashinit(1, M_PCB, &ripcbinfo.ipi_hashmask);
171 ripcbinfo.ipi_porthashbase = hashinit(1, M_PCB, &ripcbinfo.ipi_porthashmask);
172
173 ripcbinfo.ipi_zone = zinit(sizeof(struct inpcb),
174 (4096 * sizeof(struct inpcb)), 4096, "ripzone");
175
176 pcbinfo = &ripcbinfo;
177 /*
178 * allocate lock group attribute and group for udp pcb mutexes
179 */
180 pcbinfo->ipi_lock_grp_attr = lck_grp_attr_alloc_init();
181 pcbinfo->ipi_lock_grp = lck_grp_alloc_init("ripcb", pcbinfo->ipi_lock_grp_attr);
182
183 /*
184 * allocate the lock attribute for udp pcb mutexes
185 */
186 pcbinfo->ipi_lock_attr = lck_attr_alloc_init();
187 if ((pcbinfo->ipi_lock = lck_rw_alloc_init(pcbinfo->ipi_lock_grp,
188 pcbinfo->ipi_lock_attr)) == NULL) {
189 panic("%s: unable to allocate PCB lock\n", __func__);
190 /* NOTREACHED */
191 }
192
193 in_pcbinfo_attach(&ripcbinfo);
194 }
195
196 static struct sockaddr_in ripsrc = {
197 .sin_len = sizeof(ripsrc),
198 .sin_family = AF_INET,
199 .sin_port = 0,
200 .sin_addr = { .s_addr = 0 },
201 .sin_zero = {0, 0, 0, 0, 0, 0, 0, 0, }
202 };
203
204 /*
205 * Setup generic address and protocol structures
206 * for raw_input routine, then pass them along with
207 * mbuf chain.
208 */
209 void
210 rip_input(struct mbuf *m, int iphlen)
211 {
212 struct ip *ip = mtod(m, struct ip *);
213 struct inpcb *inp;
214 struct inpcb *last = 0;
215 struct mbuf *opts = 0;
216 int skipit = 0, ret = 0;
217 struct ifnet *ifp = m->m_pkthdr.rcvif;
218
219 /* Expect 32-bit aligned data pointer on strict-align platforms */
220 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
221
222 ripsrc.sin_addr = ip->ip_src;
223 lck_rw_lock_shared(ripcbinfo.ipi_lock);
224 LIST_FOREACH(inp, &ripcb, inp_list) {
225 #if INET6
226 if ((inp->inp_vflag & INP_IPV4) == 0) {
227 continue;
228 }
229 #endif
230 if (inp->inp_ip_p && (inp->inp_ip_p != ip->ip_p)) {
231 continue;
232 }
233 if (inp->inp_laddr.s_addr &&
234 inp->inp_laddr.s_addr != ip->ip_dst.s_addr) {
235 continue;
236 }
237 if (inp->inp_faddr.s_addr &&
238 inp->inp_faddr.s_addr != ip->ip_src.s_addr) {
239 continue;
240 }
241 if (inp_restricted_recv(inp, ifp)) {
242 continue;
243 }
244 if (last) {
245 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
246
247 skipit = 0;
248
249 #if NECP
250 if (n && !necp_socket_is_allowed_to_send_recv_v4(last, 0, 0,
251 &ip->ip_dst, &ip->ip_src, ifp, NULL, NULL, NULL)) {
252 m_freem(n);
253 /* do not inject data to pcb */
254 skipit = 1;
255 }
256 #endif /* NECP */
257 #if CONFIG_MACF_NET
258 if (n && skipit == 0) {
259 if (mac_inpcb_check_deliver(last, n, AF_INET,
260 SOCK_RAW) != 0) {
261 m_freem(n);
262 skipit = 1;
263 }
264 }
265 #endif
266 if (n && skipit == 0) {
267 int error = 0;
268 if ((last->inp_flags & INP_CONTROLOPTS) != 0 ||
269 (last->inp_socket->so_options & SO_TIMESTAMP) != 0 ||
270 (last->inp_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
271 (last->inp_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
272 ret = ip_savecontrol(last, &opts, ip, n);
273 if (ret != 0) {
274 m_freem(n);
275 m_freem(opts);
276 last = inp;
277 continue;
278 }
279 }
280 if (last->inp_flags & INP_STRIPHDR) {
281 n->m_len -= iphlen;
282 n->m_pkthdr.len -= iphlen;
283 n->m_data += iphlen;
284 }
285 so_recv_data_stat(last->inp_socket, m, 0);
286 if (sbappendaddr(&last->inp_socket->so_rcv,
287 (struct sockaddr *)&ripsrc, n,
288 opts, &error) != 0) {
289 sorwakeup(last->inp_socket);
290 } else {
291 if (error) {
292 /* should notify about lost packet */
293 ipstat.ips_raw_sappend_fail++;
294 }
295 }
296 opts = 0;
297 }
298 }
299 last = inp;
300 }
301
302 skipit = 0;
303 #if NECP
304 if (last && !necp_socket_is_allowed_to_send_recv_v4(last, 0, 0,
305 &ip->ip_dst, &ip->ip_src, ifp, NULL, NULL, NULL)) {
306 m_freem(m);
307 OSAddAtomic(1, &ipstat.ips_delivered);
308 /* do not inject data to pcb */
309 skipit = 1;
310 }
311 #endif /* NECP */
312 #if CONFIG_MACF_NET
313 if (last && skipit == 0) {
314 if (mac_inpcb_check_deliver(last, m, AF_INET, SOCK_RAW) != 0) {
315 skipit = 1;
316 m_freem(m);
317 }
318 }
319 #endif
320 if (skipit == 0) {
321 if (last) {
322 if ((last->inp_flags & INP_CONTROLOPTS) != 0 ||
323 (last->inp_socket->so_options & SO_TIMESTAMP) != 0 ||
324 (last->inp_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
325 (last->inp_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
326 ret = ip_savecontrol(last, &opts, ip, m);
327 if (ret != 0) {
328 m_freem(m);
329 m_freem(opts);
330 goto unlock;
331 }
332 }
333 if (last->inp_flags & INP_STRIPHDR) {
334 m->m_len -= iphlen;
335 m->m_pkthdr.len -= iphlen;
336 m->m_data += iphlen;
337 }
338 so_recv_data_stat(last->inp_socket, m, 0);
339 if (sbappendaddr(&last->inp_socket->so_rcv,
340 (struct sockaddr *)&ripsrc, m, opts, NULL) != 0) {
341 sorwakeup(last->inp_socket);
342 } else {
343 ipstat.ips_raw_sappend_fail++;
344 }
345 } else {
346 m_freem(m);
347 OSAddAtomic(1, &ipstat.ips_noproto);
348 OSAddAtomic(-1, &ipstat.ips_delivered);
349 }
350 }
351 unlock:
352 /*
353 * Keep the list locked because socket filter may force the socket lock
354 * to be released when calling sbappendaddr() -- see rdar://7627704
355 */
356 lck_rw_done(ripcbinfo.ipi_lock);
357 }
358
359 /*
360 * Generate IP header and pass packet to ip_output.
361 * Tack on options user may have setup with control call.
362 */
363 int
364 rip_output(
365 struct mbuf *m,
366 struct socket *so,
367 u_int32_t dst,
368 struct mbuf *control)
369 {
370 struct ip *ip;
371 struct inpcb *inp = sotoinpcb(so);
372 int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
373 struct ip_out_args ipoa;
374 struct ip_moptions *imo;
375 int tos = IPTOS_UNSPEC;
376 int error = 0;
377
378 bzero(&ipoa, sizeof(ipoa));
379 ipoa.ipoa_boundif = IFSCOPE_NONE;
380 ipoa.ipoa_flags = IPOAF_SELECT_SRCIF;
381
382 int sotc = SO_TC_UNSPEC;
383 int netsvctype = _NET_SERVICE_TYPE_UNSPEC;
384
385
386 if (control != NULL) {
387 tos = so_tos_from_control(control);
388 sotc = so_tc_from_control(control, &netsvctype);
389
390 m_freem(control);
391 control = NULL;
392 }
393 if (sotc == SO_TC_UNSPEC) {
394 sotc = so->so_traffic_class;
395 netsvctype = so->so_netsvctype;
396 }
397
398 if (inp == NULL
399 #if NECP
400 || (necp_socket_should_use_flow_divert(inp))
401 #endif /* NECP */
402 ) {
403 if (m != NULL) {
404 m_freem(m);
405 }
406 VERIFY(control == NULL);
407 return inp == NULL ? EINVAL : EPROTOTYPE;
408 }
409
410 flags |= IP_OUTARGS;
411 /* If socket was bound to an ifindex, tell ip_output about it */
412 if (inp->inp_flags & INP_BOUND_IF) {
413 ipoa.ipoa_boundif = inp->inp_boundifp->if_index;
414 ipoa.ipoa_flags |= IPOAF_BOUND_IF;
415 }
416 if (INP_NO_CELLULAR(inp)) {
417 ipoa.ipoa_flags |= IPOAF_NO_CELLULAR;
418 }
419 if (INP_NO_EXPENSIVE(inp)) {
420 ipoa.ipoa_flags |= IPOAF_NO_EXPENSIVE;
421 }
422 if (INP_NO_CONSTRAINED(inp)) {
423 ipoa.ipoa_flags |= IPOAF_NO_CONSTRAINED;
424 }
425 if (INP_AWDL_UNRESTRICTED(inp)) {
426 ipoa.ipoa_flags |= IPOAF_AWDL_UNRESTRICTED;
427 }
428 ipoa.ipoa_sotc = sotc;
429 ipoa.ipoa_netsvctype = netsvctype;
430
431 if (inp->inp_flowhash == 0) {
432 inp->inp_flowhash = inp_calc_flowhash(inp);
433 }
434
435 /*
436 * If the user handed us a complete IP packet, use it.
437 * Otherwise, allocate an mbuf for a header and fill it in.
438 */
439 if ((inp->inp_flags & INP_HDRINCL) == 0) {
440 if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
441 m_freem(m);
442 return EMSGSIZE;
443 }
444 M_PREPEND(m, sizeof(struct ip), M_WAIT, 1);
445 if (m == NULL) {
446 return ENOBUFS;
447 }
448 ip = mtod(m, struct ip *);
449 if (tos != IPTOS_UNSPEC) {
450 ip->ip_tos = (uint8_t)(tos & IPTOS_MASK);
451 } else {
452 ip->ip_tos = inp->inp_ip_tos;
453 }
454 ip->ip_off = 0;
455 ip->ip_p = inp->inp_ip_p;
456 ip->ip_len = m->m_pkthdr.len;
457 ip->ip_src = inp->inp_laddr;
458 ip->ip_dst.s_addr = dst;
459 ip->ip_ttl = inp->inp_ip_ttl;
460 } else {
461 if (m->m_pkthdr.len > IP_MAXPACKET) {
462 m_freem(m);
463 return EMSGSIZE;
464 }
465 ip = mtod(m, struct ip *);
466 /* don't allow both user specified and setsockopt options,
467 * and don't allow packet length sizes that will crash */
468 if (((IP_VHL_HL(ip->ip_vhl) != (sizeof(*ip) >> 2))
469 && inp->inp_options)
470 || (ip->ip_len > m->m_pkthdr.len)
471 || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
472 m_freem(m);
473 return EINVAL;
474 }
475 if (ip->ip_id == 0 && !(rfc6864 && IP_OFF_IS_ATOMIC(ntohs(ip->ip_off)))) {
476 ip->ip_id = ip_randomid();
477 }
478 /* XXX prevent ip_output from overwriting header fields */
479 flags |= IP_RAWOUTPUT;
480 OSAddAtomic(1, &ipstat.ips_rawout);
481 }
482
483 if (inp->inp_laddr.s_addr != INADDR_ANY) {
484 ipoa.ipoa_flags |= IPOAF_BOUND_SRCADDR;
485 }
486
487 #if NECP
488 {
489 necp_kernel_policy_id policy_id;
490 necp_kernel_policy_id skip_policy_id;
491 u_int32_t route_rule_id;
492
493 /*
494 * We need a route to perform NECP route rule checks
495 */
496 if (net_qos_policy_restricted != 0 &&
497 ROUTE_UNUSABLE(&inp->inp_route)) {
498 struct sockaddr_in to;
499 struct sockaddr_in from;
500 struct in_addr laddr = ip->ip_src;
501
502 ROUTE_RELEASE(&inp->inp_route);
503
504 bzero(&from, sizeof(struct sockaddr_in));
505 from.sin_family = AF_INET;
506 from.sin_len = sizeof(struct sockaddr_in);
507 from.sin_addr = laddr;
508
509 bzero(&to, sizeof(struct sockaddr_in));
510 to.sin_family = AF_INET;
511 to.sin_len = sizeof(struct sockaddr_in);
512 to.sin_addr.s_addr = ip->ip_dst.s_addr;
513
514 if ((error = in_pcbladdr(inp, (struct sockaddr *)&to,
515 &laddr, ipoa.ipoa_boundif, NULL, 1)) != 0) {
516 printf("%s in_pcbladdr(%p) error %d\n",
517 __func__, inp, error);
518 m_freem(m);
519 return error;
520 }
521
522 inp_update_necp_policy(inp, (struct sockaddr *)&from,
523 (struct sockaddr *)&to, ipoa.ipoa_boundif);
524 inp->inp_policyresult.results.qos_marking_gencount = 0;
525 }
526
527 if (!necp_socket_is_allowed_to_send_recv_v4(inp, 0, 0,
528 &ip->ip_src, &ip->ip_dst, NULL, &policy_id, &route_rule_id, &skip_policy_id)) {
529 m_freem(m);
530 return EHOSTUNREACH;
531 }
532
533 necp_mark_packet_from_socket(m, inp, policy_id, route_rule_id, skip_policy_id);
534
535 if (net_qos_policy_restricted != 0) {
536 struct ifnet *rt_ifp = NULL;
537
538 if (inp->inp_route.ro_rt != NULL) {
539 rt_ifp = inp->inp_route.ro_rt->rt_ifp;
540 }
541
542 necp_socket_update_qos_marking(inp, inp->inp_route.ro_rt,
543 NULL, route_rule_id);
544 }
545 }
546 #endif /* NECP */
547 if ((so->so_flags1 & SOF1_QOSMARKING_ALLOWED)) {
548 ipoa.ipoa_flags |= IPOAF_QOSMARKING_ALLOWED;
549 }
550
551 #if IPSEC
552 if (inp->inp_sp != NULL && ipsec_setsocket(m, so) != 0) {
553 m_freem(m);
554 return ENOBUFS;
555 }
556 #endif /*IPSEC*/
557
558 if (ROUTE_UNUSABLE(&inp->inp_route)) {
559 ROUTE_RELEASE(&inp->inp_route);
560 }
561
562 set_packet_service_class(m, so, sotc, 0);
563 m->m_pkthdr.pkt_flowsrc = FLOWSRC_INPCB;
564 m->m_pkthdr.pkt_flowid = inp->inp_flowhash;
565 m->m_pkthdr.pkt_flags |= (PKTF_FLOW_ID | PKTF_FLOW_LOCALSRC |
566 PKTF_FLOW_RAWSOCK);
567 m->m_pkthdr.pkt_proto = inp->inp_ip_p;
568 m->m_pkthdr.tx_rawip_pid = so->last_pid;
569 m->m_pkthdr.tx_rawip_e_pid = so->e_pid;
570 if (so->so_flags & SOF_DELEGATED) {
571 m->m_pkthdr.tx_rawip_e_pid = so->e_pid;
572 } else {
573 m->m_pkthdr.tx_rawip_e_pid = 0;
574 }
575
576 #if CONFIG_MACF_NET
577 mac_mbuf_label_associate_inpcb(inp, m);
578 #endif
579
580 imo = inp->inp_moptions;
581 if (imo != NULL) {
582 IMO_ADDREF(imo);
583 }
584 /*
585 * The domain lock is held across ip_output, so it is okay
586 * to pass the PCB cached route pointer directly to IP and
587 * the modules beneath it.
588 */
589 // TODO: PASS DOWN ROUTE RULE ID
590 error = ip_output(m, inp->inp_options, &inp->inp_route, flags,
591 imo, &ipoa);
592
593 if (imo != NULL) {
594 IMO_REMREF(imo);
595 }
596
597 if (inp->inp_route.ro_rt != NULL) {
598 struct rtentry *rt = inp->inp_route.ro_rt;
599 struct ifnet *outif;
600
601 if ((rt->rt_flags & (RTF_MULTICAST | RTF_BROADCAST)) ||
602 inp->inp_socket == NULL ||
603 !(inp->inp_socket->so_state & SS_ISCONNECTED)) {
604 rt = NULL; /* unusable */
605 }
606 /*
607 * Always discard the cached route for unconnected
608 * socket or if it is a multicast route.
609 */
610 if (rt == NULL) {
611 ROUTE_RELEASE(&inp->inp_route);
612 }
613
614 /*
615 * If this is a connected socket and the destination
616 * route is unicast, update outif with that of the
617 * route interface used by IP.
618 */
619 if (rt != NULL &&
620 (outif = rt->rt_ifp) != inp->inp_last_outifp) {
621 inp->inp_last_outifp = outif;
622 }
623 } else {
624 ROUTE_RELEASE(&inp->inp_route);
625 }
626
627 /*
628 * If output interface was cellular/expensive/constrained, and this socket is
629 * denied access to it, generate an event.
630 */
631 if (error != 0 && (ipoa.ipoa_retflags & IPOARF_IFDENIED) &&
632 (INP_NO_CELLULAR(inp) || INP_NO_EXPENSIVE(inp) || INP_NO_CONSTRAINED(inp))) {
633 soevent(so, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_IFDENIED));
634 }
635
636 return error;
637 }
638
639 #if IPFIREWALL
640 int
641 load_ipfw(void)
642 {
643 kern_return_t err;
644
645 ipfw_init();
646
647 #if DUMMYNET
648 if (!DUMMYNET_LOADED) {
649 ip_dn_init();
650 }
651 #endif /* DUMMYNET */
652 err = 0;
653
654 return err == 0 && ip_fw_ctl_ptr == NULL ? -1 : err;
655 }
656 #endif /* IPFIREWALL */
657
658 /*
659 * Raw IP socket option processing.
660 */
661 int
662 rip_ctloutput(struct socket *so, struct sockopt *sopt)
663 {
664 struct inpcb *inp = sotoinpcb(so);
665 int error, optval;
666
667 /* Allow <SOL_SOCKET,SO_FLUSH> at this level */
668 if (sopt->sopt_level != IPPROTO_IP &&
669 !(sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_FLUSH)) {
670 return EINVAL;
671 }
672
673 error = 0;
674
675 switch (sopt->sopt_dir) {
676 case SOPT_GET:
677 switch (sopt->sopt_name) {
678 case IP_HDRINCL:
679 optval = inp->inp_flags & INP_HDRINCL;
680 error = sooptcopyout(sopt, &optval, sizeof optval);
681 break;
682
683 case IP_STRIPHDR:
684 optval = inp->inp_flags & INP_STRIPHDR;
685 error = sooptcopyout(sopt, &optval, sizeof optval);
686 break;
687
688 #if IPFIREWALL
689 case IP_FW_ADD:
690 case IP_FW_GET:
691 case IP_OLD_FW_ADD:
692 case IP_OLD_FW_GET:
693 if (ip_fw_ctl_ptr == 0) {
694 error = load_ipfw();
695 }
696 if (ip_fw_ctl_ptr && error == 0) {
697 error = ip_fw_ctl_ptr(sopt);
698 } else {
699 error = ENOPROTOOPT;
700 }
701 break;
702 #endif /* IPFIREWALL */
703
704 #if DUMMYNET
705 case IP_DUMMYNET_GET:
706 if (!DUMMYNET_LOADED) {
707 ip_dn_init();
708 }
709 if (DUMMYNET_LOADED) {
710 error = ip_dn_ctl_ptr(sopt);
711 } else {
712 error = ENOPROTOOPT;
713 }
714 break;
715 #endif /* DUMMYNET */
716
717 default:
718 error = ip_ctloutput(so, sopt);
719 break;
720 }
721 break;
722
723 case SOPT_SET:
724 switch (sopt->sopt_name) {
725 case IP_HDRINCL:
726 error = sooptcopyin(sopt, &optval, sizeof optval,
727 sizeof optval);
728 if (error) {
729 break;
730 }
731 if (optval) {
732 inp->inp_flags |= INP_HDRINCL;
733 } else {
734 inp->inp_flags &= ~INP_HDRINCL;
735 }
736 break;
737
738 case IP_STRIPHDR:
739 error = sooptcopyin(sopt, &optval, sizeof optval,
740 sizeof optval);
741 if (error) {
742 break;
743 }
744 if (optval) {
745 inp->inp_flags |= INP_STRIPHDR;
746 } else {
747 inp->inp_flags &= ~INP_STRIPHDR;
748 }
749 break;
750
751 #if IPFIREWALL
752 case IP_FW_ADD:
753 case IP_FW_DEL:
754 case IP_FW_FLUSH:
755 case IP_FW_ZERO:
756 case IP_FW_RESETLOG:
757 case IP_OLD_FW_ADD:
758 case IP_OLD_FW_DEL:
759 case IP_OLD_FW_FLUSH:
760 case IP_OLD_FW_ZERO:
761 case IP_OLD_FW_RESETLOG:
762 if (ip_fw_ctl_ptr == 0) {
763 error = load_ipfw();
764 }
765 if (ip_fw_ctl_ptr && error == 0) {
766 error = ip_fw_ctl_ptr(sopt);
767 } else {
768 error = ENOPROTOOPT;
769 }
770 break;
771 #endif /* IPFIREWALL */
772
773 #if DUMMYNET
774 case IP_DUMMYNET_CONFIGURE:
775 case IP_DUMMYNET_DEL:
776 case IP_DUMMYNET_FLUSH:
777 if (!DUMMYNET_LOADED) {
778 ip_dn_init();
779 }
780 if (DUMMYNET_LOADED) {
781 error = ip_dn_ctl_ptr(sopt);
782 } else {
783 error = ENOPROTOOPT;
784 }
785 break;
786 #endif
787
788 case SO_FLUSH:
789 if ((error = sooptcopyin(sopt, &optval, sizeof(optval),
790 sizeof(optval))) != 0) {
791 break;
792 }
793
794 error = inp_flush(inp, optval);
795 break;
796
797 default:
798 error = ip_ctloutput(so, sopt);
799 break;
800 }
801 break;
802 }
803
804 return error;
805 }
806
807 /*
808 * This function exists solely to receive the PRC_IFDOWN messages which
809 * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa,
810 * and calls in_ifadown() to remove all routes corresponding to that address.
811 * It also receives the PRC_IFUP messages from if_up() and reinstalls the
812 * interface routes.
813 */
814 void
815 rip_ctlinput(
816 int cmd,
817 struct sockaddr *sa,
818 __unused void *vip,
819 __unused struct ifnet *ifp)
820 {
821 struct in_ifaddr *ia = NULL;
822 struct ifnet *iaifp = NULL;
823 int err = 0;
824 int flags, done = 0;
825
826 switch (cmd) {
827 case PRC_IFDOWN:
828 lck_rw_lock_shared(in_ifaddr_rwlock);
829 for (ia = in_ifaddrhead.tqh_first; ia;
830 ia = ia->ia_link.tqe_next) {
831 IFA_LOCK(&ia->ia_ifa);
832 if (ia->ia_ifa.ifa_addr == sa &&
833 (ia->ia_flags & IFA_ROUTE)) {
834 done = 1;
835 IFA_ADDREF_LOCKED(&ia->ia_ifa);
836 IFA_UNLOCK(&ia->ia_ifa);
837 lck_rw_done(in_ifaddr_rwlock);
838 lck_mtx_lock(rnh_lock);
839 /*
840 * in_ifscrub kills the interface route.
841 */
842 in_ifscrub(ia->ia_ifp, ia, 1);
843 /*
844 * in_ifadown gets rid of all the rest of
845 * the routes. This is not quite the right
846 * thing to do, but at least if we are running
847 * a routing process they will come back.
848 */
849 in_ifadown(&ia->ia_ifa, 1);
850 lck_mtx_unlock(rnh_lock);
851 IFA_REMREF(&ia->ia_ifa);
852 break;
853 }
854 IFA_UNLOCK(&ia->ia_ifa);
855 }
856 if (!done) {
857 lck_rw_done(in_ifaddr_rwlock);
858 }
859 break;
860
861 case PRC_IFUP:
862 lck_rw_lock_shared(in_ifaddr_rwlock);
863 for (ia = in_ifaddrhead.tqh_first; ia;
864 ia = ia->ia_link.tqe_next) {
865 IFA_LOCK(&ia->ia_ifa);
866 if (ia->ia_ifa.ifa_addr == sa) {
867 /* keep it locked */
868 break;
869 }
870 IFA_UNLOCK(&ia->ia_ifa);
871 }
872 if (ia == NULL || (ia->ia_flags & IFA_ROUTE) ||
873 (ia->ia_ifa.ifa_debug & IFD_NOTREADY)) {
874 if (ia != NULL) {
875 IFA_UNLOCK(&ia->ia_ifa);
876 }
877 lck_rw_done(in_ifaddr_rwlock);
878 return;
879 }
880 IFA_ADDREF_LOCKED(&ia->ia_ifa);
881 IFA_UNLOCK(&ia->ia_ifa);
882 lck_rw_done(in_ifaddr_rwlock);
883
884 flags = RTF_UP;
885 iaifp = ia->ia_ifa.ifa_ifp;
886
887 if ((iaifp->if_flags & IFF_LOOPBACK)
888 || (iaifp->if_flags & IFF_POINTOPOINT)) {
889 flags |= RTF_HOST;
890 }
891
892 err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
893 if (err == 0) {
894 IFA_LOCK_SPIN(&ia->ia_ifa);
895 ia->ia_flags |= IFA_ROUTE;
896 IFA_UNLOCK(&ia->ia_ifa);
897 }
898 IFA_REMREF(&ia->ia_ifa);
899 break;
900 }
901 }
902
903 u_int32_t rip_sendspace = RIPSNDQ;
904 u_int32_t rip_recvspace = RIPRCVQ;
905
906 SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW | CTLFLAG_LOCKED,
907 &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
908 SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW | CTLFLAG_LOCKED,
909 &rip_recvspace, 0, "Maximum incoming raw IP datagram size");
910 SYSCTL_UINT(_net_inet_raw, OID_AUTO, pcbcount, CTLFLAG_RD | CTLFLAG_LOCKED,
911 &ripcbinfo.ipi_count, 0, "Number of active PCBs");
912
913 static int
914 rip_attach(struct socket *so, int proto, struct proc *p)
915 {
916 struct inpcb *inp;
917 int error;
918
919 inp = sotoinpcb(so);
920 if (inp) {
921 panic("rip_attach");
922 }
923 if ((so->so_state & SS_PRIV) == 0) {
924 return EPERM;
925 }
926
927 error = soreserve(so, rip_sendspace, rip_recvspace);
928 if (error) {
929 return error;
930 }
931 error = in_pcballoc(so, &ripcbinfo, p);
932 if (error) {
933 return error;
934 }
935 inp = (struct inpcb *)so->so_pcb;
936 inp->inp_vflag |= INP_IPV4;
937 inp->inp_ip_p = proto;
938 inp->inp_ip_ttl = ip_defttl;
939 return 0;
940 }
941
942 __private_extern__ int
943 rip_detach(struct socket *so)
944 {
945 struct inpcb *inp;
946
947 inp = sotoinpcb(so);
948 if (inp == 0) {
949 panic("rip_detach");
950 }
951 in_pcbdetach(inp);
952 return 0;
953 }
954
955 __private_extern__ int
956 rip_abort(struct socket *so)
957 {
958 soisdisconnected(so);
959 return rip_detach(so);
960 }
961
962 __private_extern__ int
963 rip_disconnect(struct socket *so)
964 {
965 if ((so->so_state & SS_ISCONNECTED) == 0) {
966 return ENOTCONN;
967 }
968 return rip_abort(so);
969 }
970
971 __private_extern__ int
972 rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
973 {
974 #pragma unused(p)
975 struct inpcb *inp = sotoinpcb(so);
976 struct sockaddr_in sin;
977 struct ifaddr *ifa = NULL;
978 struct ifnet *outif = NULL;
979
980 if (inp == NULL
981 #if NECP
982 || (necp_socket_should_use_flow_divert(inp))
983 #endif /* NECP */
984 ) {
985 return inp == NULL ? EINVAL : EPROTOTYPE;
986 }
987
988 if (nam->sa_len != sizeof(struct sockaddr_in)) {
989 return EINVAL;
990 }
991
992 /* Sanitized local copy for interface address searches */
993 bzero(&sin, sizeof(sin));
994 sin.sin_family = AF_INET;
995 sin.sin_len = sizeof(struct sockaddr_in);
996 sin.sin_addr.s_addr = SIN(nam)->sin_addr.s_addr;
997
998 if (TAILQ_EMPTY(&ifnet_head) ||
999 (sin.sin_family != AF_INET && sin.sin_family != AF_IMPLINK) ||
1000 (sin.sin_addr.s_addr && (ifa = ifa_ifwithaddr(SA(&sin))) == 0)) {
1001 return EADDRNOTAVAIL;
1002 } else if (ifa) {
1003 /*
1004 * Opportunistically determine the outbound
1005 * interface that may be used; this may not
1006 * hold true if we end up using a route
1007 * going over a different interface, e.g.
1008 * when sending to a local address. This
1009 * will get updated again after sending.
1010 */
1011 IFA_LOCK(ifa);
1012 outif = ifa->ifa_ifp;
1013 IFA_UNLOCK(ifa);
1014 IFA_REMREF(ifa);
1015 }
1016 inp->inp_laddr = sin.sin_addr;
1017 inp->inp_last_outifp = outif;
1018
1019 return 0;
1020 }
1021
1022 __private_extern__ int
1023 rip_connect(struct socket *so, struct sockaddr *nam, __unused struct proc *p)
1024 {
1025 struct inpcb *inp = sotoinpcb(so);
1026 struct sockaddr_in *addr = (struct sockaddr_in *)(void *)nam;
1027
1028 if (inp == NULL
1029 #if NECP
1030 || (necp_socket_should_use_flow_divert(inp))
1031 #endif /* NECP */
1032 ) {
1033 return inp == NULL ? EINVAL : EPROTOTYPE;
1034 }
1035 if (nam->sa_len != sizeof(*addr)) {
1036 return EINVAL;
1037 }
1038 if (TAILQ_EMPTY(&ifnet_head)) {
1039 return EADDRNOTAVAIL;
1040 }
1041 if ((addr->sin_family != AF_INET) &&
1042 (addr->sin_family != AF_IMPLINK)) {
1043 return EAFNOSUPPORT;
1044 }
1045
1046 if (!(so->so_flags1 & SOF1_CONNECT_COUNTED)) {
1047 so->so_flags1 |= SOF1_CONNECT_COUNTED;
1048 INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_inet_dgram_connected);
1049 }
1050
1051 inp->inp_faddr = addr->sin_addr;
1052 soisconnected(so);
1053
1054 return 0;
1055 }
1056
1057 __private_extern__ int
1058 rip_shutdown(struct socket *so)
1059 {
1060 socantsendmore(so);
1061 return 0;
1062 }
1063
1064 __private_extern__ int
1065 rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
1066 struct mbuf *control, struct proc *p)
1067 {
1068 #pragma unused(flags, p)
1069 struct inpcb *inp = sotoinpcb(so);
1070 u_int32_t dst;
1071 int error = 0;
1072
1073 if (inp == NULL
1074 #if NECP
1075 || (necp_socket_should_use_flow_divert(inp) && (error = EPROTOTYPE))
1076 #endif /* NECP */
1077 ) {
1078 if (inp == NULL) {
1079 error = EINVAL;
1080 } else {
1081 error = EPROTOTYPE;
1082 }
1083 goto bad;
1084 }
1085
1086 if (so->so_state & SS_ISCONNECTED) {
1087 if (nam != NULL) {
1088 error = EISCONN;
1089 goto bad;
1090 }
1091 dst = inp->inp_faddr.s_addr;
1092 } else {
1093 if (nam == NULL) {
1094 error = ENOTCONN;
1095 goto bad;
1096 }
1097 dst = ((struct sockaddr_in *)(void *)nam)->sin_addr.s_addr;
1098 }
1099 return rip_output(m, so, dst, control);
1100
1101 bad:
1102 VERIFY(error != 0);
1103
1104 if (m != NULL) {
1105 m_freem(m);
1106 }
1107 if (control != NULL) {
1108 m_freem(control);
1109 }
1110
1111 return error;
1112 }
1113
1114 /* note: rip_unlock is called from different protos instead of the generic socket_unlock,
1115 * it will handle the socket dealloc on last reference
1116 * */
1117 int
1118 rip_unlock(struct socket *so, int refcount, void *debug)
1119 {
1120 void *lr_saved;
1121 struct inpcb *inp = sotoinpcb(so);
1122
1123 if (debug == NULL) {
1124 lr_saved = __builtin_return_address(0);
1125 } else {
1126 lr_saved = debug;
1127 }
1128
1129 if (refcount) {
1130 if (so->so_usecount <= 0) {
1131 panic("rip_unlock: bad refoucnt so=%p val=%x lrh= %s\n",
1132 so, so->so_usecount, solockhistory_nr(so));
1133 /* NOTREACHED */
1134 }
1135 so->so_usecount--;
1136 if (so->so_usecount == 0 && (inp->inp_wantcnt == WNT_STOPUSING)) {
1137 /* cleanup after last reference */
1138 lck_mtx_unlock(so->so_proto->pr_domain->dom_mtx);
1139 lck_rw_lock_exclusive(ripcbinfo.ipi_lock);
1140 if (inp->inp_state != INPCB_STATE_DEAD) {
1141 #if INET6
1142 if (SOCK_CHECK_DOM(so, PF_INET6)) {
1143 in6_pcbdetach(inp);
1144 } else
1145 #endif /* INET6 */
1146 in_pcbdetach(inp);
1147 }
1148 in_pcbdispose(inp);
1149 lck_rw_done(ripcbinfo.ipi_lock);
1150 return 0;
1151 }
1152 }
1153 so->unlock_lr[so->next_unlock_lr] = lr_saved;
1154 so->next_unlock_lr = (so->next_unlock_lr + 1) % SO_LCKDBG_MAX;
1155 lck_mtx_unlock(so->so_proto->pr_domain->dom_mtx);
1156 return 0;
1157 }
1158
1159 static int
1160 rip_pcblist SYSCTL_HANDLER_ARGS
1161 {
1162 #pragma unused(oidp, arg1, arg2)
1163 int error, i, n;
1164 struct inpcb *inp, **inp_list;
1165 inp_gen_t gencnt;
1166 struct xinpgen xig;
1167
1168 /*
1169 * The process of preparing the TCB list is too time-consuming and
1170 * resource-intensive to repeat twice on every request.
1171 */
1172 lck_rw_lock_exclusive(ripcbinfo.ipi_lock);
1173 if (req->oldptr == USER_ADDR_NULL) {
1174 n = ripcbinfo.ipi_count;
1175 req->oldidx = 2 * (sizeof xig)
1176 + (n + n / 8) * sizeof(struct xinpcb);
1177 lck_rw_done(ripcbinfo.ipi_lock);
1178 return 0;
1179 }
1180
1181 if (req->newptr != USER_ADDR_NULL) {
1182 lck_rw_done(ripcbinfo.ipi_lock);
1183 return EPERM;
1184 }
1185
1186 /*
1187 * OK, now we're committed to doing something.
1188 */
1189 gencnt = ripcbinfo.ipi_gencnt;
1190 n = ripcbinfo.ipi_count;
1191
1192 bzero(&xig, sizeof(xig));
1193 xig.xig_len = sizeof xig;
1194 xig.xig_count = n;
1195 xig.xig_gen = gencnt;
1196 xig.xig_sogen = so_gencnt;
1197 error = SYSCTL_OUT(req, &xig, sizeof xig);
1198 if (error) {
1199 lck_rw_done(ripcbinfo.ipi_lock);
1200 return error;
1201 }
1202 /*
1203 * We are done if there is no pcb
1204 */
1205 if (n == 0) {
1206 lck_rw_done(ripcbinfo.ipi_lock);
1207 return 0;
1208 }
1209
1210 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
1211 if (inp_list == 0) {
1212 lck_rw_done(ripcbinfo.ipi_lock);
1213 return ENOMEM;
1214 }
1215
1216 for (inp = ripcbinfo.ipi_listhead->lh_first, i = 0; inp && i < n;
1217 inp = inp->inp_list.le_next) {
1218 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1219 inp_list[i++] = inp;
1220 }
1221 }
1222 n = i;
1223
1224 error = 0;
1225 for (i = 0; i < n; i++) {
1226 inp = inp_list[i];
1227 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1228 struct xinpcb xi;
1229
1230 bzero(&xi, sizeof(xi));
1231 xi.xi_len = sizeof xi;
1232 /* XXX should avoid extra copy */
1233 inpcb_to_compat(inp, &xi.xi_inp);
1234 if (inp->inp_socket) {
1235 sotoxsocket(inp->inp_socket, &xi.xi_socket);
1236 }
1237 error = SYSCTL_OUT(req, &xi, sizeof xi);
1238 }
1239 }
1240 if (!error) {
1241 /*
1242 * Give the user an updated idea of our state.
1243 * If the generation differs from what we told
1244 * her before, she knows that something happened
1245 * while we were processing this request, and it
1246 * might be necessary to retry.
1247 */
1248 bzero(&xig, sizeof(xig));
1249 xig.xig_len = sizeof xig;
1250 xig.xig_gen = ripcbinfo.ipi_gencnt;
1251 xig.xig_sogen = so_gencnt;
1252 xig.xig_count = ripcbinfo.ipi_count;
1253 error = SYSCTL_OUT(req, &xig, sizeof xig);
1254 }
1255 FREE(inp_list, M_TEMP);
1256 lck_rw_done(ripcbinfo.ipi_lock);
1257 return error;
1258 }
1259
1260 SYSCTL_PROC(_net_inet_raw, OID_AUTO /*XXX*/, pcblist,
1261 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
1262 rip_pcblist, "S,xinpcb", "List of active raw IP sockets");
1263
1264 #if !CONFIG_EMBEDDED
1265
1266 static int
1267 rip_pcblist64 SYSCTL_HANDLER_ARGS
1268 {
1269 #pragma unused(oidp, arg1, arg2)
1270 int error, i, n;
1271 struct inpcb *inp, **inp_list;
1272 inp_gen_t gencnt;
1273 struct xinpgen xig;
1274
1275 /*
1276 * The process of preparing the TCB list is too time-consuming and
1277 * resource-intensive to repeat twice on every request.
1278 */
1279 lck_rw_lock_exclusive(ripcbinfo.ipi_lock);
1280 if (req->oldptr == USER_ADDR_NULL) {
1281 n = ripcbinfo.ipi_count;
1282 req->oldidx = 2 * (sizeof xig)
1283 + (n + n / 8) * sizeof(struct xinpcb64);
1284 lck_rw_done(ripcbinfo.ipi_lock);
1285 return 0;
1286 }
1287
1288 if (req->newptr != USER_ADDR_NULL) {
1289 lck_rw_done(ripcbinfo.ipi_lock);
1290 return EPERM;
1291 }
1292
1293 /*
1294 * OK, now we're committed to doing something.
1295 */
1296 gencnt = ripcbinfo.ipi_gencnt;
1297 n = ripcbinfo.ipi_count;
1298
1299 bzero(&xig, sizeof(xig));
1300 xig.xig_len = sizeof xig;
1301 xig.xig_count = n;
1302 xig.xig_gen = gencnt;
1303 xig.xig_sogen = so_gencnt;
1304 error = SYSCTL_OUT(req, &xig, sizeof xig);
1305 if (error) {
1306 lck_rw_done(ripcbinfo.ipi_lock);
1307 return error;
1308 }
1309 /*
1310 * We are done if there is no pcb
1311 */
1312 if (n == 0) {
1313 lck_rw_done(ripcbinfo.ipi_lock);
1314 return 0;
1315 }
1316
1317 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
1318 if (inp_list == 0) {
1319 lck_rw_done(ripcbinfo.ipi_lock);
1320 return ENOMEM;
1321 }
1322
1323 for (inp = ripcbinfo.ipi_listhead->lh_first, i = 0; inp && i < n;
1324 inp = inp->inp_list.le_next) {
1325 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1326 inp_list[i++] = inp;
1327 }
1328 }
1329 n = i;
1330
1331 error = 0;
1332 for (i = 0; i < n; i++) {
1333 inp = inp_list[i];
1334 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1335 struct xinpcb64 xi;
1336
1337 bzero(&xi, sizeof(xi));
1338 xi.xi_len = sizeof xi;
1339 inpcb_to_xinpcb64(inp, &xi);
1340 if (inp->inp_socket) {
1341 sotoxsocket64(inp->inp_socket, &xi.xi_socket);
1342 }
1343 error = SYSCTL_OUT(req, &xi, sizeof xi);
1344 }
1345 }
1346 if (!error) {
1347 /*
1348 * Give the user an updated idea of our state.
1349 * If the generation differs from what we told
1350 * her before, she knows that something happened
1351 * while we were processing this request, and it
1352 * might be necessary to retry.
1353 */
1354 bzero(&xig, sizeof(xig));
1355 xig.xig_len = sizeof xig;
1356 xig.xig_gen = ripcbinfo.ipi_gencnt;
1357 xig.xig_sogen = so_gencnt;
1358 xig.xig_count = ripcbinfo.ipi_count;
1359 error = SYSCTL_OUT(req, &xig, sizeof xig);
1360 }
1361 FREE(inp_list, M_TEMP);
1362 lck_rw_done(ripcbinfo.ipi_lock);
1363 return error;
1364 }
1365
1366 SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist64,
1367 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
1368 rip_pcblist64, "S,xinpcb64", "List of active raw IP sockets");
1369
1370 #endif /* !CONFIG_EMBEDDED */
1371
1372
1373 static int
1374 rip_pcblist_n SYSCTL_HANDLER_ARGS
1375 {
1376 #pragma unused(oidp, arg1, arg2)
1377 int error = 0;
1378
1379 error = get_pcblist_n(IPPROTO_IP, req, &ripcbinfo);
1380
1381 return error;
1382 }
1383
1384 SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist_n,
1385 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
1386 rip_pcblist_n, "S,xinpcb_n", "List of active raw IP sockets");
1387
1388 struct pr_usrreqs rip_usrreqs = {
1389 .pru_abort = rip_abort,
1390 .pru_attach = rip_attach,
1391 .pru_bind = rip_bind,
1392 .pru_connect = rip_connect,
1393 .pru_control = in_control,
1394 .pru_detach = rip_detach,
1395 .pru_disconnect = rip_disconnect,
1396 .pru_peeraddr = in_getpeeraddr,
1397 .pru_send = rip_send,
1398 .pru_shutdown = rip_shutdown,
1399 .pru_sockaddr = in_getsockaddr,
1400 .pru_sosend = sosend,
1401 .pru_soreceive = soreceive,
1402 };
1403 /* DSEP Review Done pl-20051213-v02 @3253 */