Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/netaddr/strategy/ipv6.py: 57%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

107 statements  

1# ----------------------------------------------------------------------------- 

2# Copyright (c) 2008 by David P. D. Moss. All rights reserved. 

3# 

4# Released under the BSD license. See the LICENSE file for details. 

5# ----------------------------------------------------------------------------- 

6""" 

7IPv6 address logic. 

8""" 

9import struct as _struct 

10 

11OPT_IMPORTS = False 

12 

13# Check whether we need to use fallback code or not. 

14try: 

15 import socket as _socket 

16 

17 # These might all generate exceptions on different platforms. 

18 if not _socket.has_ipv6: 

19 raise Exception('IPv6 disabled') 

20 _socket.inet_pton 

21 _socket.AF_INET6 

22 from _socket import inet_pton as _inet_pton, inet_ntop as _inet_ntop, AF_INET6 

23 

24 OPT_IMPORTS = True 

25except Exception: 

26 from netaddr.fbsocket import inet_pton as _inet_pton, inet_ntop as _inet_ntop, AF_INET6 

27 

28from netaddr.core import AddrFormatError 

29from netaddr.strategy import ( 

30 valid_words as _valid_words, 

31 int_to_words as _int_to_words, 

32 words_to_int as _words_to_int, 

33 valid_bits as _valid_bits, 

34 bits_to_int as _bits_to_int, 

35 int_to_bits as _int_to_bits, 

36 valid_bin as _valid_bin, 

37 int_to_bin as _int_to_bin, 

38 bin_to_int as _bin_to_int, 

39) 

40 

41#: The width (in bits) of this address type. 

42width = 128 

43 

44#: The individual word size (in bits) of this address type. 

45word_size = 16 

46 

47#: The separator character used between each word. 

48word_sep = ':' 

49 

50#: The AF_* constant value of this address type. 

51family = AF_INET6 

52 

53#: A friendly string name address type. 

54family_name = 'IPv6' 

55 

56#: The version of this address type. 

57version = 6 

58 

59#: The number base to be used when interpreting word values as integers. 

60word_base = 16 

61 

62#: The maximum integer value that can be represented by this address type. 

63max_int = 2**width - 1 

64 

65#: The number of words in this address type. 

66num_words = width // word_size 

67 

68#: The maximum integer value for an individual word in this address type. 

69max_word = 2**word_size - 1 

70 

71#: A dictionary mapping IPv6 CIDR prefixes to the equivalent netmasks. 

72prefix_to_netmask = dict([(i, max_int ^ (2 ** (width - i) - 1)) for i in range(0, width + 1)]) 

73 

74#: A dictionary mapping IPv6 netmasks to their equivalent CIDR prefixes. 

75netmask_to_prefix = dict([(max_int ^ (2 ** (width - i) - 1), i) for i in range(0, width + 1)]) 

76 

77#: A dictionary mapping IPv6 CIDR prefixes to the equivalent hostmasks. 

78prefix_to_hostmask = dict([(i, (2 ** (width - i) - 1)) for i in range(0, width + 1)]) 

79 

80#: A dictionary mapping IPv6 hostmasks to their equivalent CIDR prefixes. 

81hostmask_to_prefix = dict([((2 ** (width - i) - 1), i) for i in range(0, width + 1)]) 

82 

83# ----------------------------------------------------------------------------- 

84# Dialect classes. 

85# ----------------------------------------------------------------------------- 

86 

87 

88class ipv6_compact(object): 

89 """An IPv6 dialect class - compact form.""" 

90 

91 #: The format string used to converting words into string values. 

92 word_fmt = '%x' 

93 

94 #: Boolean flag indicating if IPv6 compaction algorithm should be used. 

95 compact = True 

96 

97 

98class ipv6_full(ipv6_compact): 

99 """An IPv6 dialect class - 'all zeroes' form.""" 

100 

101 #: Boolean flag indicating if IPv6 compaction algorithm should be used. 

102 compact = False 

103 

104 

105class ipv6_verbose(ipv6_compact): 

106 """An IPv6 dialect class - extra wide 'all zeroes' form.""" 

107 

108 #: The format string used to converting words into string values. 

109 word_fmt = '%.4x' 

110 

111 #: Boolean flag indicating if IPv6 compaction algorithm should be used. 

112 compact = False 

113 

114 

115def valid_str(addr, flags=0): 

116 """ 

117 :param addr: An IPv6 address in presentation (string) format. 

118 

119 :param flags: decides which rules are applied to the interpretation of the 

120 addr value. Future use - currently has no effect. 

121 

122 :return: ``True`` if IPv6 address is valid, ``False`` otherwise. 

123 

124 .. versionchanged:: 1.0.0 

125 Returns ``False`` instead of raising :exc:`AddrFormatError` for empty strings. 

126 """ 

