从/ proc / net / tcp6解析IPv6地址(python 2.7)

时间:2017-01-30 16:11:01

标签: python python-2.7 parsing converter ipv6

我正在尝试从Python 2.7中的/proc/net/tcp6读取 IPv6地址。以下是/proc/net/tcp6中使用的IPv6表示示例:

00000000000000000000000000000000
00000000000000000000000001000000
0000000000000000FFFF00001F00C80A

我遇到的问题是将这些转换为“正确”的IPv6表示,如维基百科所述:

  

IPv6地址表示为八个十六进制组   数字,每组代表16位(两个八位字节)。这些团体是   用冒号(:)分隔。 IPv6地址的示例是:

2001:0db8:85a3:0000:0000:8a2e:0370:7334
     

[...]示例地址可以进一步简化:

2001:db8:85a3::8a2e:370:7334

socket.inet_ntopstruct.pack的帮助下,这似乎最容易实现。

但是,我不知道要采用哪些步骤来生成这两个函数所需的特定格式。

使用Python 2.7 stdlib中的其他方法的任何其他方法当然都是受欢迎的。

为了便于比较,以下是我现在对从/proc/net/tcp读取的 IPv4地址的做法:

>>> addr = '0101007F'
>>> addr = int(addr, 16)
>>> addr = struct.pack('<I', addr)
>>> addr = socket.inet_ntoa(addr)
>>> print addr
127.0.1.1

不幸的是inet_ntoa不支持IPv6地址,您必须使用inet_ntop(AF_INET6, packed_ipv6)

但是我不知道如何使用in6_addr函数将上述字符串转换为struct.pack结构。

2 个答案:

答案 0 :(得分:1)

这是一种有效的方法,并自动处理本机字节序:

def ipv6(addr):
    addr = addr.decode('hex')
    addr = struct.unpack('>IIII', addr)
    addr = struct.pack('@IIII', *addr)
    addr = socket.inet_ntop(socket.AF_INET6, addr)
    return addr

样品:

>>> ipv6('00000000000000000000000001000000')
'::1'
>>> ipv6('B80D01200000000067452301EFCDAB89')
'2001:db8::123:4567:89ab:cdef'

步骤:

  1. 地址转换为字节字符串(decode('hex')),
  2. 拆分为4个切片,保持字节顺序不变(>IIII),
  3. 重新打包,每个切片都转换为本机字节顺序(@IIII),
  4. 传递给socket.inet_ntop,最终生成正确的IPv6表示
  5. systems that use little endian上,字节字符串将从DCBA-HGFE-LKJI-PONM转换为ABCD-EFGH-IJKL-MNOP。请参阅struct模块&#39; byte order notation

    unpack&amp;的替代方案pack部分,但在我的系统上慢两倍,并且它不会自动处理本机字节序(假设这里有小端):

    addr = ''.join(addr[i:i+4][::-1] for i in range(0, 16, 4))
    

答案 1 :(得分:0)

这样的东西?

from ipaddress import ip_address

components = [line[i:i+4] for i in range(0, len(line), 4)]
ipv6_string = ":".join(components)
print(ip_address(ipv6_string))