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