Difference between revisions of "Unix sockets"
(Created page with " ==Socket status== The kernel exports information about open network sockets. The relevant <code>/proc/net/</code> files for IPv4 are: tcp, udp, and raw. All three files have...") |
(→Socket status) |
||
Line 2: | Line 2: | ||
==Socket status== | ==Socket status== | ||
− | The kernel exports information about open network sockets. The relevant <code>/proc/net/</code> 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 <code> | + | The kernel exports information about open network sockets. The relevant <code>/proc/net/</code> 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 <code>$(cat /proc/net/tcp)</code> are shown here. |
The data presented in each output column is: | The data presented in each output column is: | ||
Line 45: | Line 45: | ||
$ ip_addr=$(echo 0F01A8C0 | sed -e 's/\(..\)\(..\)\(..\)\(..\)/echo $((0x\4)).$(echo $((0x\3))).$(echo $((0x\2))).$(echo $((0x\1)))/e') | $ 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 | + | * Nice, but, let's do this in pure [[awk]]: |
$ awk 'NR>1{split($2, addr, ":"); for(i=0;i<4;i++){ | $ awk 'NR>1{split($2, addr, ":"); for(i=0;i<4;i++){ | ||
Line 58: | Line 58: | ||
rshift(and(ip,0xff000000),24))}' | rshift(and(ip,0xff000000),24))}' | ||
− | * Final, pure | + | * Final, pure awk: |
<pre> | <pre> | ||
$ awk 'NR>1 { | $ awk 'NR>1 { |
Revision as of 21:31, 20 January 2022
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 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.
- 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