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