Unix sockets
Socket status
The kernel exports information about open network sockets. The relevant /proc/net/
files for IPv4 are: tcp
, udp
, and raw
. All three files have identical syntax. The first line provides labels for each of the columns in the output. Each following line represents one open socket. Results from $(cat /proc/net/tcp)
are shown here.
The data presented in each output column is:
-
sl
- The number of the line in the output listing.
-
local_address
- The local IP address and port number for the socket. The IP address is displayed as a little-endian four-byte hexadecimal number; that is, the least significant byte is listed first, so one needs to reverse the order of the bytes to convert it to an IP address. The port number is a simple two-byte hexadecimal number.
-
rem_address
- The remote IP address and port number for the socket. Encoding is the same as for the
local_address
. -
st
- The socket status.
-
tx_queue / rx_queue
- The size of the transmit and receive queues.
-
tr / tm->when : The <code>tr
field indicates whether a timer is active for this socket. A value of zero indicates the timer is not active. Thetm->when
field indicates the time remaining (in jiffies) before timeout occurs. -
retrnsmt
- Unused.
-
uid
- The ID of the user that owns the socket. This is the same ID found in the
/etc/passwd
file. -
time-out
- Unused.
-
inode
- A cryptic-looking number that identifies the socket to the Linux virtual filesystem.
IP addresses in /proc/net/
In the files offered by the /proc/net/
directory, IP addresses are often represented as little-endian four-byte hexadecimal numbers. These are easy to convert into the more usual dotted-decimal notation.
For example, to convert the remote address and port of line 16 of the /proc/net/tcp
output shown in this column, one would do the following:
- Take the rem_address field:
-
0100007F:0017
-
- Reverse the ordering of the bytes in the IP address part:
-
7F000001:0017
-
- Separate the bytes of the address for readability:
-
7F 00 00 01 : 0017
-
- Perform a simple hexadecimal-to-decimal conversion on each:
-
127 0 0 1 : 23
-
It is a telnet connection to localhost. Simple enough.
- Get a list of local IP addresses and ports listening via UDP:
$ netstat -planu | awk '/^udp / {print $4}'
- Get the same info via the
/proc
filesystem:
$ for h in $(awk 'NR>1{print $2}' /proc/net/udp); do printf "%s:%d\n" $(printf "%d." $(echo ${h%:*}|sed 's/../0x& /g'|tr ' ' '\n'|tac)|sed 's/\.$/\n/') 0x${h#*:}; done
$ ip_addr=$(echo 0F01A8C0 | sed -e 's/\(..\)\(..\)\(..\)\(..\)/echo $((0x\4)).$(echo $((0x\3))).$(echo $((0x\2))).$(echo $((0x\1)))/e')
- Nice, but, let's do this in pure awk:
$ awk 'NR>1{split($2, addr, ":"); for(i=0;i<4;i++){ printf("%d.",strtonum("0x" substr(addr[1],2*i+1,2)))}; print ":" strtonum("0x" addr[2]);}' /proc/net/udp
- Almost. Just need to reverse the dotted decimals.
$ echo 0F01A8C0 | awk '{str = sprintf("0x%s", $0); ip = strtonum(str); \ printf ("%d.%d.%d.%d\t",rshift(and(ip,0x000000ff),00), rshift(and(ip,0x0000ff00),08), rshift(and(ip,0x00ff0000),16), rshift(and(ip,0xff000000),24))}'
- Final, pure awk:
$ awk 'NR>1 { split($2, a, ":"); patsplit(a[1],h,/.{2}/); for(i=4;i>0;i--){ h[i]=strtonum("0x" h[i]); }; printf("%d.%d.%d.%d:%d\n",h[4],h[3],h[2],h[1],strtonum("0x" a[2])); }' /proc/net/udp
External links
- Exploring the /proc/net/ Directory — where most of the above explanation came from
- http://www.usna.edu/Users/cs/aviv/classes/ic221/s14/lec/22/lec.html
- https://dzone.com/articles/linux-system-mining-python