xref: /freebsd/cddl/usr.sbin/dwatch/libexec/sendrecv (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 send(2)/recv(2) $
6# $Copyright: 2014-2018 Devin Teske. All rights reserved. $
7#
8############################################################ DESCRIPTION
9#
10# Print details from send(2)/recv(2)
11#
12############################################################ PROBE
13
14case "$PROFILE" in
15sendrecv)
16	: ${PROBE:=$( echo \
17		syscall::recvfrom:return, \
18		syscall::recvmsg:return, \
19		syscall::sendmsg:entry, \
20		syscall::sendto:entry )} ;;
21send)
22	: ${PROBE:=$( echo \
23		syscall::sendmsg:entry, \
24		syscall::sendto:entry )} ;;
25recv)
26	: ${PROBE:=$( echo \
27		syscall::recvfrom:return, \
28		syscall::recvmsg:return )} ;;
29recv*)
30	: ${PROBE:=syscall::$PROFILE:return} ;;
31*)
32	: ${PROBE:=syscall::$PROFILE:entry}
33esac
34
35############################################################ EVENT ACTION
36
37#[ "$CUSTOM_TEST" ] || EVENT_TEST="this->from != NULL"
38
39############################################################ ACTIONS
40
41exec 9<<EOF
42typedef struct sainfo {
43	sa_family_t sa_family;
44	uint16_t port;
45	string addr;
46	string family;
47} sainfo_t;
48
49/*
50 * Address families from <sys/socket.h>
51 */
52#pragma D binding "1.13" address_family_string
53inline string address_family_string[sa_family_t af] =
54	af == AF_UNSPEC ?		"AF_UNSPEC" :
55	af == AF_LOCAL ?		"AF_UNIX" :
56	af == AF_UNIX ?			"AF_UNIX" :
57	af == AF_INET ?			"AF_INET" :
58	af == AF_IMPLINK ?		"AF_IMPLINK" :
59	af == AF_PUP ?			"AF_PUP" :
60	af == AF_CHAOS ?		"AF_CHAOS" :
61	af == AF_NETBIOS ?		"AF_NETBIOS" :
62	af == AF_ISO ?			"AF_ISO" :
63	af == AF_OSI ?			"AF_ISO" :
64	af == AF_ECMA ?			"AF_ECMA" :
65	af == AF_DATAKIT ?		"AF_DATAKIT" :
66	af == AF_CCITT ?		"AF_CCITT" :
67	af == AF_SNA ?			"AF_SNA" :
68	af == AF_DECnet ?		"AF_DECnet" :
69	af == AF_DLI ?			"AF_DLI" :
70	af == AF_LAT ?			"AF_LAT" :
71	af == AF_HYLINK ?		"AF_HYLINK" :
72	af == AF_APPLETALK ?		"AF_APPLETALK" :
73	af == AF_ROUTE ?		"AF_ROUTE" :
74	af == AF_LINK ?			"AF_LINK" :
75	af == pseudo_AF_XTP ?		"pseudo_AF_XTP" :
76	af == AF_COIP ?			"AF_COIP" :
77	af == AF_CNT ?			"AF_CNT" :
78	af == pseudo_AF_RTIP ?		"pseudo_AF_RTIP" :
79	af == AF_IPX ?			"AF_IPX" :
80	af == AF_SIP ?			"AF_SIP" :
81	af == pseudo_AF_PIP ?		"pseudo_AF_PIP" :
82	af == AF_ISDN ?			"AF_ISDN" :
83	af == AF_E164 ?			"AF_ISDN" :
84	af == pseudo_AF_KEY ?		"pseudo_AF_KEY" :
85	af == AF_INET6 ?		"AF_INET6" :
86	af == AF_NATM ?			"AF_NATM" :
87	af == AF_ATM ?			"AF_ATM" :
88	af == pseudo_AF_HDRCMPLT ?	"pseudo_AF_HDRCMPLT" :
89	af == AF_NETGRAPH ?		"AF_NETGRAPH" :
90	af == AF_SLOW ?			"AF_SLOW" :
91	af == AF_SCLUSTER ?		"AF_SCLUSTER" :
92	af == AF_ARP ?			"AF_ARP" :
93	af == AF_BLUETOOTH ?		"AF_BLUETOOTH" :
94	af == AF_IEEE80211 ?		"AF_IEEE80211" :
95	af == AF_INET_SDP ?		"AF_INET_SDP" :
96	af == AF_INET6_SDP ?		"AF_INET6_SDP" :
97	af == AF_MAX ?			"AF_MAX" :
98	strjoin("AF_UNKNOWN(", strjoin(lltostr(af), ")"));
99
100#pragma D binding "1.13" sa_data_size
101inline int sa_data_size = 14;
102#pragma D binding "1.13" sa_dummy_data
103inline char *sa_dummy_data = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
104
105#pragma D binding "1.13" sa_data_addr
106inline string sa_data_addr[sa_family_t af, char data[sa_data_size]] =
107	af == AF_INET ? strjoin(
108		strjoin(strjoin(lltostr(data[2] & 0xFF), "."),
109			strjoin(lltostr(data[3] & 0xFF), ".")
110		),
111		strjoin(strjoin(lltostr(data[4] & 0xFF), "."),
112			lltostr(data[5] & 0xFF))
113	) :
114	"";
115
116#pragma D binding "1.13" sa_data_port
117inline uint16_t sa_data_port[sa_family_t af, char data[sa_data_size]] =
118	af == AF_INET ? (data[0] << 8) + data[1] :
119	0;
120
121#pragma D binding "1.13" translator
122translator sainfo_t < struct sockaddr *SA > {
123	sa_family =	SA == NULL ? 0 : SA->sa_family;
124	family =	address_family_string[SA == NULL ? 0 : SA->sa_family];
125	addr =		SA == NULL ?
126	    sa_data_addr[0, sa_dummy_data] :
127	    sa_data_addr[SA->sa_family, SA->sa_data];
128	port =		SA == NULL ?
129	    sa_data_port[0, sa_dummy_data] :
130	    sa_data_port[SA->sa_family, SA->sa_data];
131};
132
133this sainfo_t		sainfo;
134this ssize_t		nbytes;
135this string		details;
136this string		flow;
137this struct msghdr *	msghdr;
138this struct sockaddr *	sa;
139
140inline string probeflow[string func] =
141	func == "recvfrom" ?	"<-" :
142	func == "recvmsg" ?	"<-" :
143	func == "recvmmsg" ?	"<-" :
144	"->";
145
146inline string af_details[sa_family_t af, string addr, uint16_t port] =
147	af == AF_INET ? strjoin(addr, strjoin(":", lltostr(port))) :
148	"";
149
150$PROBE /* probe ID $ID */
151{${TRACE:+
152	printf("<$ID>");}
153	this->details = "";
154	this->flow = probeflow[probefunc];
155}
156
157syscall::recvfrom:entry /* probe ID $(( $ID + 1 )) */
158{${TRACE:+
159	printf("<$(( $ID + 1 ))>");}
160	this->sainfo = xlate <sainfo_t> ((struct sockaddr *)(args[4] == NULL ?
161		NULL : copyin(arg4, sizeof(struct sockaddr))));
162}
163
164syscall::recvfrom:return /* probe ID $(( $ID + 2 )) */
165{${TRACE:+
166	printf("<$(( $ID + 2 ))>");}
167	this->nbytes = arg0;
168	this->details = strjoin("from ", strjoin(
169		strjoin(this->sainfo.family, " "),
170		af_details[this->sainfo.sa_family,
171			this->sainfo.addr, this->sainfo.port]));
172}
173
174syscall::recvmsg:entry /* probe ID $(( $ID + 3 )) */
175{${TRACE:+
176	printf("<$(( $ID + 3 ))>");}
177	this->sockaddr = (struct sockaddr *)arg1;
178}
179
180syscall::recvmsg:return /this->sockaddr != NULL/ /* probe ID $(( $ID + 4 )) */
181{${TRACE:+
182	printf("<$(( $ID + 4 ))>");}
183	this->nbytes = arg0;
184	this->sainfo = xlate <sainfo_t> ((struct sockaddr *)this->sockaddr);
185	this->details = strjoin("sainfo=[", "]");
186}
187
188syscall::sendmsg:entry /* probe ID $(( $ID + 5 )) */
189{${TRACE:+
190	printf("<$(( $ID + 5 ))>");}
191	this->nbytes = arg2;
192}
193
194syscall::sendto:entry /* probe ID $(( $ID + 6 )) */
195{${TRACE:+
196	printf("<$(( $ID + 6 ))>");}
197	this->nbytes = arg2;
198	this->sainfo = xlate <sainfo_t> ((struct sockaddr *)(arg4 == NULL ?
199		NULL : copyin(arg4, sizeof(struct sockaddr))));
200	this->details = strjoin("to ", strjoin(
201		strjoin(this->sainfo.family, " "),
202		af_details[this->sainfo.sa_family,
203			this->sainfo.addr, this->sainfo.port]));
204}
205EOF
206ACTIONS=$( cat <&9 )
207ID=$(( $ID + 7 ))
208
209############################################################ EVENT DETAILS
210
211if [ ! "$CUSTOM_DETAILS" ]; then
212exec 9<<EOF
213	/*
214	 * Print socket details
215	 */
216	printf("%s %d byte%s%s%s",
217		this->flow,
218		this->nbytes,
219		this->nbytes != 1 ? "s" : "",
220		this->details != "" ? " " : "",
221		this->details);
222EOF
223EVENT_DETAILS=$( cat <&9 )
224fi
225
226################################################################################
227# END
228################################################################################
229