]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in_pcblist.c
xnu-1699.26.8.tar.gz
[apple/xnu.git] / bsd / netinet / in_pcblist.c
1 /*
2 * Copyright (c) 2010 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
71 #include <net/route.h>
72
73 #include <netinet/in.h>
74 #include <netinet/in_pcb.h>
75 #include <netinet/ip_var.h>
76
77 #include <netinet/udp.h>
78 #include <netinet/udp_var.h>
79
80 #include <netinet/tcp.h>
81 #include <netinet/tcp_fsm.h>
82 #include <netinet/tcp_seq.h>
83 #include <netinet/tcp_timer.h>
84 #include <netinet/tcp_var.h>
85
86 #ifndef ROUNDUP64
87 #define ROUNDUP64(x) P2ROUNDUP((x), sizeof(u_int64_t))
88 #endif
89
90 #ifndef ADVANCE64
91 #define ADVANCE64(p, n) (void*)((char *)(p) + ROUNDUP64(n))
92 #endif
93
94
95 void sotoxsocket_n(struct socket *, struct xsocket_n *);
96 void sbtoxsockbuf_n(struct sockbuf *, struct xsockbuf_n *);
97 void sbtoxsockstat_n(struct socket *, struct xsockstat_n *);
98 void inpcb_to_xinpcb_n(struct inpcb *, struct xinpcb_n *);
99 void tcpcb_to_xtcpcb_n(struct tcpcb *, struct xtcpcb_n *);
100
101 __private_extern__ void
102 sotoxsocket_n(struct socket *so, struct xsocket_n *xso)
103 {
104 xso->xso_len = sizeof(struct xsocket_n);
105 xso->xso_kind = XSO_SOCKET;
106
107 if (so != NULL) {
108 xso->xso_so = (u_int64_t)(uintptr_t)so;
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;
113 xso->so_pcb = (u_int64_t)(uintptr_t)so->so_pcb;
114 if (so->so_proto) {
115 xso->xso_protocol = so->so_proto->pr_protocol;
116 xso->xso_family = so->so_proto->pr_domain->dom_family;
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;
127 xso->so_uid = so->so_uid;
128 }
129 }
130
131 __private_extern__ void
132 sbtoxsockbuf_n(struct sockbuf *sb, struct xsockbuf_n *xsb)
133 {
134 xsb->xsb_len = sizeof(struct xsockbuf_n);
135 xsb->xsb_kind = (sb->sb_flags & SB_RECV) ? XSO_RCVBUF : XSO_SNDBUF;
136
137 if (sb != NULL) {
138 xsb->sb_cc = sb->sb_cc;
139 xsb->sb_hiwat = sb->sb_hiwat;
140 xsb->sb_mbcnt = sb->sb_mbcnt;
141 xsb->sb_mbmax = sb->sb_mbmax;
142 xsb->sb_lowat = sb->sb_lowat;
143 xsb->sb_flags = sb->sb_flags;
144 xsb->sb_timeo = (short)
145 (sb->sb_timeo.tv_sec * hz) + sb->sb_timeo.tv_usec / tick;
146 if (xsb->sb_timeo == 0 && sb->sb_timeo.tv_usec != 0)
147 xsb->sb_timeo = 1;
148 }
149 }
150
151 __private_extern__ void
152 sbtoxsockstat_n(struct socket *so, struct xsockstat_n *xst)
153 {
154 int i;
155
156 xst->xst_len = sizeof(struct xsockstat_n);
157 xst->xst_kind = XSO_STATS;
158
159 for (i = 0; i < SO_TC_STATS_MAX; i++) {
160 xst->xst_tc_stats[i].rxpackets = so->so_tc_stats[i].rxpackets;
161 xst->xst_tc_stats[i].rxbytes = so->so_tc_stats[i].rxbytes;
162 xst->xst_tc_stats[i].txpackets = so->so_tc_stats[i].txpackets;
163 xst->xst_tc_stats[i].txbytes = so->so_tc_stats[i].txbytes;
164 }
165 }
166
167 __private_extern__ void
168 inpcb_to_xinpcb_n(struct inpcb *inp, struct xinpcb_n *xinp)
169 {
170 xinp->xi_len = sizeof(struct xinpcb_n);
171 xinp->xi_kind = XSO_INPCB;
172 xinp->xi_inpp = (u_int64_t)(uintptr_t)inp;
173 xinp->inp_fport = inp->inp_fport;
174 xinp->inp_lport = inp->inp_lport;
175 xinp->inp_ppcb = (u_int64_t)(uintptr_t)inp->inp_ppcb;
176 xinp->inp_gencnt = inp->inp_gencnt;
177 xinp->inp_flags = inp->inp_flags;
178 xinp->inp_flow = inp->inp_flow;
179 xinp->inp_vflag = inp->inp_vflag;
180 xinp->inp_ip_ttl = inp->inp_ip_ttl;
181 xinp->inp_ip_p = inp->inp_ip_p;
182 xinp->inp_dependfaddr.inp6_foreign = inp->inp_dependfaddr.inp6_foreign;
183 xinp->inp_dependladdr.inp6_local = inp->inp_dependladdr.inp6_local;
184 xinp->inp_depend4.inp4_ip_tos = inp->inp_depend4.inp4_ip_tos;
185 xinp->inp_depend6.inp6_hlim = inp->inp_depend6.inp6_hlim;
186 xinp->inp_depend6.inp6_cksum = inp->inp_depend6.inp6_cksum;
187 xinp->inp_depend6.inp6_ifindex = inp->inp_depend6.inp6_ifindex;
188 xinp->inp_depend6.inp6_hops = inp->inp_depend6.inp6_hops;
189 }
190
191 __private_extern__ void
192 tcpcb_to_xtcpcb_n(struct tcpcb *tp, struct xtcpcb_n *xt)
193 {
194 int i;
195
196 xt->xt_len = sizeof(struct xtcpcb_n);
197 xt->xt_kind = XSO_TCPCB;
198
199 xt->t_segq = (u_int32_t)(uintptr_t)tp->t_segq.lh_first;
200 xt->t_dupacks = tp->t_dupacks;
201 for (i = 0; i < TCPT_NTIMERS_EXT; i++)
202 xt->t_timer[i] = tp->t_timer[i];
203 xt->t_state = tp->t_state;
204 xt->t_flags = tp->t_flags;
205 xt->t_force = tp->t_force;
206 xt->snd_una = tp->snd_una;
207 xt->snd_max = tp->snd_max;
208 xt->snd_nxt = tp->snd_nxt;
209 xt->snd_up = tp->snd_up;
210 xt->snd_wl1 = tp->snd_wl1;
211 xt->snd_wl2 = tp->snd_wl2;
212 xt->iss = tp->iss;
213 xt->irs = tp->irs;
214 xt->rcv_nxt = tp->rcv_nxt;
215 xt->rcv_adv = tp->rcv_adv;
216 xt->rcv_wnd = tp->rcv_wnd;
217 xt->rcv_up = tp->rcv_up;
218 xt->snd_wnd = tp->snd_wnd;
219 xt->snd_cwnd = tp->snd_cwnd;
220 xt->snd_ssthresh = tp->snd_ssthresh;
221 xt->t_maxopd = tp->t_maxopd;
222 xt->t_rcvtime = tp->t_rcvtime;
223 xt->t_starttime = tp->t_starttime;
224 xt->t_rtttime = tp->t_rtttime;
225 xt->t_rtseq = tp->t_rtseq;
226 xt->t_rxtcur = tp->t_rxtcur;
227 xt->t_maxseg = tp->t_maxseg;
228 xt->t_srtt = tp->t_srtt;
229 xt->t_rttvar = tp->t_rttvar;
230 xt->t_rxtshift = tp->t_rxtshift;
231 xt->t_rttmin = tp->t_rttmin;
232 xt->t_rttupdated = tp->t_rttupdated;
233 xt->max_sndwnd = tp->max_sndwnd;
234 xt->t_softerror = tp->t_softerror;
235 xt->t_oobflags = tp->t_oobflags;
236 xt->t_iobc = tp->t_iobc;
237 xt->snd_scale = tp->snd_scale;
238 xt->rcv_scale = tp->rcv_scale;
239 xt->request_r_scale = tp->request_r_scale;
240 xt->requested_s_scale = tp->requested_s_scale;
241 xt->ts_recent = tp->ts_recent;
242 xt->ts_recent_age = tp->ts_recent_age;
243 xt->last_ack_sent = tp->last_ack_sent;
244 xt->cc_send = tp->cc_send;
245 xt->cc_recv = tp->cc_recv;
246 xt->snd_recover = tp->snd_recover;
247 xt->snd_cwnd_prev = tp->snd_cwnd_prev;
248 xt->snd_ssthresh_prev = tp->snd_ssthresh_prev;
249 xt->t_badrxtwin = tp->t_badrxtwin;
250 }
251
252 __private_extern__ int
253 get_pcblist_n(short proto, struct sysctl_req *req, struct inpcbinfo *pcbinfo)
254 {
255 int error = 0;
256 int i, n;
257 struct inpcb *inp, **inp_list = NULL;
258 inp_gen_t gencnt;
259 struct xinpgen xig;
260 void *buf = NULL;
261 size_t item_size = ROUNDUP64(sizeof(struct xinpcb_n)) +
262 ROUNDUP64(sizeof(struct xsocket_n)) +
263 2 * ROUNDUP64(sizeof(struct xsockbuf_n)) +
264 ROUNDUP64(sizeof(struct xsockstat_n));
265
266 if (proto == IPPROTO_TCP)
267 item_size += ROUNDUP64(sizeof(struct xtcpcb_n));
268
269 /*
270 * The process of preparing the PCB list is too time-consuming and
271 * resource-intensive to repeat twice on every request.
272 */
273 lck_rw_lock_exclusive(pcbinfo->mtx);
274 if (req->oldptr == USER_ADDR_NULL) {
275 n = pcbinfo->ipi_count;
276 req->oldidx = 2 * (sizeof xig)
277 + (n + n/8) * item_size;
278 goto done;
279 }
280
281 if (req->newptr != USER_ADDR_NULL) {
282 error = EPERM;
283 goto done;
284 }
285
286 /*
287 * OK, now we're committed to doing something.
288 */
289 gencnt = pcbinfo->ipi_gencnt;
290 n = pcbinfo->ipi_count;
291
292 bzero(&xig, sizeof(xig));
293 xig.xig_len = sizeof xig;
294 xig.xig_count = n;
295 xig.xig_gen = gencnt;
296 xig.xig_sogen = so_gencnt;
297 error = SYSCTL_OUT(req, &xig, sizeof xig);
298 if (error) {
299 goto done;
300 }
301 /*
302 * We are done if there is no pcb
303 */
304 if (n == 0) {
305 goto done;
306 }
307
308 buf = _MALLOC(item_size, M_TEMP, M_WAITOK);
309 if (buf == 0) {
310 error = ENOMEM;
311 goto done;
312 }
313
314 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
315 if (inp_list == 0) {
316 error = ENOMEM;
317 goto done;
318 }
319
320 for (inp = pcbinfo->listhead->lh_first, i = 0; inp && i < n;
321 inp = inp->inp_list.le_next) {
322 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)
323 inp_list[i++] = inp;
324 }
325 n = i;
326
327 error = 0;
328 for (i = 0; i < n; i++) {
329 inp = inp_list[i];
330 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
331 struct xinpcb_n *xi = (struct xinpcb_n *)buf;
332 struct xsocket_n *xso = (struct xsocket_n *)ADVANCE64(xi, sizeof(*xi));
333 struct xsockbuf_n *xsbrcv = (struct xsockbuf_n *)ADVANCE64(xso, sizeof(*xso));
334 struct xsockbuf_n *xsbsnd = (struct xsockbuf_n *)ADVANCE64(xsbrcv, sizeof(*xsbrcv));
335 struct xsockstat_n *xsostats = (struct xsockstat_n *)ADVANCE64(xsbsnd, sizeof(*xsbsnd));
336
337 bzero(buf, item_size);
338
339 inpcb_to_xinpcb_n(inp, xi);
340 sotoxsocket_n(inp->inp_socket, xso);
341 sbtoxsockbuf_n(inp->inp_socket ? &inp->inp_socket->so_rcv : NULL, xsbrcv);
342 sbtoxsockbuf_n(inp->inp_socket ? &inp->inp_socket->so_snd : NULL, xsbsnd);
343 sbtoxsockstat_n(inp->inp_socket, xsostats);
344 if (proto == IPPROTO_TCP) {
345 struct xtcpcb_n *xt = (struct xtcpcb_n *)ADVANCE64(xsostats, sizeof(*xsostats));
346
347 /*
348 * inp->inp_ppcb, can only be NULL on
349 * an initialization race window.
350 * No need to lock.
351 */
352 if (inp->inp_ppcb == NULL)
353 continue;
354
355 tcpcb_to_xtcpcb_n((struct tcpcb *)inp->inp_ppcb, xt);
356 }
357 error = SYSCTL_OUT(req, buf, item_size);
358 }
359 }
360 if (!error) {
361 /*
362 * Give the user an updated idea of our state.
363 * If the generation differs from what we told
364 * her before, she knows that something happened
365 * while we were processing this request, and it
366 * might be necessary to retry.
367 */
368 bzero(&xig, sizeof(xig));
369 xig.xig_len = sizeof xig;
370 xig.xig_gen = pcbinfo->ipi_gencnt;
371 xig.xig_sogen = so_gencnt;
372 xig.xig_count = pcbinfo->ipi_count;
373 error = SYSCTL_OUT(req, &xig, sizeof xig);
374 }
375 done:
376 lck_rw_done(pcbinfo->mtx);
377 if (inp_list)
378 FREE(inp_list, M_TEMP);
379 if (buf)
380 FREE(buf, M_TEMP);
381 return error;
382 }
383