xref: /freebsd/cddl/usr.sbin/dwatch/libexec/tcp (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
1 # -*- tab-width: 4 -*- ;; Emacs
2 # vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM
3 ############################################################ IDENT(1)
4 #
5 # $Title: dwatch(8) module for dtrace_tcp(4) connections $
6 # $Copyright: 2014-2018 Devin Teske. All rights reserved. $
7 #
8 ############################################################ DESCRIPTION
9 #
10 # Display local/remote TCP addresses/ports and bytes sent/received for TCP I/O
11 #
12 ############################################################ PROBE
13 
14 case "$PROFILE" in
15 tcp)
16 	: ${PROBE:=$( echo \
17 		tcp:::accept-established, \
18 		tcp:::accept-refused, \
19 		tcp:::connect-established, \
20 		tcp:::connect-refused, \
21 		tcp:::connect-request, \
22 		tcp:::receive, \
23 		tcp:::send, \
24 		tcp:::state-change )} ;;
25 tcp-accept)
26 	: ${PROBE:=tcp:::accept-established, tcp:::accept-refused} ;;
27 tcp-connect)
28 	: ${PROBE:=$( echo \
29 		tcp:::connect-established, \
30 		tcp:::connect-refused, \
31 		tcp:::connect-request )} ;;
32 tcp-established)
33 	: ${PROBE:=tcp:::accept-established, tcp:::connect-established} ;;
34 tcp-init)
35 	: ${PROBE:=$( echo \
36 		tcp:::accept-established, \
37 		tcp:::accept-refused, \
38 		tcp:::connect-established, \
39 		tcp:::connect-refused, \
40 		tcp:::connect-request )} ;;
41 tcp-io)
42 	: ${PROBE:=tcp:::send, tcp:::receive} ;;
43 tcp-refused)
44 	: ${PROBE:=tcp:::accept-refused, tcp:::connect-refused} ;;
45 tcp-status)
46 	: ${PROBE:=$( echo \
47 		tcp:::accept-established, \
48 		tcp:::accept-refused, \
49 		tcp:::connect-established, \
50 		tcp:::connect-refused, \
51 		tcp:::connect-request, \
52 		tcp:::state-change )} ;;
53 *)
54 	: ${PROBE:=tcp:::${PROFILE#tcp-}}
55 esac
56 
57 ############################################################ ACTIONS
58 
59 exec 9<<EOF
60 this int32_t	from_state;
61 this int32_t	to_state;
62 this string	details;
63 this string	flow;
64 this string	local;
65 this string	remote;
66 this u_char	local6;
67 this u_char	remote6;
68 this u_char	slocal;
69 this uint16_t	lport;
70 this uint16_t	rport;
71 this uint32_t	length;
72 
73 inline string probeflow[string name] =
74 	name == "accept-established" ?	"<-" :
75 	name == "accept-refused" ?	"X-" :
76 	name == "connect-refused" ?	"-X" :
77 	name == "connect-request" ?	"-?" :
78 	name == "receive" ?		"<-" :
79 	"->";
80 
81 inline u_char srclocal[string name] =
82 	name == "accept-refused" ?	1 :
83 	name == "connect-request" ?	1 :
84 	name == "send" ?		1 :
85 	0;
86 
87 /*
88  * TCPSTATES from <sys/netinet/tcp_fsm.h> used by netstat(1)
89  */
90 inline string tcpstate[int32_t state] =
91         state == TCPS_CLOSED ?		"CLOSED" :
92         state == TCPS_LISTEN ?		"LISTEN" :
93         state == TCPS_SYN_SENT ?	"SYN_SENT" :
94         state == TCPS_SYN_RECEIVED ?	"SYN_RCVD" :
95         state == TCPS_ESTABLISHED ?	"ESTABLISHED" :
96         state == TCPS_CLOSE_WAIT ?	"CLOSE_WAIT" :
97         state == TCPS_FIN_WAIT_1 ?	"FIN_WAIT_1" :
98         state == TCPS_CLOSING ?		"CLOSING" :
99         state == TCPS_LAST_ACK ?	"LAST_ACK" :
100         state == TCPS_FIN_WAIT_2 ?	"FIN_WAIT_2" :
101         state == TCPS_TIME_WAIT ?	"TIME_WAIT" :
102         strjoin("UNKNOWN(", strjoin(lltostr(state), ")"));
103 
104 $PROBE /* probe ID $ID */
105 {${TRACE:+
106 	printf("<$ID>");}
107 	this->details = "";
108 
109 	/*
110 	 * dtrace_tcp(4)
111 	 */
112 	this->flow = probeflow[probename];
113 }
114 
115 tcp:::accept-established,
116 tcp:::accept-refused,
117 tcp:::connect-established,
118 tcp:::connect-refused,
119 tcp:::connect-request,
120 tcp:::receive,
121 tcp:::send /* probe ID $(( $ID + 1 )) */
122 {${TRACE:+
123 	printf("<$(( $ID + 1 ))>");
124 }
125 	/*
126 	 * dtrace_tcp(4)
127 	 */
128 	this->slocal = srclocal[probename];
129 
130 	/*
131 	 * ipinfo_t *
132 	 */
133 	this->local  = this->slocal ? args[2]->ip_saddr : args[2]->ip_daddr;
134 	this->remote = this->slocal ? args[2]->ip_daddr : args[2]->ip_saddr;
135 
136 	/*
137 	 * tcpinfo_t *
138 	 */
139 	this->lport = this->slocal ? args[4]->tcp_sport : args[4]->tcp_dport;
140 	this->rport = this->slocal ? args[4]->tcp_dport : args[4]->tcp_sport;
141 
142 	/*
143 	 * IPv6 support
144 	 */
145 	this->local6 = strstr(this->local, ":") != NULL ? 1 : 0;
146 	this->remote6 = strstr(this->remote, ":") != NULL ? 1 : 0;
147 	this->local = strjoin(strjoin(this->local6 ? "[" : "",
148 		this->local), this->local6 ? "]" : "");
149 	this->remote = strjoin(strjoin(this->remote6 ? "[" : "",
150 		this->remote), this->remote6 ? "]" : "");
151 }
152 
153 tcp:::state-change /* probe ID $(( $ID + 2 )) */
154 {${TRACE:+
155 	printf("<$(( $ID + 2 ))>");
156 }
157 	/*
158 	 * tcpsinfo_t *
159 	 */
160 	this->local    = args[3]->tcps_laddr;
161 	this->lport    = (uint16_t)args[3]->tcps_lport;
162 	this->remote   = args[3]->tcps_raddr;
163 	this->rport    = (uint16_t)args[3]->tcps_rport;
164 	this->to_state = (int32_t)args[3]->tcps_state;
165 
166 	/*
167 	 * tcplsinfo_t *
168 	 */
169 	this->from_state = (int32_t)args[5]->tcps_state;
170 
171 	/* flow = "[from state]->[to state]" */
172 	this->flow = strjoin(tcpstate[this->from_state],
173 		strjoin("->", tcpstate[this->to_state]));
174 }
175 
176 tcp:::send, tcp:::receive /* pribe ID $(( $ID + 3 )) */
177 {${TRACE:+
178 	printf("<$(( $ID + 3 ))>");}
179 	this->length = (uint32_t)args[2]->ip_plength -
180 		(uint8_t)args[4]->tcp_offset;
181 
182 	/* details = " <length> byte<s>" */
183 	this->details = strjoin(
184 		strjoin(" ", lltostr(this->length)),
185 		strjoin(" byte", this->length == 1 ? "" : "s"));
186 }
187 EOF
188 ACTIONS=$( cat <&9 )
189 ID=$(( $ID + 4 ))
190 
191 ############################################################ EVENT DETAILS
192 
193 if [ ! "$CUSTOM_DETAILS" ]; then
194 exec 9<<EOF
195 	/*
196 	 * Print details
197 	 */
198 	printf("%s:%u %s %s:%u%s",
199 		this->local, this->lport,
200 		this->flow,
201 		this->remote, this->rport,
202 		this->details);
203 EOF
204 EVENT_DETAILS=$( cat <&9 )
205 fi
206 
207 ################################################################################
208 # END
209 ################################################################################
210