# -*- tab-width: 4 -*- ;; Emacs # vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM ############################################################ IDENT(1) # # $Title: dwatch(8) module for send(2)/recv(2) $ # $Copyright: 2014-2018 Devin Teske. All rights reserved. $ # ############################################################ DESCRIPTION # # Print details from send(2)/recv(2) # ############################################################ PROBE case "$PROFILE" in sendrecv) : ${PROBE:=$( echo \ syscall::recvfrom:return, \ syscall::recvmsg:return, \ syscall::sendmsg:entry, \ syscall::sendto:entry )} ;; send) : ${PROBE:=$( echo \ syscall::sendmsg:entry, \ syscall::sendto:entry )} ;; recv) : ${PROBE:=$( echo \ syscall::recvfrom:return, \ syscall::recvmsg:return )} ;; recv*) : ${PROBE:=syscall::$PROFILE:return} ;; *) : ${PROBE:=syscall::$PROFILE:entry} esac ############################################################ EVENT ACTION #[ "$CUSTOM_TEST" ] || EVENT_TEST="this->from != NULL" ############################################################ ACTIONS exec 9< */ #pragma D binding "1.13" address_family_string inline string address_family_string[sa_family_t af] = af == AF_UNSPEC ? "AF_UNSPEC" : af == AF_LOCAL ? "AF_UNIX" : af == AF_UNIX ? "AF_UNIX" : af == AF_INET ? "AF_INET" : af == AF_IMPLINK ? "AF_IMPLINK" : af == AF_PUP ? "AF_PUP" : af == AF_CHAOS ? "AF_CHAOS" : af == AF_NETBIOS ? "AF_NETBIOS" : af == AF_ISO ? "AF_ISO" : af == AF_OSI ? "AF_ISO" : af == AF_ECMA ? "AF_ECMA" : af == AF_DATAKIT ? "AF_DATAKIT" : af == AF_CCITT ? "AF_CCITT" : af == AF_SNA ? "AF_SNA" : af == AF_DECnet ? "AF_DECnet" : af == AF_DLI ? "AF_DLI" : af == AF_LAT ? "AF_LAT" : af == AF_HYLINK ? "AF_HYLINK" : af == AF_APPLETALK ? "AF_APPLETALK" : af == AF_ROUTE ? "AF_ROUTE" : af == AF_LINK ? "AF_LINK" : af == pseudo_AF_XTP ? "pseudo_AF_XTP" : af == AF_COIP ? "AF_COIP" : af == AF_CNT ? "AF_CNT" : af == pseudo_AF_RTIP ? "pseudo_AF_RTIP" : af == AF_IPX ? "AF_IPX" : af == AF_SIP ? "AF_SIP" : af == pseudo_AF_PIP ? "pseudo_AF_PIP" : af == AF_ISDN ? "AF_ISDN" : af == AF_E164 ? "AF_ISDN" : af == pseudo_AF_KEY ? "pseudo_AF_KEY" : af == AF_INET6 ? "AF_INET6" : af == AF_NATM ? "AF_NATM" : af == AF_ATM ? "AF_ATM" : af == pseudo_AF_HDRCMPLT ? "pseudo_AF_HDRCMPLT" : af == AF_NETGRAPH ? "AF_NETGRAPH" : af == AF_SLOW ? "AF_SLOW" : af == AF_SCLUSTER ? "AF_SCLUSTER" : af == AF_ARP ? "AF_ARP" : af == AF_BLUETOOTH ? "AF_BLUETOOTH" : af == AF_IEEE80211 ? "AF_IEEE80211" : af == AF_INET_SDP ? "AF_INET_SDP" : af == AF_INET6_SDP ? "AF_INET6_SDP" : af == AF_MAX ? "AF_MAX" : strjoin("AF_UNKNOWN(", strjoin(lltostr(af), ")")); #pragma D binding "1.13" sa_data_size inline int sa_data_size = 14; #pragma D binding "1.13" sa_dummy_data inline char *sa_dummy_data = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; #pragma D binding "1.13" sa_data_addr inline string sa_data_addr[sa_family_t af, char data[sa_data_size]] = af == AF_INET ? strjoin( strjoin(strjoin(lltostr(data[2] & 0xFF), "."), strjoin(lltostr(data[3] & 0xFF), ".") ), strjoin(strjoin(lltostr(data[4] & 0xFF), "."), lltostr(data[5] & 0xFF)) ) : ""; #pragma D binding "1.13" sa_data_port inline uint16_t sa_data_port[sa_family_t af, char data[sa_data_size]] = af == AF_INET ? (data[0] << 8) + data[1] : 0; #pragma D binding "1.13" translator translator sainfo_t < struct sockaddr *SA > { sa_family = SA == NULL ? 0 : SA->sa_family; family = address_family_string[SA == NULL ? 0 : SA->sa_family]; addr = SA == NULL ? sa_data_addr[0, sa_dummy_data] : sa_data_addr[SA->sa_family, SA->sa_data]; port = SA == NULL ? sa_data_port[0, sa_dummy_data] : sa_data_port[SA->sa_family, SA->sa_data]; }; this sainfo_t sainfo; this ssize_t nbytes; this string details; this string flow; this struct msghdr * msghdr; this struct sockaddr * sa; inline string probeflow[string func] = func == "recvfrom" ? "<-" : func == "recvmsg" ? "<-" : func == "recvmmsg" ? "<-" : "->"; inline string af_details[sa_family_t af, string addr, uint16_t port] = af == AF_INET ? strjoin(addr, strjoin(":", lltostr(port))) : ""; $PROBE /* probe ID $ID */ {${TRACE:+ printf("<$ID>");} this->details = ""; this->flow = probeflow[probefunc]; } syscall::recvfrom:entry /* probe ID $(( $ID + 1 )) */ {${TRACE:+ printf("<$(( $ID + 1 ))>");} this->sainfo = xlate ((struct sockaddr *)(args[4] == NULL ? NULL : copyin(arg4, sizeof(struct sockaddr)))); } syscall::recvfrom:return /* probe ID $(( $ID + 2 )) */ {${TRACE:+ printf("<$(( $ID + 2 ))>");} this->nbytes = arg0; this->details = strjoin("from ", strjoin( strjoin(this->sainfo.family, " "), af_details[this->sainfo.sa_family, this->sainfo.addr, this->sainfo.port])); } syscall::recvmsg:entry /* probe ID $(( $ID + 3 )) */ {${TRACE:+ printf("<$(( $ID + 3 ))>");} this->sockaddr = (struct sockaddr *)arg1; } syscall::recvmsg:return /this->sockaddr != NULL/ /* probe ID $(( $ID + 4 )) */ {${TRACE:+ printf("<$(( $ID + 4 ))>");} this->nbytes = arg0; this->sainfo = xlate ((struct sockaddr *)this->sockaddr); this->details = strjoin("sainfo=[", "]"); } syscall::sendmsg:entry /* probe ID $(( $ID + 5 )) */ {${TRACE:+ printf("<$(( $ID + 5 ))>");} this->nbytes = arg2; } syscall::sendto:entry /* probe ID $(( $ID + 6 )) */ {${TRACE:+ printf("<$(( $ID + 6 ))>");} this->nbytes = arg2; this->sainfo = xlate ((struct sockaddr *)(arg4 == NULL ? NULL : copyin(arg4, sizeof(struct sockaddr)))); this->details = strjoin("to ", strjoin( strjoin(this->sainfo.family, " "), af_details[this->sainfo.sa_family, this->sainfo.addr, this->sainfo.port])); } EOF ACTIONS=$( cat <&9 ) ID=$(( $ID + 7 )) ############################################################ EVENT DETAILS if [ ! "$CUSTOM_DETAILS" ]; then exec 9<flow, this->nbytes, this->nbytes != 1 ? "s" : "", this->details != "" ? " " : "", this->details); EOF EVENT_DETAILS=$( cat <&9 ) fi ################################################################################ # END ################################################################################