# -*- tab-width: 4 -*- ;; Emacs
# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM
############################################################ IDENT(1)
#
# $Title: dwatch(8) module for dtrace_tcp(4) connections $
# $Copyright: 2014-2018 Devin Teske. All rights reserved. $
#
############################################################ DESCRIPTION
#
# Display local/remote TCP addresses/ports and bytes sent/received for TCP I/O
#
############################################################ PROBE
case "$PROFILE" in
tcp)
: ${PROBE:=$( echo \
tcp:::accept-established, \
tcp:::accept-refused, \
tcp:::connect-established, \
tcp:::connect-refused, \
tcp:::connect-request, \
tcp:::receive, \
tcp:::send, \
tcp:::state-change )} ;;
tcp-accept)
: ${PROBE:=tcp:::accept-established, tcp:::accept-refused} ;;
tcp-connect)
: ${PROBE:=$( echo \
tcp:::connect-established, \
tcp:::connect-refused, \
tcp:::connect-request )} ;;
tcp-established)
: ${PROBE:=tcp:::accept-established, tcp:::connect-established} ;;
tcp-init)
: ${PROBE:=$( echo \
tcp:::accept-established, \
tcp:::accept-refused, \
tcp:::connect-established, \
tcp:::connect-refused, \
tcp:::connect-request )} ;;
tcp-io)
: ${PROBE:=tcp:::send, tcp:::receive} ;;
tcp-refused)
: ${PROBE:=tcp:::accept-refused, tcp:::connect-refused} ;;
tcp-status)
: ${PROBE:=$( echo \
tcp:::accept-established, \
tcp:::accept-refused, \
tcp:::connect-established, \
tcp:::connect-refused, \
tcp:::connect-request, \
tcp:::state-change )} ;;
*)
: ${PROBE:=tcp:::${PROFILE#tcp-}}
esac
############################################################ ACTIONS
exec 9<<EOF
this int32_t from_state;
this int32_t to_state;
this string details;
this string flow;
this string local;
this string remote;
this u_char local6;
this u_char remote6;
this u_char slocal;
this uint16_t lport;
this uint16_t rport;
this uint32_t length;
inline string probeflow[string name] =
name == "accept-established" ? "<-" :
name == "accept-refused" ? "X-" :
name == "connect-refused" ? "-X" :
name == "connect-request" ? "-?" :
name == "receive" ? "<-" :
"->";
inline u_char srclocal[string name] =
name == "accept-refused" ? 1 :
name == "connect-request" ? 1 :
name == "send" ? 1 :
0;
/*
* TCPSTATES from <sys/netinet/tcp_fsm.h> used by netstat(1)
*/
inline string tcpstate[int32_t state] =
state == TCPS_CLOSED ? "CLOSED" :
state == TCPS_LISTEN ? "LISTEN" :
state == TCPS_SYN_SENT ? "SYN_SENT" :
state == TCPS_SYN_RECEIVED ? "SYN_RCVD" :
state == TCPS_ESTABLISHED ? "ESTABLISHED" :
state == TCPS_CLOSE_WAIT ? "CLOSE_WAIT" :
state == TCPS_FIN_WAIT_1 ? "FIN_WAIT_1" :
state == TCPS_CLOSING ? "CLOSING" :
state == TCPS_LAST_ACK ? "LAST_ACK" :
state == TCPS_FIN_WAIT_2 ? "FIN_WAIT_2" :
state == TCPS_TIME_WAIT ? "TIME_WAIT" :
strjoin("UNKNOWN(", strjoin(lltostr(state), ")"));
$PROBE /* probe ID $ID */
{${TRACE:+
printf("<$ID>");}
this->details = "";
/*
* dtrace_tcp(4)
*/
this->flow = probeflow[probename];
}
tcp:::accept-established,
tcp:::accept-refused,
tcp:::connect-established,
tcp:::connect-refused,
tcp:::connect-request,
tcp:::receive,
tcp:::send /* probe ID $(( $ID + 1 )) */
{${TRACE:+
printf("<$(( $ID + 1 ))>");
}
/*
* dtrace_tcp(4)
*/
this->slocal = srclocal[probename];
/*
* ipinfo_t *
*/
this->local = this->slocal ? args[2]->ip_saddr : args[2]->ip_daddr;
this->remote = this->slocal ? args[2]->ip_daddr : args[2]->ip_saddr;
/*
* tcpinfo_t *
*/
this->lport = this->slocal ? args[4]->tcp_sport : args[4]->tcp_dport;
this->rport = this->slocal ? args[4]->tcp_dport : args[4]->tcp_sport;
/*
* IPv6 support
*/
this->local6 = strstr(this->local, ":") != NULL ? 1 : 0;
this->remote6 = strstr(this->remote, ":") != NULL ? 1 : 0;
this->local = strjoin(strjoin(this->local6 ? "[" : "",
this->local), this->local6 ? "]" : "");
this->remote = strjoin(strjoin(this->remote6 ? "[" : "",
this->remote), this->remote6 ? "]" : "");
}
tcp:::state-change /* probe ID $(( $ID + 2 )) */
{${TRACE:+
printf("<$(( $ID + 2 ))>");
}
/*
* tcpsinfo_t *
*/
this->local = args[3]->tcps_laddr;
this->lport = (uint16_t)args[3]->tcps_lport;
this->remote = args[3]->tcps_raddr;
this->rport = (uint16_t)args[3]->tcps_rport;
this->to_state = (int32_t)args[3]->tcps_state;
/*
* tcplsinfo_t *
*/
this->from_state = (int32_t)args[5]->tcps_state;
/* flow = "[from state]->[to state]" */
this->flow = strjoin(tcpstate[this->from_state],
strjoin("->", tcpstate[this->to_state]));
}
tcp:::send, tcp:::receive /* pribe ID $(( $ID + 3 )) */
{${TRACE:+
printf("<$(( $ID + 3 ))>");}
this->length = (uint32_t)args[2]->ip_plength -
(uint8_t)args[4]->tcp_offset;
/* details = " <length> byte<s>" */
this->details = strjoin(
strjoin(" ", lltostr(this->length)),
strjoin(" byte", this->length == 1 ? "" : "s"));
}
EOF
ACTIONS=$( cat <&9 )
ID=$(( $ID + 4 ))
############################################################ EVENT DETAILS
if [ ! "$CUSTOM_DETAILS" ]; then
exec 9<<EOF
/*
* Print details
*/
printf("%s:%u %s %s:%u%s",
this->local, this->lport,
this->flow,
this->remote, this->rport,
this->details);
EOF
EVENT_DETAILS=$( cat <&9 )
fi
################################################################################
# END
################################################################################