xref: /freebsd/cddl/lib/libdtrace/tcp.d (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright (c) 2013 Mark Johnston <markj@freebsd.org>
24  */
25 
26 #pragma D depends_on library ip.d
27 #pragma D depends_on module kernel
28 #pragma D depends_on provider tcp
29 
30 /*
31  * Convert a TCP state value to a string.
32  */
33 #pragma D binding "1.6.3" TCPS_CLOSED
34 inline int TCPS_CLOSED =	0;
35 #pragma D binding "1.6.3" TCPS_LISTEN
36 inline int TCPS_LISTEN =	1;
37 #pragma D binding "1.6.3" TCPS_SYN_SENT
38 inline int TCPS_SYN_SENT =	2;
39 #pragma D binding "1.6.3" TCPS_SYN_RECEIVED
40 inline int TCPS_SYN_RECEIVED =	3;
41 #pragma D binding "1.6.3" TCPS_ESTABLISHED
42 inline int TCPS_ESTABLISHED =	4;
43 #pragma D binding "1.6.3" TCPS_CLOSE_WAIT
44 inline int TCPS_CLOSE_WAIT =	5;
45 #pragma D binding "1.6.3" TCPS_FIN_WAIT_1
46 inline int TCPS_FIN_WAIT_1 =	6;
47 #pragma D binding "1.6.3" TCPS_CLOSING
48 inline int TCPS_CLOSING =	7;
49 #pragma D binding "1.6.3" TCPS_LAST_ACK
50 inline int TCPS_LAST_ACK =	8;
51 #pragma D binding "1.6.3" TCPS_FIN_WAIT_2
52 inline int TCPS_FIN_WAIT_2 =	9;
53 #pragma D binding "1.6.3" TCPS_TIME_WAIT
54 inline int TCPS_TIME_WAIT =	10;
55 
56 /*
57  * For compatibility also provide the names used by Solaris.
58  */
59 #pragma D binding "1.13" TCP_STATE_CLOSED
60 inline int TCP_STATE_CLOSED =		TCPS_CLOSED;
61 #pragma D binding "1.13" TCP_STATE_LISTEN
62 inline int TCP_STATE_LISTEN =		TCPS_LISTEN;
63 #pragma D binding "1.13" TCP_STATE_SYN_SENT
64 inline int TCP_STATE_SYN_SENT =		TCPS_SYN_SENT;
65 #pragma D binding "1.13" TCP_STATE_SYN_RECEIVED
66 inline int TCP_STATE_SYN_RECEIVED =	TCPS_SYN_RECEIVED;
67 #pragma D binding "1.13" TCP_STATE_ESTABLISHED
68 inline int TCP_STATE_ESTABLISHED =	TCPS_ESTABLISHED;
69 #pragma D binding "1.13" TCP_STATE_CLOSE_WAIT
70 inline int TCP_STATE_CLOSE_WAIT =	TCPS_CLOSE_WAIT;
71 #pragma D binding "1.13" TCP_STATE_FIN_WAIT_1
72 inline int TCP_STATE_FIN_WAIT_1 =	TCPS_FIN_WAIT_1;
73 #pragma D binding "1.13" TCP_STATE_CLOSING
74 inline int TCP_STATE_CLOSING =		TCPS_CLOSING;
75 #pragma D binding "1.13" TCP_STATE_LAST_ACK
76 inline int TCP_STATE_LAST_ACK =		TCPS_LAST_ACK;
77 #pragma D binding "1.13" TCP_STATE_FIN_WAIT_2
78 inline int TCP_STATE_FIN_WAIT_2 =	TCPS_FIN_WAIT_2;
79 #pragma D binding "1.13" TCP_STATE_TIME_WAIT
80 inline int TCP_STATE_TIME_WAIT =	TCPS_TIME_WAIT;
81 
82 /* TCP segment flags. */
83 #pragma D binding "1.6.3" TH_FIN
84 inline uint16_t TH_FIN =	0x01;
85 #pragma D binding "1.6.3" TH_SYN
86 inline uint16_t TH_SYN =	0x02;
87 #pragma D binding "1.6.3" TH_RST
88 inline uint16_t TH_RST =	0x04;
89 #pragma D binding "1.6.3" TH_PUSH
90 inline uint16_t TH_PUSH =	0x08;
91 #pragma D binding "1.6.3" TH_ACK
92 inline uint16_t TH_ACK =	0x10;
93 #pragma D binding "1.6.3" TH_URG
94 inline uint16_t TH_URG =	0x20;
95 #pragma D binding "1.6.3" TH_ECE
96 inline uint16_t TH_ECE =	0x40;
97 #pragma D binding "1.6.3" TH_CWR
98 inline uint16_t TH_CWR =	0x80;
99 #pragma D binding "1.6.3" TH_AE
100 inline uint16_t TH_AE =		0x100;
101 
102 /* TCP connection state strings. */
103 #pragma D binding "1.6.3" tcp_state_string
104 inline string tcp_state_string[int32_t state] =
105 	state == TCPS_CLOSED ?		"state-closed" :
106 	state == TCPS_LISTEN ?		"state-listen" :
107 	state == TCPS_SYN_SENT ?	"state-syn-sent" :
108 	state == TCPS_SYN_RECEIVED ?	"state-syn-received" :
109 	state == TCPS_ESTABLISHED ?	"state-established" :
110 	state == TCPS_CLOSE_WAIT ?	"state-close-wait" :
111 	state == TCPS_FIN_WAIT_1 ?	"state-fin-wait-1" :
112 	state == TCPS_CLOSING ?		"state-closing" :
113 	state == TCPS_LAST_ACK ?	"state-last-ack" :
114 	state == TCPS_FIN_WAIT_2 ?	"state-fin-wait-2" :
115 	state == TCPS_TIME_WAIT ?	"state-time-wait" :
116 	"<unknown>";
117 
118 /*
119  * tcpsinfo contains stable TCP details from tcp_t.
120  */
121 typedef struct tcpsinfo {
122 	uintptr_t tcps_addr;
123 	int tcps_local;			/* is delivered locally, boolean */
124 	int tcps_active;		/* active open (from here), boolean */
125 	uint16_t tcps_lport;		/* local port */
126 	uint16_t tcps_rport;		/* remote port */
127 	string tcps_laddr;		/* local address, as a string */
128 	string tcps_raddr;		/* remote address, as a string */
129 	int32_t tcps_state;		/* TCP state */
130 	uint32_t tcps_iss;		/* Initial sequence # sent */
131 	uint32_t tcps_irs;		/* Initial sequence # received */
132 	uint32_t tcps_suna;		/* sequence # sent but unacked */
133 	uint32_t tcps_smax;		/* highest sequence number sent */
134 	uint32_t tcps_snxt;		/* next sequence # to send */
135 	uint32_t tcps_rack;		/* sequence # we have acked */
136 	uint32_t tcps_rnxt;		/* next sequence # expected */
137 	u_long tcps_swnd;		/* send window size */
138 	int32_t tcps_snd_ws;		/* send window scaling */
139 	uint32_t tcps_swl1;		/* window update seg seq number */
140 	uint32_t tcps_swl2;		/* window update seg ack number */
141 	uint32_t tcps_rup;		/* receive urgent pointer */
142 	uint32_t tcps_radv;		/* advertised window */
143 	u_long tcps_rwnd;		/* receive window size */
144 	int32_t tcps_rcv_ws;		/* receive window scaling */
145 	u_long tcps_cwnd;		/* congestion window */
146 	u_long tcps_cwnd_ssthresh;	/* threshold for congestion avoidance */
147 	uint32_t tcps_srecover;		/* for use in NewReno Fast Recovery */
148 	uint32_t tcps_sack_fack;	/* SACK sequence # we have acked */
149 	uint32_t tcps_sack_snxt;	/* next SACK seq # for retransmission */
150 	uint32_t tcps_rto;		/* round-trip timeout, msec */
151 	uint32_t tcps_mss;		/* max segment size */
152 	int tcps_retransmit;		/* retransmit send event, boolean */
153 	int tcps_srtt;			/* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
154 	int tcps_debug;			/* socket has SO_DEBUG set */
155 	int tcps_cookie;		/* expose the socket's SO_USER_COOKIE */
156 	int32_t tcps_dupacks;		/* consecutive dup acks received */
157 	uint32_t tcps_rtttime;		/* RTT measurement start time */
158 	uint32_t tcps_rtseq;		/* sequence # being timed */
159 	uint32_t tcps_ts_recent;	/* timestamp echo data */
160 } tcpsinfo_t;
161 
162 /*
163  * tcplsinfo provides the old tcp state for state changes.
164  */
165 typedef struct tcplsinfo {
166 	int32_t tcps_state;		/* previous TCP state */
167 } tcplsinfo_t;
168 
169 /*
170  * tcpinfo is the TCP header fields.
171  */
172 typedef struct tcpinfo {
173 	uint16_t tcp_sport;		/* source port */
174 	uint16_t tcp_dport;		/* destination port */
175 	uint32_t tcp_seq;		/* sequence number */
176 	uint32_t tcp_ack;		/* acknowledgment number */
177 	uint8_t tcp_offset;		/* data offset, in bytes */
178 	uint16_t tcp_flags;		/* flags */
179 	uint16_t tcp_window;		/* window size */
180 	uint16_t tcp_checksum;		/* checksum */
181 	uint16_t tcp_urgent;		/* urgent data pointer */
182 	struct tcphdr *tcp_hdr;		/* raw TCP header */
183 } tcpinfo_t;
184 
185 /*
186  * A clone of tcpinfo_t used to handle the fact that the TCP input path
187  * overwrites some fields of the TCP header with their host-order equivalents.
188  * Unfortunately, DTrace doesn't let us simply typedef a new name for struct
189  * tcpinfo and define a separate translator for it.
190  */
191 typedef struct tcpinfoh {
192 	uint16_t tcp_sport;		/* source port */
193 	uint16_t tcp_dport;		/* destination port */
194 	uint32_t tcp_seq;		/* sequence number */
195 	uint32_t tcp_ack;		/* acknowledgment number */
196 	uint8_t tcp_offset;		/* data offset, in bytes */
197 	uint16_t tcp_flags;		/* flags */
198 	uint16_t tcp_window;		/* window size */
199 	uint16_t tcp_checksum;		/* checksum */
200 	uint16_t tcp_urgent;		/* urgent data pointer */
201 	struct tcphdr *tcp_hdr;		/* raw TCP header */
202 } tcpinfoh_t;
203 
204 #pragma D binding "1.6.3" translator
205 translator csinfo_t < struct tcpcb *p > {
206 	cs_addr =	NULL;
207 	cs_cid =	(uint64_t)(p == NULL ? 0 : &p->t_inpcb);
208 	cs_pid =	0;
209 	cs_zoneid =	0;
210 };
211 
212 #pragma D binding "1.6.3" translator
213 translator tcpsinfo_t < struct tcpcb *p > {
214 	tcps_addr =		(uintptr_t)p;
215 	tcps_local =		-1; /* XXX */
216 	tcps_active =		-1; /* XXX */
217 	tcps_lport =		p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_lport);
218 	tcps_rport =		p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_fport);
219 	tcps_laddr =		p == NULL ? "<unknown>" :
220 	    p->t_inpcb.inp_vflag == INP_IPV4 ?
221 	    inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id46_addr.ia46_addr4.s_addr) :
222 	    inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id6_addr);
223 	tcps_raddr =		p == NULL ? "<unknown>" :
224 	    p->t_inpcb.inp_vflag == INP_IPV4 ?
225 	    inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id46_addr.ia46_addr4.s_addr) :
226 	    inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id6_addr);
227 	tcps_state =		p == NULL ? -1 : p->t_state;
228 	tcps_iss =		p == NULL ? 0  : p->iss;
229 	tcps_irs =		p == NULL ? 0  : p->irs;
230 	tcps_suna =		p == NULL ? 0  : p->snd_una;
231 	tcps_smax =		p == NULL ? 0  : p->snd_max;
232 	tcps_snxt =		p == NULL ? 0  : p->snd_nxt;
233 	tcps_rack =		p == NULL ? 0  : p->last_ack_sent;
234 	tcps_rnxt =		p == NULL ? 0  : p->rcv_nxt;
235 	tcps_swnd =		p == NULL ? -1 : p->snd_wnd;
236 	tcps_snd_ws =		p == NULL ? -1 : p->snd_scale;
237 	tcps_swl1 =		p == NULL ? -1 : p->snd_wl1;
238 	tcps_swl2 = 		p == NULL ? -1 : p->snd_wl2;
239 	tcps_radv =		p == NULL ? -1 : p->rcv_adv;
240 	tcps_rwnd =		p == NULL ? -1 : p->rcv_wnd;
241 	tcps_rup =		p == NULL ? -1 : p->rcv_up;
242 	tcps_rcv_ws =		p == NULL ? -1 : p->rcv_scale;
243 	tcps_cwnd =		p == NULL ? -1 : p->snd_cwnd;
244 	tcps_cwnd_ssthresh =	p == NULL ? -1 : p->snd_ssthresh;
245 	tcps_srecover =		p == NULL ? -1 : p->snd_recover;
246 	tcps_sack_fack =	p == NULL ? 0  : p->snd_fack;
247 	tcps_sack_snxt =	p == NULL ? 0  : p->snd_recover;
248 	tcps_rto =		p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz;
249 	tcps_mss =		p == NULL ? -1 : p->t_maxseg;
250 	tcps_retransmit =	p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0;
251 	tcps_srtt =		p == NULL ? -1 : p->t_srtt;   /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
252 	tcps_debug =		p == NULL ? 0 :
253 	    p->t_inpcb.inp_socket->so_options & 1;
254 	tcps_cookie =		p == NULL ? -1 :
255 	    p->t_inpcb.inp_socket->so_user_cookie;
256 	tcps_dupacks =		p == NULL ? -1 : p->t_dupacks;
257 	tcps_rtttime =		p == NULL ? -1 : p->t_rtttime;
258 	tcps_rtseq =		p == NULL ? -1 : p->t_rtseq;
259 	tcps_ts_recent =	p == NULL ? -1 : p->ts_recent;
260 };
261 
262 #pragma D binding "1.6.3" translator
263 translator tcpinfo_t < struct tcphdr *p > {
264 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
265 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
266 	tcp_seq =	p == NULL ? -1 : ntohl(p->th_seq);
267 	tcp_ack =	p == NULL ? -1 : ntohl(p->th_ack);
268 	tcp_offset =	p == NULL ? -1 : (p->th_off << 2);
269 	tcp_flags =	p == NULL ? 0  : ((p->th_x2 << 8) | p->th_flags);
270 	tcp_window =	p == NULL ? 0  : ntohs(p->th_win);
271 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
272 	tcp_urgent =	p == NULL ? 0  : ntohs(p->th_urp);
273 	tcp_hdr =	(struct tcphdr *)p;
274 };
275 
276 /*
277  * This translator differs from the one for tcpinfo_t in that the sequence
278  * number, acknowledgement number, window size and urgent pointer are already
279  * in host order and thus don't need to be converted.
280  */
281 #pragma D binding "1.6.3" translator
282 translator tcpinfoh_t < struct tcphdr *p > {
283 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
284 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
285 	tcp_seq =	p == NULL ? -1 : p->th_seq;
286 	tcp_ack =	p == NULL ? -1 : p->th_ack;
287 	tcp_offset =	p == NULL ? -1 : (p->th_off << 2);
288 	tcp_flags =	p == NULL ? 0  : ((p->th_x2 << 8) | p->th_flags);
289 	tcp_window =	p == NULL ? 0  : p->th_win;
290 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
291 	tcp_urgent =	p == NULL ? 0  : p->th_urp;
292 	tcp_hdr =	(struct tcphdr *)p;
293 };
294 
295 #pragma D binding "1.6.3" translator
296 translator tcplsinfo_t < int s > {
297 	tcps_state =	s;
298 };
299 
300 
301 /* Support for TCP debug */
302 
303 #pragma D binding "1.12.1" TA_INPUT
304 inline int TA_INPUT =	0;
305 #pragma D binding "1.12.1" TA_OUTPUT
306 inline int TA_OUTPUT =	1;
307 #pragma D binding "1.12.1" TA_USER
308 inline int TA_USER =	2;
309 #pragma D binding "1.12.1" TA_RESPOND
310 inline int TA_RESPOND =	3;
311 #pragma D binding "1.12.1" TA_DROP
312 inline int TA_DROP =	4;
313 
314 /* direction strings. */
315 
316 #pragma D binding "1.13" tcpdebug_dir_string
317 inline string tcpdebug_dir_string[uint8_t direction] =
318 	direction == TA_INPUT ?	"input" :
319 	direction == TA_OUTPUT ? "output" :
320 	direction == TA_USER ? "user" :
321 	direction == TA_RESPOND ? "respond" :
322 	direction == TA_DROP ? "drop" :
323 	"unknown" ;
324 
325 #pragma D binding "1.13" tcpflag_string
326 inline string tcpflag_string[uint16_t flags] =
327 	flags & TH_FIN ?	"FIN" :
328 	flags & TH_SYN ?	"SYN" :
329 	flags & TH_RST ?	"RST" :
330 	flags & TH_PUSH ?	"PUSH" :
331 	flags & TH_ACK ?	"ACK" :
332 	flags & TH_URG ?	"URG" :
333 	flags & TH_ECE ?	"ECE" :
334 	flags & TH_CWR ?	"CWR" :
335 	flags & TH_AE ? 	"AE" :
336 	"unknown" ;
337 
338 #pragma D binding "1.12.1" PRU_ATTACH
339 inline int PRU_ATTACH		= 0;
340 #pragma D binding "1.12.1" PRU_DETACH
341 inline int PRU_DETACH		= 1;
342 #pragma D binding "1.12.1" PRU_BIND
343 inline int PRU_BIND		= 2;
344 #pragma D binding "1.12.1" PRU_LISTEN
345 inline int PRU_LISTEN		= 3;
346 #pragma D binding "1.12.1" PRU_CONNECT
347 inline int PRU_CONNECT		= 4;
348 #pragma D binding "1.12.1" PRU_ACCEPT
349 inline int PRU_ACCEPT		= 5 ;
350 #pragma D binding "1.12.1" PRU_DISCONNECT
351 inline int PRU_DISCONNECT	= 6;
352 #pragma D binding "1.12.1" PRU_SHUTDOWN
353 inline int PRU_SHUTDOWN		= 7;
354 #pragma D binding "1.12.1" PRU_RCVD
355 inline int PRU_RCVD		= 8;
356 #pragma D binding "1.12.1" PRU_SEND
357 inline int PRU_SEND		= 9;
358 #pragma D binding "1.12.1" PRU_ABORT
359 inline int PRU_ABORT		= 10;
360 #pragma D binding "1.12.1" PRU_CONTROL
361 inline int PRU_CONTROL		= 11;
362 #pragma D binding "1.12.1" PRU_SENSE
363 inline int PRU_SENSE		= 12;
364 #pragma D binding "1.12.1" PRU_RCVOOB
365 inline int PRU_RCVOOB		= 13;
366 #pragma D binding "1.12.1" PRU_SENDOOB
367 inline int PRU_SENDOOB		= 14;
368 #pragma D binding "1.12.1" PRU_SOCKADDR
369 inline int PRU_SOCKADDR		= 15;
370 #pragma D binding "1.12.1" PRU_PEERADDR
371 inline int PRU_PEERADDR		= 16;
372 #pragma D binding "1.12.1" PRU_CONNECT2
373 inline int PRU_CONNECT2		= 17;
374 #pragma D binding "1.12.1" PRU_FASTTIMO
375 inline int PRU_FASTTIMO		= 18;
376 #pragma D binding "1.12.1" PRU_SLOWTIMO
377 inline int PRU_SLOWTIMO		= 19;
378 #pragma D binding "1.12.1" PRU_PROTORCV
379 inline int PRU_PROTORCV		= 20;
380 #pragma D binding "1.12.1" PRU_PROTOSEND
381 inline int PRU_PROTOSEND	= 21;
382 #pragma D binding "1.12.1" PRU_SEND_EOF
383 inline int PRU_SEND_EOF		= 22;
384 #pragma D binding "1.12.1" PRU_SOSETLABEL
385 inline int PRU_SOSETLABEL	= 23;
386 #pragma D binding "1.12.1" PRU_CLOSE
387 inline int PRU_CLOSE		= 24;
388 #pragma D binding "1.12.1" PRU_FLUSH
389 inline int PRU_FLUSH		= 25;
390 
391 #pragma D binding "1.12.1" prureq_string
392 inline string prureq_string[uint8_t req] =
393 	req == PRU_ATTACH ?	"ATTACH" :
394 	req == PRU_DETACH ?	"DETACH" :
395 	req == PRU_BIND ?	"BIND" :
396 	req == PRU_LISTEN ?	"LISTEN" :
397 	req == PRU_CONNECT ?	"CONNECT" :
398 	req == PRU_ACCEPT ?	"ACCEPT" :
399 	req == PRU_DISCONNECT ?	"DISCONNECT" :
400 	req == PRU_SHUTDOWN ?	"SHUTDOWN" :
401 	req == PRU_RCVD ?	"RCVD" :
402 	req == PRU_SEND ?	"SEND" :
403 	req == PRU_ABORT ?	"ABORT" :
404 	req == PRU_CONTROL ?	"CONTROL" :
405 	req == PRU_SENSE ?	"SENSE" :
406 	req == PRU_RCVOOB ?	"RCVOOB" :
407 	req == PRU_SENDOOB ?	"SENDOOB" :
408 	req == PRU_SOCKADDR ?	"SOCKADDR" :
409 	req == PRU_PEERADDR ?	"PEERADDR" :
410 	req == PRU_CONNECT2 ?	"CONNECT2" :
411 	req == PRU_FASTTIMO ?	"FASTTIMO" :
412 	req == PRU_SLOWTIMO ?	"SLOWTIMO" :
413 	req == PRU_PROTORCV ?	"PROTORCV" :
414 	req == PRU_PROTOSEND ?	"PROTOSEND" :
415 	req == PRU_SEND ?	"SEND_EOF" :
416 	req == PRU_SOSETLABEL ?	"SOSETLABEL" :
417 	req == PRU_CLOSE ?	"CLOSE" :
418 	req == PRU_FLUSH ?	"FLUSE" :
419 	"unknown" ;
420