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