Unix sockets

From Christoph's Personal Wiki
Jump to: navigation, search

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:

The number of the line in the output listing.
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.
The remote IP address and port number for the socket. Encoding is the same as for the local_address.
The socket status.
rx_queue : The size of the transmit and receive queues.
tm->when : The tr field indicates whether a timer is active for this socket. A value of zero indicates the timer is not active. The tm->when field indicates the time remaining (in jiffies) before timeout occurs.
The ID of the user that owns the socket. This is the same ID found in the /etc/passwd file.
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:

  1. Take the rem_address field:
  2. Reverse the ordering of the bytes in the IP address part:
  3. Separate the bytes of the address for readability:
    7F 00 00 01 : 0017
  4. 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#*:};
$ 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),
  • Final, pure `awk`:
$ awk 'NR>1 {
       split($2, a, ":");
         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