Linux – Why does /proc/net/tcp6 represents ::1 as ::100:0

ipv6linuxlinux-kernel

I was writing an utility to check /proc/net/tcp and tcp6 for active connections as its faster than parsing netstat output.

As I dont actually have ipv6 enabled I was mainly utilizing localhost as my reference point. Here is a copy of my /proc/net/tcp6

sl  local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
 0: 00000000000000000000000000000000:006F 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 19587 1 ffff880262630000 100 0 0 10 -1
 1: 00000000000000000000000000000000:0050 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 22011 1 ffff880261c887c0 100 0 0 10 -1
 2: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 21958 1 ffff880261c88000 100 0 0 10 -1
 3: 00000000000000000000000001000000:0277 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 28592 1 ffff88024eea0000 100 0 0 10 -1

Here is the matching netstat -6 -pant

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp6       0      0 :::111                  :::*                    LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:631                 :::*                    LISTEN      -      

Entries 0-3 from tcp6 correspond with the ::'s (all ipv6), but entry 4 is supposedly the corresponding entry for ::1.

This is where I'm confused…

00000000000000000000000001000000 => 0000:0000:0000:0000:0000:0000:0100:0000 => ::100:0

When I run ::1 through some code to generate the full hex representation I get:

import binascii
import socket
print binascii.hexlify(socket.inet_pton(socket.AF_INET6, '::1'))
00000000000000000000000000000001

I can't programatically line these two values up, because they don't match (obviously). Why don't they match? Why does the kernel think ::100:0 is ::1?

Best Answer

This is due to counterintuitive byte order in /proc/net/tcp6. The address is handled as four words consisting of four bytes each. In each of those four words the four bytes are written in reverse order.

2001:0db8       :: 0123:4567:89ab:cdef would thus come out as:
B80D 0120 00000000 6745 2301 EFCD AB89 (with spaces inserted for clarity).

This is probably due to endianness differences. Most PCs these days use IA32 or AMD64 which are using the opposite endianness from what IP was designed with. I don't have any other systems to test with to figure out if you can rely on /proc/net/tcp6 always looking like that. But I verified that it is the case on both IA32 and AMD64 architectures.