1/*
2 * Copyright (c) 2010-2018 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, 1990, 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
61#include <sys/types.h>
62#include <sys/malloc.h>
63#include <sys/socket.h>
64#include <sys/socketvar.h>
65#include <sys/protosw.h>
66#include <sys/domain.h>
67#include <sys/filedesc.h>
68#include <sys/file_internal.h>
69#include <sys/kernel.h>
70#include <sys/sysctl.h>
71#include <sys/dtrace.h>
72#include <sys/kauth.h>
73
74#include <net/route.h>
75#include <net/if_var.h>
76#include <net/if_ports_used.h>
77#include <net/ntstat.h>
78
79#include <netinet/in.h>
80#include <netinet/in_pcb.h>
81#include <netinet/in_var.h>
82#include <netinet/ip_var.h>
83
84#include <netinet/udp.h>
85#include <netinet/udp_var.h>
86
87#include <netinet/tcp.h>
88#include <netinet/tcp_fsm.h>
89#include <netinet/tcp_seq.h>
90#include <netinet/tcp_timer.h>
91#include <netinet/tcp_var.h>
92#include <netinet6/in6_var.h>
93
94#include <os/log.h>
95
96#ifndef ROUNDUP64
97#define ROUNDUP64(x) P2ROUNDUP((x), sizeof (u_int64_t))
98#endif
99
100#ifndef ADVANCE64
101#define ADVANCE64(p, n) (void*)((char *)(p) + ROUNDUP64(n))
102#endif
103
104static void inpcb_to_xinpcb_n(struct inpcb *, struct xinpcb_n *);
105static void tcpcb_to_xtcpcb_n(struct tcpcb *, struct xtcpcb_n *);
106void shutdown_sockets_on_interface(struct ifnet *ifp);
107
108
109__private_extern__ void
110sotoxsocket_n(struct socket *so, struct xsocket_n *xso)
111{
112 xso->xso_len = sizeof (struct xsocket_n);
113 xso->xso_kind = XSO_SOCKET;
114
115 if (so != NULL) {
116 xso->xso_so = (uint64_t)VM_KERNEL_ADDRPERM(so);
117 xso->so_type = so->so_type;
118 xso->so_options = so->so_options;
119 xso->so_linger = so->so_linger;
120 xso->so_state = so->so_state;
121 xso->so_pcb = (uint64_t)VM_KERNEL_ADDRPERM(so->so_pcb);
122 if (so->so_proto) {
123 xso->xso_protocol = SOCK_PROTO(so);
124 xso->xso_family = SOCK_DOM(so);
125 } else {
126 xso->xso_protocol = xso->xso_family = 0;
127 }
128 xso->so_qlen = so->so_qlen;
129 xso->so_incqlen = so->so_incqlen;
130 xso->so_qlimit = so->so_qlimit;
131 xso->so_timeo = so->so_timeo;
132 xso->so_error = so->so_error;
133 xso->so_pgid = so->so_pgid;
134 xso->so_oobmark = so->so_oobmark;
135 xso->so_uid = kauth_cred_getuid(so->so_cred);
136 xso->so_last_pid = so->last_pid;
137 xso->so_e_pid = so->e_pid;
138 }
139}
140
141__private_extern__ void
142sbtoxsockbuf_n(struct sockbuf *sb, struct xsockbuf_n *xsb)
143{
144 xsb->xsb_len = sizeof (struct xsockbuf_n);
145 xsb->xsb_kind = (sb->sb_flags & SB_RECV) ? XSO_RCVBUF : XSO_SNDBUF;
146
147 if (sb != NULL) {
148 xsb->sb_cc = sb->sb_cc;
149 xsb->sb_hiwat = sb->sb_hiwat;
150 xsb->sb_mbcnt = sb->sb_mbcnt;
151 xsb->sb_mbmax = sb->sb_mbmax;
152 xsb->sb_lowat = sb->sb_lowat;
153 xsb->sb_flags = sb->sb_flags;
154 xsb->sb_timeo = (short)(sb->sb_timeo.tv_sec * hz) +
155 sb->sb_timeo.tv_usec / tick;
156 if (xsb->sb_timeo == 0 && sb->sb_timeo.tv_usec != 0)
157 xsb->sb_timeo = 1;
158 }
159}
160
161__private_extern__ void
162sbtoxsockstat_n(struct socket *so, struct xsockstat_n *xst)
163{
164 int i;
165
166 xst->xst_len = sizeof (struct xsockstat_n);
167 xst->xst_kind = XSO_STATS;
168
169 for (i = 0; i < SO_TC_STATS_MAX; i++) {
170 xst->xst_tc_stats[i].rxpackets = so->so_tc_stats[i].rxpackets;
171 xst->xst_tc_stats[i].rxbytes = so->so_tc_stats[i].rxbytes;
172 xst->xst_tc_stats[i].txpackets = so->so_tc_stats[i].txpackets;
173 xst->xst_tc_stats[i].txbytes = so->so_tc_stats[i].txbytes;
174 }
175}
176
177static void
178inpcb_to_xinpcb_n(struct inpcb *inp, struct xinpcb_n *xinp)
179{
180 xinp->xi_len = sizeof (struct xinpcb_n);
181 xinp->xi_kind = XSO_INPCB;
182 xinp->xi_inpp = (uint64_t)VM_KERNEL_ADDRPERM(inp);
183 xinp->inp_fport = inp->inp_fport;
184 xinp->inp_lport = inp->inp_lport;
185 xinp->inp_ppcb = (uint64_t)VM_KERNEL_ADDRPERM(inp->inp_ppcb);
186 xinp->inp_gencnt = inp->inp_gencnt;
187 xinp->inp_flags = inp->inp_flags;
188 xinp->inp_flow = inp->inp_flow;
189 xinp->inp_vflag = inp->inp_vflag;
190 xinp->inp_ip_ttl = inp->inp_ip_ttl;
191 xinp->inp_ip_p = inp->inp_ip_p;
192 xinp->inp_dependfaddr.inp6_foreign = inp->inp_dependfaddr.inp6_foreign;
193 xinp->inp_dependladdr.inp6_local = inp->inp_dependladdr.inp6_local;
194 xinp->inp_depend4.inp4_ip_tos = inp->inp_depend4.inp4_ip_tos;
195 xinp->inp_depend6.inp6_hlim = 0;
196 xinp->inp_depend6.inp6_cksum = inp->inp_depend6.inp6_cksum;
197 xinp->inp_depend6.inp6_ifindex = 0;
198 xinp->inp_depend6.inp6_hops = inp->inp_depend6.inp6_hops;
199 xinp->inp_flowhash = inp->inp_flowhash;
200 xinp->inp_flags2 = inp->inp_flags2;
201}
202
203__private_extern__ void
204tcpcb_to_xtcpcb_n(struct tcpcb *tp, struct xtcpcb_n *xt)
205{
206 xt->xt_len = sizeof (struct xtcpcb_n);
207 xt->xt_kind = XSO_TCPCB;
208
209 xt->t_segq = (uint32_t)VM_KERNEL_ADDRPERM(tp->t_segq.lh_first);
210 xt->t_dupacks = tp->t_dupacks;
211 xt->t_timer[TCPT_REXMT_EXT] = tp->t_timer[TCPT_REXMT];
212 xt->t_timer[TCPT_PERSIST_EXT] = tp->t_timer[TCPT_PERSIST];
213 xt->t_timer[TCPT_KEEP_EXT] = tp->t_timer[TCPT_KEEP];
214 xt->t_timer[TCPT_2MSL_EXT] = tp->t_timer[TCPT_2MSL];
215 xt->t_state = tp->t_state;
216 xt->t_flags = tp->t_flags;
217 xt->t_force = (tp->t_flagsext & TF_FORCE) ? 1 : 0;
218 xt->snd_una = tp->snd_una;
219 xt->snd_max = tp->snd_max;
220 xt->snd_nxt = tp->snd_nxt;
221 xt->snd_up = tp->snd_up;
222 xt->snd_wl1 = tp->snd_wl1;
223 xt->snd_wl2 = tp->snd_wl2;
224 xt->iss = tp->iss;
225 xt->irs = tp->irs;
226 xt->rcv_nxt = tp->rcv_nxt;
227 xt->rcv_adv = tp->rcv_adv;
228 xt->rcv_wnd = tp->rcv_wnd;
229 xt->rcv_up = tp->rcv_up;
230 xt->snd_wnd = tp->snd_wnd;
231 xt->snd_cwnd = tp->snd_cwnd;
232 xt->snd_ssthresh = tp->snd_ssthresh;
233 xt->t_maxopd = tp->t_maxopd;
234 xt->t_rcvtime = tp->t_rcvtime;
235 xt->t_starttime = tp->t_starttime;
236 xt->t_rtttime = tp->t_rtttime;
237 xt->t_rtseq = tp->t_rtseq;
238 xt->t_rxtcur = tp->t_rxtcur;
239 xt->t_maxseg = tp->t_maxseg;
240 xt->t_srtt = tp->t_srtt;
241 xt->t_rttvar = tp->t_rttvar;
242 xt->t_rxtshift = tp->t_rxtshift;
243 xt->t_rttmin = tp->t_rttmin;
244 xt->t_rttupdated = tp->t_rttupdated;
245 xt->max_sndwnd = tp->max_sndwnd;
246 xt->t_softerror = tp->t_softerror;
247 xt->t_oobflags = tp->t_oobflags;
248 xt->t_iobc = tp->t_iobc;
249 xt->snd_scale = tp->snd_scale;
250 xt->rcv_scale = tp->rcv_scale;
251 xt->request_r_scale = tp->request_r_scale;
252 xt->requested_s_scale = tp->requested_s_scale;
253 xt->ts_recent = tp->ts_recent;
254 xt->ts_recent_age = tp->ts_recent_age;
255 xt->last_ack_sent = tp->last_ack_sent;
256 xt->cc_send = 0;
257 xt->cc_recv = 0;
258 xt->snd_recover = tp->snd_recover;
259 xt->snd_cwnd_prev = tp->snd_cwnd_prev;
260 xt->snd_ssthresh_prev = tp->snd_ssthresh_prev;
261}
262
263__private_extern__ int
264get_pcblist_n(short proto, struct sysctl_req *req, struct inpcbinfo *pcbinfo)
265{
266 int error = 0;
267 int i, n;
268 struct inpcb *inp, **inp_list = NULL;
269 inp_gen_t gencnt;
270 struct xinpgen xig;
271 void *buf = NULL;
272 size_t item_size = ROUNDUP64(sizeof (struct xinpcb_n)) +
273 ROUNDUP64(sizeof (struct xsocket_n)) +
274 2 * ROUNDUP64(sizeof (struct xsockbuf_n)) +
275 ROUNDUP64(sizeof (struct xsockstat_n));
276
277 if (proto == IPPROTO_TCP)
278 item_size += ROUNDUP64(sizeof (struct xtcpcb_n));
279
280 if (req->oldptr == USER_ADDR_NULL) {
281 n = pcbinfo->ipi_count;
282 req->oldidx = 2 * (sizeof (xig)) + (n + n/8 + 1) * item_size;
283 return 0;
284 }
285
286 if (req->newptr != USER_ADDR_NULL) {
287 return EPERM;
288 }
289
290
291 /*
292 * The process of preparing the PCB list is too time-consuming and
293 * resource-intensive to repeat twice on every request.
294 */
295 lck_rw_lock_exclusive(pcbinfo->ipi_lock);
296 /*
297 * OK, now we're committed to doing something.
298 */
299 gencnt = pcbinfo->ipi_gencnt;
300 n = pcbinfo->ipi_count;
301
302 bzero(&xig, sizeof (xig));
303 xig.xig_len = sizeof (xig);
304 xig.xig_count = n;
305 xig.xig_gen = gencnt;
306 xig.xig_sogen = so_gencnt;
307 error = SYSCTL_OUT(req, &xig, sizeof (xig));
308 if (error) {
309 goto done;
310 }
311 /*
312 * We are done if there is no pcb
313 */
314 if (xig.xig_count == 0) {
315 goto done;
316 }
317
318 buf = _MALLOC(item_size, M_TEMP, M_WAITOK);
319 if (buf == NULL) {
320 error = ENOMEM;
321 goto done;
322 }
323
324 inp_list = _MALLOC(n * sizeof (*inp_list), M_TEMP, M_WAITOK);
325 if (inp_list == NULL) {
326 error = ENOMEM;
327 goto done;
328 }
329
330 /*
331 * Special case TCP to include the connections in time wait
332 */
333 if (proto == IPPROTO_TCP) {
334 n = get_tcp_inp_list(inp_list, n, gencnt);
335 } else {
336 for (inp = pcbinfo->ipi_listhead->lh_first, i = 0; inp && i < n;
337 inp = inp->inp_list.le_next) {
338 if (inp->inp_gencnt <= gencnt &&
339 inp->inp_state != INPCB_STATE_DEAD)
340 inp_list[i++] = inp;
341 }
342 n = i;
343 }
344
345
346 error = 0;
347 for (i = 0; i < n; i++) {
348 inp = inp_list[i];
349 if (inp->inp_gencnt <= gencnt &&
350 inp->inp_state != INPCB_STATE_DEAD) {
351 struct xinpcb_n *xi = (struct xinpcb_n *)buf;
352 struct xsocket_n *xso = (struct xsocket_n *)
353 ADVANCE64(xi, sizeof (*xi));
354 struct xsockbuf_n *xsbrcv = (struct xsockbuf_n *)
355 ADVANCE64(xso, sizeof (*xso));
356 struct xsockbuf_n *xsbsnd = (struct xsockbuf_n *)
357 ADVANCE64(xsbrcv, sizeof (*xsbrcv));
358 struct xsockstat_n *xsostats = (struct xsockstat_n *)
359 ADVANCE64(xsbsnd, sizeof (*xsbsnd));
360
361 bzero(buf, item_size);
362
363 inpcb_to_xinpcb_n(inp, xi);
364 sotoxsocket_n(inp->inp_socket, xso);
365 sbtoxsockbuf_n(inp->inp_socket ?
366 &inp->inp_socket->so_rcv : NULL, xsbrcv);
367 sbtoxsockbuf_n(inp->inp_socket ?
368 &inp->inp_socket->so_snd : NULL, xsbsnd);
369 sbtoxsockstat_n(inp->inp_socket, xsostats);
370 if (proto == IPPROTO_TCP) {
371 struct xtcpcb_n *xt = (struct xtcpcb_n *)
372 ADVANCE64(xsostats, sizeof (*xsostats));
373
374 /*
375 * inp->inp_ppcb, can only be NULL on
376 * an initialization race window.
377 * No need to lock.
378 */
379 if (inp->inp_ppcb == NULL)
380 continue;
381
382 tcpcb_to_xtcpcb_n((struct tcpcb *)
383 inp->inp_ppcb, xt);
384 }
385 error = SYSCTL_OUT(req, buf, item_size);
386 if (error) {
387 break;
388 }
389 }
390 }
391
392 if (!error) {
393 /*
394 * Give the user an updated idea of our state.
395 * If the generation differs from what we told
396 * her before, she knows that something happened
397 * while we were processing this request, and it
398 * might be necessary to retry.
399 */
400 bzero(&xig, sizeof (xig));
401 xig.xig_len = sizeof (xig);
402 xig.xig_gen = pcbinfo->ipi_gencnt;
403 xig.xig_sogen = so_gencnt;
404 xig.xig_count = pcbinfo->ipi_count;
405 error = SYSCTL_OUT(req, &xig, sizeof (xig));
406 }
407done:
408 lck_rw_done(pcbinfo->ipi_lock);
409
410 if (inp_list != NULL)
411 FREE(inp_list, M_TEMP);
412 if (buf != NULL)
413 FREE(buf, M_TEMP);
414 return (error);
415}
416
417__private_extern__ void
418inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags,
419 bitstr_t *bitfield, struct inpcbinfo *pcbinfo)
420{
421 struct inpcb *inp;
422 struct socket *so;
423 inp_gen_t gencnt;
424 bool iswildcard, wildcardok, nowakeok;
425 bool recvanyifonly, extbgidleok;
426 bool activeonly;
427
428 wildcardok = ((flags & INPCB_GET_PORTS_USED_WILDCARDOK) != 0);
429 nowakeok = ((flags & INPCB_GET_PORTS_USED_NOWAKEUPOK) != 0);
430 recvanyifonly = ((flags & INPCB_GET_PORTS_USED_RECVANYIFONLY) != 0);
431 extbgidleok = ((flags & INPCB_GET_PORTS_USED_EXTBGIDLEONLY) != 0);
432 activeonly = ((flags & INPCB_GET_PORTS_USED_ACTIVEONLY) != 0);
433
434 lck_rw_lock_shared(pcbinfo->ipi_lock);
435 gencnt = pcbinfo->ipi_gencnt;
436
437 for (inp = LIST_FIRST(pcbinfo->ipi_listhead); inp;
438 inp = LIST_NEXT(inp, inp_list)) {
439 uint16_t port;
440
441 if (inp->inp_gencnt > gencnt ||
442 inp->inp_state == INPCB_STATE_DEAD ||
443 inp->inp_wantcnt == WNT_STOPUSING)
444 continue;
445
446 if ((so = inp->inp_socket) == NULL ||
447 (so->so_state & SS_DEFUNCT) ||
448 (so->so_state & SS_ISDISCONNECTED))
449 continue;
450
451 /*
452 * If protocol is specified, filter out inpcbs that
453 * are not relevant to the protocol family of interest.
454 */
455 if (protocol != PF_UNSPEC) {
456 if (protocol == PF_INET) {
457 /*
458 * If protocol of interest is IPv4, skip the inpcb
459 * if the family is not IPv4.
460 * OR
461 * If the family is IPv4, skip if the IPv4 flow is
462 * CLAT46 translated.
463 */
464 if ((inp->inp_vflag & INP_IPV4) == 0 ||
465 (inp->inp_flags2 & INP2_CLAT46_FLOW) != 0) {
466 continue;
467 }
468 } else if (protocol == PF_INET6) {
469 /*
470 * If protocol of interest is IPv6, skip the inpcb
471 * if the family is not IPv6.
472 * AND
473 * The flow is not a CLAT46'd flow.
474 */
475 if ((inp->inp_vflag & INP_IPV6) == 0 &&
476 (inp->inp_flags2 & INP2_CLAT46_FLOW) == 0) {
477 continue;
478 }
479 } else {
480 /* Protocol family not supported */
481 continue;
482 }
483 }
484
485 if (SOCK_PROTO(inp->inp_socket) != IPPROTO_UDP &&
486 SOCK_PROTO(inp->inp_socket) != IPPROTO_TCP)
487 continue;
488
489 iswildcard = (((inp->inp_vflag & INP_IPV4) &&
490 inp->inp_laddr.s_addr == INADDR_ANY) ||
491 ((inp->inp_vflag & INP_IPV6) &&
492 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)));
493
494 if (!wildcardok && iswildcard)
495 continue;
496
497 if ((so->so_options & SO_NOWAKEFROMSLEEP) &&
498 !nowakeok)
499 continue;
500
501 if (!(inp->inp_flags & INP_RECV_ANYIF) &&
502 recvanyifonly)
503 continue;
504
505 if (!(so->so_flags1 & SOF1_EXTEND_BK_IDLE_WANTED) &&
506 extbgidleok)
507 continue;
508
509 if (!iswildcard &&
510 !(ifindex == 0 || inp->inp_last_outifp == NULL ||
511 ifindex == inp->inp_last_outifp->if_index))
512 continue;
513
514 if (SOCK_PROTO(inp->inp_socket) == IPPROTO_UDP &&
515 so->so_state & SS_CANTRCVMORE)
516 continue;
517
518 if (SOCK_PROTO(inp->inp_socket) == IPPROTO_TCP) {
519 struct tcpcb *tp = sototcpcb(inp->inp_socket);
520
521 /*
522 * Workaround race where inp_ppcb is NULL during
523 * socket initialization
524 */
525 if (tp == NULL)
526 continue;
527
528 switch (tp->t_state) {
529 case TCPS_CLOSED:
530 continue;
531 /* NOT REACHED */
532 case TCPS_LISTEN:
533 case TCPS_SYN_SENT:
534 case TCPS_SYN_RECEIVED:
535 case TCPS_ESTABLISHED:
536 case TCPS_FIN_WAIT_1:
537 /*
538 * Note: FIN_WAIT_1 is an active state
539 * because we need our FIN to be
540 * acknowledged
541 */
542 break;
543 case TCPS_CLOSE_WAIT:
544 case TCPS_CLOSING:
545 case TCPS_LAST_ACK:
546 case TCPS_FIN_WAIT_2:
547 /*
548 * In the closing states, the connection
549 * is not idle when there is outgoing
550 * data having to be acknowledged
551 */
552 if (activeonly && so->so_snd.sb_cc == 0)
553 continue;
554 break;
555 case TCPS_TIME_WAIT:
556 continue;
557 /* NOT REACHED */
558 }
559 }
560 /*
561 * Final safeguard to exclude unspecified local port
562 */
563 port = ntohs(inp->inp_lport);
564 if (port == 0)
565 continue;
566 bitstr_set(bitfield, port);
567
568 if_ports_used_add_inpcb(ifindex, inp);
569 }
570 lck_rw_done(pcbinfo->ipi_lock);
571}
572
573__private_extern__ uint32_t
574inpcb_count_opportunistic(unsigned int ifindex, struct inpcbinfo *pcbinfo,
575 u_int32_t flags)
576{
577 uint32_t opportunistic = 0;
578 struct inpcb *inp;
579 inp_gen_t gencnt;
580
581 lck_rw_lock_shared(pcbinfo->ipi_lock);
582 gencnt = pcbinfo->ipi_gencnt;
583 for (inp = LIST_FIRST(pcbinfo->ipi_listhead);
584 inp != NULL; inp = LIST_NEXT(inp, inp_list)) {
585 if (inp->inp_gencnt <= gencnt &&
586 inp->inp_state != INPCB_STATE_DEAD &&
587 inp->inp_socket != NULL &&
588 so_get_opportunistic(inp->inp_socket) &&
589 inp->inp_last_outifp != NULL &&
590 ifindex == inp->inp_last_outifp->if_index) {
591 opportunistic++;
592 struct socket *so = inp->inp_socket;
593 if ((flags & INPCB_OPPORTUNISTIC_SETCMD) &&
594 (so->so_state & SS_ISCONNECTED)) {
595 socket_lock(so, 1);
596 if (flags & INPCB_OPPORTUNISTIC_THROTTLEON) {
597 so->so_flags |= SOF_SUSPENDED;
598 soevent(so,
599 (SO_FILT_HINT_LOCKED |
600 SO_FILT_HINT_SUSPEND));
601 } else {
602 so->so_flags &= ~(SOF_SUSPENDED);
603 soevent(so,
604 (SO_FILT_HINT_LOCKED |
605 SO_FILT_HINT_RESUME));
606 }
607 SOTHROTTLELOG("throttle[%d]: so 0x%llx "
608 "[%d,%d] %s\n", so->last_pid,
609 (uint64_t)VM_KERNEL_ADDRPERM(so),
610 SOCK_DOM(so), SOCK_TYPE(so),
611 (so->so_flags & SOF_SUSPENDED) ?
612 "SUSPENDED" : "RESUMED");
613 socket_unlock(so, 1);
614 }
615 }
616 }
617
618 lck_rw_done(pcbinfo->ipi_lock);
619
620 return (opportunistic);
621}
622
623__private_extern__ uint32_t
624inpcb_find_anypcb_byaddr(struct ifaddr *ifa, struct inpcbinfo *pcbinfo)
625{
626 struct inpcb *inp;
627 inp_gen_t gencnt = pcbinfo->ipi_gencnt;
628 struct socket *so = NULL;
629 int af;
630
631 if ((ifa->ifa_addr->sa_family != AF_INET) &&
632 (ifa->ifa_addr->sa_family != AF_INET6)) {
633 return (0);
634 }
635
636 lck_rw_lock_shared(pcbinfo->ipi_lock);
637 for (inp = LIST_FIRST(pcbinfo->ipi_listhead);
638 inp != NULL; inp = LIST_NEXT(inp, inp_list)) {
639
640 if (inp->inp_gencnt <= gencnt &&
641 inp->inp_state != INPCB_STATE_DEAD &&
642 inp->inp_socket != NULL) {
643 so = inp->inp_socket;
644 af = SOCK_DOM(so);
645 if (af != ifa->ifa_addr->sa_family)
646 continue;
647 if (inp->inp_last_outifp != ifa->ifa_ifp)
648 continue;
649
650 if (af == AF_INET) {
651 if (inp->inp_laddr.s_addr ==
652 (satosin(ifa->ifa_addr))->sin_addr.s_addr) {
653 lck_rw_done(pcbinfo->ipi_lock);
654 return (1);
655 }
656 }
657 if (af == AF_INET6) {
658 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa),
659 &inp->in6p_laddr)) {
660 lck_rw_done(pcbinfo->ipi_lock);
661 return (1);
662 }
663 }
664 }
665 }
666 lck_rw_done(pcbinfo->ipi_lock);
667 return (0);
668}
669
670static int
671shutdown_sockets_on_interface_proc_callout(proc_t p, void *arg)
672{
673 struct filedesc *fdp;
674 int i;
675 struct ifnet *ifp = (struct ifnet *)arg;
676
677 if (ifp == NULL)
678 return (PROC_RETURNED);
679
680 proc_fdlock(p);
681 fdp = p->p_fd;
682 for (i = 0; i < fdp->fd_nfiles; i++) {
683 struct fileproc *fp = fdp->fd_ofiles[i];
684 struct fileglob *fg;
685 struct socket *so;
686 struct inpcb *inp;
687 struct ifnet *inp_ifp;
688 int error;
689
690 if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0) {
691 continue;
692 }
693
694 fg = fp->f_fglob;
695 if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET)
696 continue;
697
698 so = (struct socket *)fp->f_fglob->fg_data;
699 if (SOCK_DOM(so) != PF_INET && SOCK_DOM(so) != PF_INET6)
700 continue;
701
702 inp = (struct inpcb *)so->so_pcb;
703
704 if (in_pcb_checkstate(inp, WNT_ACQUIRE, 0) == WNT_STOPUSING)
705 continue;
706
707 socket_lock(so, 1);
708
709 if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
710 socket_unlock(so, 1);
711 continue;
712 }
713
714 if (inp->inp_boundifp != NULL) {
715 inp_ifp = inp->inp_boundifp;
716 } else if (inp->inp_last_outifp != NULL) {
717 inp_ifp = inp->inp_last_outifp;
718 } else {
719 socket_unlock(so, 1);
720 continue;
721 }
722
723 if (inp_ifp != ifp && inp_ifp->if_delegated.ifp != ifp) {
724 socket_unlock(so, 1);
725 continue;
726 }
727 error = sosetdefunct(p, so, 0, TRUE);
728 if (error != 0) {
729 log(LOG_ERR, "%s: sosetdefunct() error %d",
730 __func__, error);
731 } else {
732 error = sodefunct(p, so, 0);
733 if (error != 0) {
734 log(LOG_ERR, "%s: sodefunct() error %d",
735 __func__, error);
736 }
737 }
738
739 socket_unlock(so, 1);
740 }
741 proc_fdunlock(p);
742
743 return (PROC_RETURNED);
744}
745
746void
747shutdown_sockets_on_interface(struct ifnet *ifp)
748{
749 proc_iterate(PROC_ALLPROCLIST,
750 shutdown_sockets_on_interface_proc_callout,
751 ifp, NULL, NULL);
752}
753