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