1 """Pure Python IP6 parsing and formatting
2
3 Copyright (c) 2006 Stuart Gathman <stuart@bmsi.com>
4
5 This module is free software, and you may redistribute it and/or modify
6 it under the same terms as Python itself, so long as this copyright message
7 and disclaimer are retained in their original form.
8 """
9 import struct
10
11 import re
12 PAT_IP4 = r'\.'.join([r'(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])']*4)
13 RE_IP4 = re.compile(PAT_IP4+'$')
14
16 """
17 Convert ip6 address to standard hex notation.
18
19 Examples:
20
21 >>> inet_ntop(struct.pack("!HHHHHHHH",0,0,0,0,0,0xFFFF,0x0102,0x0304))
22 '::FFFF:1.2.3.4'
23
24 >>> inet_ntop(struct.pack("!HHHHHHHH",0x1234,0x5678,0,0,0,0,0x0102,0x0304))
25 '1234:5678::102:304'
26
27 >>> inet_ntop(struct.pack("!HHHHHHHH",0,0,0,0x1234,0x5678,0,0x0102,0x0304))
28 '::1234:5678:0:102:304'
29
30 >>> inet_ntop(struct.pack("!HHHHHHHH",0x1234,0x5678,0,0x0102,0x0304,0,0,0))
31 '1234:5678:0:102:304::'
32
33 >>> inet_ntop(struct.pack("!HHHHHHHH",0,0,0,0,0,0,0,0))
34 '::'
35 """
36
37 a = struct.unpack("!HHHHHHHH",s)
38 n = (0,0,0,0,0,0,0,0)
39 if a == n: return '::'
40
41 if a[:5] == (0,0,0,0,0) and a[5] in (0,0xFFFF):
42 ip4 = '.'.join([str(i) for i in struct.unpack("!BBBB",s[12:])])
43 if a[5]:
44 return "::FFFF:" + ip4
45 return "::" + ip4
46
47 for l in (7,6,5,4,3,2,1):
48 e = n[:l]
49 for i in range(9-l):
50 if a[i:i+l] == e:
51 if i == 0:
52 return ':'+':%x'*(8-l) % a[l:]
53 if i == 8 - l:
54 return '%x:'*(8-l) % a[:-l] + ':'
55 return '%x:'*i % a[:i] + ':%x'*(8-l-i) % a[i+l:]
56 return "%x:%x:%x:%x:%x:%x:%x:%x" % a
57
59 """
60 Convert ip6 standard hex notation to ip6 address.
61
62 Examples:
63
64 >>> struct.unpack('!HHHHHHHH',inet_pton('::'))
65 (0, 0, 0, 0, 0, 0, 0, 0)
66
67 >>> struct.unpack('!HHHHHHHH',inet_pton('::1234'))
68 (0, 0, 0, 0, 0, 0, 0, 4660)
69
70 >>> struct.unpack('!HHHHHHHH',inet_pton('1234::'))
71 (4660, 0, 0, 0, 0, 0, 0, 0)
72
73 >>> struct.unpack('!HHHHHHHH',inet_pton('1234::5678'))
74 (4660, 0, 0, 0, 0, 0, 0, 22136)
75
76 >>> struct.unpack('!HHHHHHHH',inet_pton('::FFFF:1.2.3.4'))
77 (0, 0, 0, 0, 0, 65535, 258, 772)
78
79 >>> struct.unpack('!HHHHHHHH',inet_pton('1.2.3.4'))
80 (0, 0, 0, 0, 0, 65535, 258, 772)
81
82 >>> try: inet_pton('::1.2.3.4.5')
83 ... except ValueError,x: print x
84 ::1.2.3.4.5
85 """
86 if p == '::':
87 return '\0'*16
88 s = p
89 m = RE_IP4.search(s)
90 try:
91 if m:
92 pos = m.start()
93 ip4 = [int(i) for i in s[pos:].split('.')]
94 if not pos:
95 return struct.pack('!QLBBBB',0,65535,*ip4)
96 s = s[:pos]+'%x%02x:%x%02x'%tuple(ip4)
97 a = s.split('::')
98 if len(a) == 2:
99 l,r = a
100 if not l:
101 r = r.split(':')
102 return struct.pack('!HHHHHHHH',
103 *[0]*(8-len(r)) + [int(s,16) for s in r])
104 if not r:
105 l = l.split(':')
106 return struct.pack('!HHHHHHHH',
107 *[int(s,16) for s in l] + [0]*(8-len(l)))
108 l = l.split(':')
109 r = r.split(':')
110 return struct.pack('!HHHHHHHH',
111 *[int(s,16) for s in l] + [0]*(8-len(l)-len(r))
112 + [int(s,16) for s in r])
113 if len(a) == 1:
114 return struct.pack('!HHHHHHHH',
115 *[int(s,16) for s in a[0].split(':')])
116 except ValueError: pass
117 raise ValueError,p
118