1
2
3
4
5
6
7 """
8 A module containing pure-Python implementations of certain socket module
9 constants and functions. Useful on some platforms or Python interpreters where
10 they may be missing for various reasons.
11 """
12 from struct import unpack as _unpack, pack as _pack
13
14 AF_UNSPEC = 0
15 AF_INET = 2
16 AF_INET6 = 10
17
18
20 """
21 Convert an IP address from 32-bit packed binary format to string format.
22 """
23 if len(packed_ip) != 4 or not hasattr(packed_ip, 'split'):
24 raise ValueError('invalid length of packed IP address string')
25 return '%d.%d.%d.%d' % _unpack('4B', packed_ip)
26
27
29 """
30 Convert an IP address in string format (123.45.67.89) to the 32-bit packed
31 binary format used in low-level network functions.
32 """
33 if hasattr(ip_string, 'split'):
34 invalid_addr = ValueError('illegal IP address string %r' % ip_string)
35
36 tokens = []
37 base = 10
38 for token in ip_string.split('.'):
39 if token.startswith('0x'):
40 base = 16
41 elif token.startswith('0') and len(token) > 1:
42 base = 8
43 elif token == '':
44 continue
45 try:
46 tokens.append(int(token, base))
47 except ValueError:
48 raise invalid_addr
49
50
51 num_tokens = len(tokens)
52 if num_tokens < 4:
53 fill_tokens = [0] * (4 - num_tokens)
54 if num_tokens > 1:
55 end_token = tokens.pop()
56 tokens = tokens + fill_tokens + [end_token]
57 else:
58 tokens = tokens + fill_tokens
59
60
61 if len(tokens) == 4:
62 words = []
63 for token in tokens:
64 if (token >> 8) != 0:
65 raise invalid_addr
66 words.append(chr(token))
67 return ''.join(words)
68 else:
69 raise invalid_addr
70
71 raise ValueError('argument should be a string, not %s' % type(ip_string))
72
73
75 new_tokens = []
76
77 positions = []
78 within_run = False
79 start_index = None
80 num_tokens = 0
81
82
83 for idx, token in enumerate(tokens):
84 if token == '0':
85 within_run = True
86 if start_index is None:
87 start_index = idx
88 num_tokens += 1
89 else:
90 if num_tokens > 1:
91 positions.append((num_tokens, start_index))
92 within_run = False
93 start_index = None
94 num_tokens = 0
95
96 new_tokens.append(token)
97
98
99 if num_tokens > 1:
100 positions.append((num_tokens, start_index))
101
102
103 if len(positions) != 0:
104
105 positions.sort(lambda x, y: cmp(x[1], y[1]))
106 best_position = positions[0]
107 for position in positions:
108 if position[0] > best_position[0]:
109 best_position = position
110
111 (length, start_idx) = best_position
112 new_tokens = new_tokens[0:start_idx] + [''] + \
113 new_tokens[start_idx+length:]
114
115
116 if new_tokens[0] == '':
117 new_tokens.insert(0, '')
118
119 if new_tokens[-1] == '':
120 new_tokens.append('')
121
122 return new_tokens
123
124
126 """Convert an packed IP address of the given family to string format."""
127 if af == AF_INET:
128
129 return inet_ntoa(packed_ip)
130 elif af == AF_INET6:
131
132 if len(packed_ip) != 16 or not hasattr(packed_ip, 'split'):
133 raise ValueError('invalid length of packed IP address string')
134
135 tokens = ['%x' % i for i in _unpack('>8H', packed_ip)]
136
137
138 words = list(_unpack('>8H', packed_ip))
139 int_val = 0
140 for i, num in enumerate(reversed(words)):
141 word = num
142 word = word << 16 * i
143 int_val = int_val | word
144
145 if 0xffff < int_val <= 0xffffffff or int_val >> 32 == 0xffff:
146
147 packed_ipv4 = _pack('>2H', *[int(i, 16) for i in tokens[-2:]])
148 ipv4_str = inet_ntoa(packed_ipv4)
149 tokens = tokens[0:-2] + [ipv4_str]
150
151 return ':'.join(_compact_ipv6_tokens(tokens))
152 else:
153 raise ValueError('unknown address family %d' % af)
154
155
157 """
158 Convert an IP address from string format to a packed string suitable for
159 use with low-level network functions.
160 """
161 if af == AF_INET:
162
163 return inet_aton(ip_string)
164 elif af == AF_INET6:
165 invalid_addr = ValueError('illegal IP address string %r' % ip_string)
166
167 values = []
168
169 if not hasattr(ip_string, 'split'):
170 raise invalid_addr
171
172 if '::' in ip_string:
173 if ip_string == '::':
174
175 return '\x00'*16
176
177 try:
178 prefix, suffix = ip_string.split('::')
179 except ValueError:
180 raise invalid_addr
181
182 l_prefix = []
183 l_suffix = []
184
185 if prefix != '':
186 l_prefix = prefix.split(':')
187
188 if suffix != '':
189 l_suffix = suffix.split(':')
190
191
192 if len(l_suffix) and '.' in l_suffix[-1]:
193 ipv4_str = inet_aton(l_suffix.pop())
194 l_suffix.append('%x' % _unpack('>H', ipv4_str[0:2])[0])
195 l_suffix.append('%x' % _unpack('>H', ipv4_str[2:4])[0])
196
197 token_count = len(l_prefix) + len(l_suffix)
198
199 if not 0 <= token_count <= 8 - 1:
200 raise invalid_addr
201
202 gap_size = 8 - ( len(l_prefix) + len(l_suffix) )
203
204 values = [_pack('>H', int(i, 16)) for i in l_prefix] \
205 + ['\x00\x00' for i in range(gap_size)] \
206 + [_pack('>H', int(i, 16)) for i in l_suffix]
207 try:
208 for token in l_prefix + l_suffix:
209 word = int(token, 16)
210 if not 0 <= word <= 0xffff:
211 raise invalid_addr
212 except ValueError:
213 raise invalid_addr
214 else:
215
216 if ':' in ip_string:
217 tokens = ip_string.split(':')
218
219 if '.' in ip_string:
220 ipv6_prefix = tokens[:-1]
221 if ipv6_prefix[:-1] != ['0', '0', '0', '0', '0']:
222 raise invalid_addr
223
224 if ipv6_prefix[-1].lower() not in ('0', 'ffff'):
225 raise invalid_addr
226
227
228 if len(tokens) != 7:
229 raise invalid_addr
230
231 ipv4_str = inet_aton(tokens.pop())
232 tokens.append('%x' % _unpack('>H', ipv4_str[0:2])[0])
233 tokens.append('%x' % _unpack('>H', ipv4_str[2:4])[0])
234
235 values = [_pack('>H', int(i, 16)) for i in tokens]
236 else:
237
238 if len(tokens) != 8:
239 raise invalid_addr
240 try:
241 tokens = [int(token, 16) for token in tokens]
242 for token in tokens:
243 if not 0 <= token <= 0xffff:
244 raise invalid_addr
245
246 except ValueError:
247 raise invalid_addr
248
249 values = [_pack('>H', i) for i in tokens]
250 else:
251 raise invalid_addr
252
253 return ''.join(values)
254 else:
255 raise ValueError('Unknown address family %d' % af)
256