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