Skip to content

Instantly share code, notes, and snippets.

@jkstill
Last active April 17, 2024 07:03
Show Gist options
  • Star 79 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save jkstill/5095725 to your computer and use it in GitHub Desktop.
Save jkstill/5095725 to your computer and use it in GitHub Desktop.
decode entries in /proc/net/tcp
Decoding the data in /proc/net/tcp:
Linux 5.x /proc/net/tcp
Linux 6.x /proc/PID/net/tcp
Given a socket:
$ ls -l /proc/24784/fd/11
lrwx------ 1 jkstill dba 64 Dec 4 16:22 /proc/24784/fd/11 -> socket:[15907701]
Find the address
$ head -1 /proc/24784/net/tcp; grep 15907701 /proc/24784/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
46: 010310AC:9C4C 030310AC:1770 01 0100000150:00000000 01:00000019 00000000 1000 0 54165785 4 cd1e6040 25 4 27 3 -1
46: 010310AC:9C4C 030310AC:1770 01
| | | | | |--> connection state
| | | | |------> remote TCP port number
| | | |-------------> remote IPv4 address
| | |--------------------> local TCP port number
| |---------------------------> local IPv4 address
|----------------------------------> number of entry
00000150:00000000 01:00000019 00000000
| | | | |--> number of unrecovered RTO timeouts
| | | |----------> number of jiffies until timer expires
| | |----------------> timer_active (see below)
| |----------------------> receive-queue
|-------------------------------> transmit-queue
1000 0 54165785 4 cd1e6040 25 4 27 3 -1
| | | | | | | | | |--> slow start size threshold,
| | | | | | | | | or -1 if the treshold
| | | | | | | | | is >= 0xFFFF
| | | | | | | | |----> sending congestion window
| | | | | | | |-------> (ack.quick<<1)|ack.pingpong
| | | | | | |---------> Predicted tick of soft clock
| | | | | | (delayed ACK control data)
| | | | | |------------> retransmit timeout
| | | | |------------------> location of socket in memory
| | | |-----------------------> socket reference count
| | |-----------------------------> inode
| |----------------------------------> unanswered 0-window probes
|---------------------------------------------> uid
timer_active:
0 no timer is pending
1 retransmit-timer is pending
2 another timer (e.g. delayed ack or keepalive) is pending
3 this is a socket in TIME_WAIT state. Not all field will contain data.
4 zero window probe timer is pending
==========================================
Perl script to decode the address
#!/usr/bin/perl
my $hexip=$ARGV[0];
my $hexport=$ARGV[1];
print "hex: $hexip\n";
my @ip = map hex($_), ( $hexip =~ m/../g );
my $ip = join('.',reverse(@ip));
my $port = hex($hexport);
print "IP: $ip PORT: $port\n";
==========================================
$ hexip.pl 030310AC 1770
hex: 030310AC
IP: 172.16.3.3 PORT: 6000
@semeion
Copy link

semeion commented May 14, 2019

Nice info, btw, how to know if a connection is incomming or outgoing?

@lrbnew
Copy link

lrbnew commented Jan 3, 2020

cool.

@AmitIITR
Copy link

@semeion Please check for connection state. For Listening state is 0x0A. Please check for enums in file https://elixir.bootlin.com/linux/v4.14.42/source/include/net/tcp_states.h.

@jrhunger
Copy link

jrhunger commented Jun 3, 2022

@AmitIITR here is a derived script to parse the full output from /proc/net/tcp and print each line in readable format:

#!/usr/bin/perl
#
# ref https://elixir.bootlin.com/linux/v4.14.42/source/include/net/tcp_states.h
@tcpstates = (
  "DUMMY",
  "TCP_ESTABLISHED",  #1
  "TCP_SYN_SENT",     #2
  "TCP_SYN_RECV",     #3
  "TCP_FIN_WAIT1",    #4
  "TCP_FIN_WAIT2",    #5
  "TCP_TIME_WAIT",    #6
  "TCP_CLOSE",        #7
  "TCP_CLOSE_WAIT",   #8
  "TCP_LAST_ACK",     #9
  "TCP_LISTEN",       #10
  "TCP_CLOSING",      #11
  "TCP_NEW_SYN_RECV", #12
  "TCP_MAX_STATES,"   #13
);

sub ipport() {
  $_[0] =~ m/([0-9A-F]+):([0-9A-F]+)/;
  $hexip = $1; $hexport = $2;
  my @ip = map hex($_), ( $hexip =~ m/../g );
  my $ip = join('.',reverse(@ip));
  my $port = hex($hexport);
  return ($ip . ":" . $port);
}

while ($line = <>) {
  if ($line =~ /(^[ ]*[0-9]+: )([0-9A-F:]+) ([0-9A-F:]+) ([0-9A-F]+)(.*)/) {
    $head = $1;
    $loc = $2;
    $rem = $3;
    $stat = $4;
    $tail = $5;
    if (hex($stat) == 0) {
      print STDERR "hex($stat) is 0\n";
    }
    push @output, sprintf("%s%-21s %-21s %s %s\n", $head, &ipport($loc), &ipport($rem), $tcpstates[hex($stat)]);
  }
}

foreach $line (@output) {
  print $line;
}

@semeion
Copy link

semeion commented Jul 6, 2022

Nice script!

@AmitIITR here is a derived script to parse the full output from /proc/net/tcp and print each line in readable format:

#!/usr/bin/perl
#
# ref https://elixir.bootlin.com/linux/v4.14.42/source/include/net/tcp_states.h
@tcpstates = (
  "DUMMY",
  "TCP_ESTABLISHED",  #1
  "TCP_SYN_SENT",     #2
  "TCP_SYN_RECV",     #3
  "TCP_FIN_WAIT1",    #4
  "TCP_FIN_WAIT2",    #5
  "TCP_TIME_WAIT",    #6
  "TCP_CLOSE",        #7
  "TCP_CLOSE_WAIT",   #8
  "TCP_LAST_ACK",     #9
  "TCP_LISTEN",       #10
  "TCP_CLOSING",      #11
  "TCP_NEW_SYN_RECV", #12
  "TCP_MAX_STATES,"   #13
);

sub ipport() {
  $_[0] =~ m/([0-9A-F]+):([0-9A-F]+)/;
  $hexip = $1; $hexport = $2;
  my @ip = map hex($_), ( $hexip =~ m/../g );
  my $ip = join('.',reverse(@ip));
  my $port = hex($hexport);
  return ($ip . ":" . $port);
}

while ($line = <>) {
  if ($line =~ /(^[ ]*[0-9]+: )([0-9A-F:]+) ([0-9A-F:]+) ([0-9A-F]+)(.*)/) {
    $head = $1;
    $loc = $2;
    $rem = $3;
    $stat = $4;
    $tail = $5;
    if (hex($stat) == 0) {
      print STDERR "hex($stat) is 0\n";
    }
    push @output, sprintf("%s%-21s %-21s %s %s\n", $head, &ipport($loc), &ipport($rem), $tcpstates[hex($stat)]);
  }
}

foreach $line (@output) {
  print $line;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment