tcpio.d Reports TCP Packet Details
The following DTrace script traces TCP packets and prints various details:
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option switchrate=10hz
dtrace:::BEGIN
{
printf(" %3s %15s:%-5s %15s:%-5s %6s %s\n", "CPU",
"LADDR", "LPORT", "RADDR", "RPORT", "BYTES", "FLAGS");
}
tcp:::send
{
this->length = args[2]->ip_plength - args[4]->tcp_offset;
printf(" %3d %16s:%-5d -> %16s:%-5d %6d (", cpu,
args[2]->ip_saddr, args[4]->tcp_sport,
args[2]->ip_daddr, args[4]->tcp_dport, this->length);
}
tcp:::receive
{
this->length = args[2]->ip_plength - args[4]->tcp_offset;
printf(" %3d %16s:%-5d <- %16s:%-5d %6d (", cpu,
args[2]->ip_daddr, args[4]->tcp_dport,
args[2]->ip_saddr, args[4]->tcp_sport, this->length);
}
tcp:::send,
tcp:::receive
{
printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : "");
printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : "");
printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : "");
printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : "");
printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : "");
printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : "");
printf("%s", args[4]->tcp_flags & TH_ECE ? "ECE|" : "");
printf("%s", args[4]->tcp_flags & TH_CWR ? "CWR|" : "");
printf("%s", args[4]->tcp_flags == 0 ? "null " : "");
printf("\b)\n");
}This example output has captured a TCP handshake:
# ./tcpio.d
CPU LADDR:LPORT RADDR:RPORT BYTES FLAGS
1 192.0.2.8/27:22 -> 192.0.2.40/27:60337 464 (PUSH|ACK)
1 192.0.2.8/27:22 -> 192.0.2.40/27:60337 48 (PUSH|ACK)
2 192.0.2.8/27:22 -> 192.0.2.40/27:60337 20 (PUSH|ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 0 (SYN)
3 192.0.2.8/27:22 -> 192.0.2.40/27:60337 0 (SYN|ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 0 (ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 0 (ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 20 (PUSH|ACK)
3 192.0.2.8/27:22 -> 192.0.2.40/27:60337 0 (ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 0 (ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 376 (PUSH|ACK)
3 192.0.2.8/27:22 -> 192.0.2.40/27:60337 0 (ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 24 (PUSH|ACK)
2 192.0.2.8/27:22 -> 192.0.2.40/27:60337 736 (PUSH|ACK)
3 192.0.2.8/27:22 <- 192.0.2.40/27:60337 0 (ACK)The following table describes the output fields.
| Field | Description |
|---|---|
|
|
CPU id that event occurred on |
|
|
Local IP address |
|
|
Local TCP port |
|
|
Remote IP address |
|
|
Remote TCP port |
|
|
TCP payload bytes |
|
|
TCP flags |
Note:
The output may be shuffled slightly on multi-CPU servers due to DTrace per-CPU buffering, and events such as the TCP handshake can be printed out of order. Keep an eye on changes in the CPU column, or add a timestamp column to this script and post sort.