127 if not isinstance(addr, str): 

128 raise TypeError('Invalid type: %s' % type(addr)) 

129 try: 

130 _inet_pton(AF_INET6, addr) 

131 except OSError: 

132 return False 

133 return True 

134 

135 

136def str_to_int(addr, flags=0): 

137 """ 

138 :param addr: An IPv6 address in string form. 

139 

140 :param flags: decides which rules are applied to the interpretation of the 

141 addr value. Future use - currently has no effect. 

142 

143 :return: The equivalent unsigned integer for a given IPv6 address. 

144 """ 

145 try: 

146 packed_int = _inet_pton(AF_INET6, addr) 

147 except OSError: 

148 raise AddrFormatError('%r is not a valid IPv6 address string!' % (addr,)) 

149 return packed_to_int(packed_int) 

150 

151 

152def int_to_str(int_val, dialect=None): 

153 """ 

154 :param int_val: An unsigned integer. 

155 

156 :param dialect: (optional) a Python class defining formatting options. 

157 

158 :return: The IPv6 presentation (string) format address equivalent to the 

159 unsigned integer provided. 

160 """ 

161 if dialect is None: 

162 dialect = ipv6_compact 

163 

164 addr = None 

165 

166 try: 

167 packed_int = int_to_packed(int_val) 

168 if dialect.compact: 

169 # Default return value. 

170 addr = _inet_ntop(AF_INET6, packed_int) 

171 else: 

172 # Custom return value. 

173 words = list(_struct.unpack('>8H', packed_int)) 

174 tokens = [dialect.word_fmt % word for word in words] 

175 addr = word_sep.join(tokens) 

176 except Exception: 

177 raise ValueError('%r is not a valid 128-bit unsigned integer!' % (int_val,)) 

178 

179 return addr 

180 

181 

182def int_to_arpa(int_val): 

183 """ 

184 :param int_val: An unsigned integer. 

185 

186 :return: The reverse DNS lookup for an IPv6 address in network byte 

187 order integer form. 

188 """ 

189 addr = int_to_str(int_val, ipv6_verbose) 

190 tokens = list(addr.replace(':', '')) 

191 tokens.reverse() 

192 # We won't support ip6.int here - see RFC 3152 for details. 

193 tokens = tokens + ['ip6', 'arpa', ''] 

194 return '.'.join(tokens) 

195 

196 

197def int_to_packed(int_val): 

198 """ 

199 :param int_val: the integer to be packed. 

200 

201 :return: a packed string that is equivalent to value represented by an 

202 unsigned integer. 

203 """ 

204 words = int_to_words(int_val, 4, 32) 

205 return _struct.pack('>4I', *words) 

206 

207 

208def packed_to_int(packed_int): 

209 """ 

210 :param packed_int: a packed string containing an unsigned integer. 

211 It is assumed that string is packed in network byte order. 

212 

213 :return: An unsigned integer equivalent to value of network address 

214 represented by packed binary string. 

215 """ 

216 words = list(_struct.unpack('>4I', packed_int)) 

217 

218 int_val = 0 

219 for i, num in enumerate(reversed(words)): 

220 word = num 

221 word = word << 32 * i 

222 int_val = int_val | word 

223 

224 return int_val 

225 

226 

227def valid_words(words): 

228 return _valid_words(words, word_size, num_words) 

229 

230 

231def int_to_words(int_val, num_words=None, word_size=None): 

232 if num_words is None: 

233 num_words = globals()['num_words'] 

234 if word_size is None: 

235 word_size = globals()['word_size'] 

236 return _int_to_words(int_val, word_size, num_words) 

237 

238 

239def words_to_int(words): 

240 return _words_to_int(words, word_size, num_words) 

241 

242 

243def valid_bits(bits): 

244 return _valid_bits(bits, width, word_sep) 

245 

246 

247def bits_to_int(bits): 

248 return _bits_to_int(bits, width, word_sep) 

249 

250 

251def int_to_bits(int_val, word_sep=None): 

252 if word_sep is None: 

253 word_sep = globals()['word_sep'] 

254 return _int_to_bits(int_val, word_size, num_words, word_sep) 

255 

256 

257def valid_bin(bin_val): 

258 return _valid_bin(bin_val, width) 

259 

260 

261def int_to_bin(int_val): 

262 return _int_to_bin(int_val, width) 

263 

264 

265def bin_to_int(bin_val): 

266 return _bin_to_int(bin_val, width)