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

106 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:45 +0000

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 # These might all generate exceptions on different platforms. 

17 if not _socket.has_ipv6: 

18 raise Exception('IPv6 disabled') 

19 _socket.inet_pton 

20 _socket.AF_INET6 

21 from _socket import (inet_pton as _inet_pton, inet_ntop as _inet_ntop, 

22 AF_INET6) 

23 OPT_IMPORTS = True 

24except Exception: 

25 from netaddr.fbsocket import (inet_pton as _inet_pton, inet_ntop as _inet_ntop, 

26 AF_INET6) 

27 

28from netaddr.core import AddrFormatError 

29from netaddr.strategy import ( 

30 valid_words as _valid_words, int_to_words as _int_to_words, 

31 words_to_int as _words_to_int, valid_bits as _valid_bits, 

32 bits_to_int as _bits_to_int, int_to_bits as _int_to_bits, 

33 valid_bin as _valid_bin, int_to_bin as _int_to_bin, 

34 bin_to_int as _bin_to_int) 

35 

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

37width = 128 

38 

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

40word_size = 16 

41 

42#: The separator character used between each word. 

43word_sep = ':' 

44 

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

46family = AF_INET6 

47 

48#: A friendly string name address type. 

49family_name = 'IPv6' 

50 

51#: The version of this address type. 

52version = 6 

53 

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

55word_base = 16 

56 

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

58max_int = 2 ** width - 1 

59 

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

61num_words = width // word_size 

62 

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

64max_word = 2 ** word_size - 1 

65 

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

67prefix_to_netmask = dict( 

68 [(i, max_int ^ (2 ** (width - i) - 1)) for i in range(0, width+1)]) 

69 

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

71netmask_to_prefix = dict( 

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

73 

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

75prefix_to_hostmask = dict( 

76 [(i, (2 ** (width - i) - 1)) for i in range(0, width+1)]) 

77 

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

79hostmask_to_prefix = dict( 

80 [((2 ** (width - i) - 1), i) for i in range(0, width+1)]) 

81 

82#----------------------------------------------------------------------------- 

83# Dialect classes. 

84#----------------------------------------------------------------------------- 

85 

86class ipv6_compact(object): 

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

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

89 word_fmt = '%x' 

90 

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

92 compact = True 

93 

94class ipv6_full(ipv6_compact): 

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

96 

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

98 compact = False 

99 

100class ipv6_verbose(ipv6_compact): 

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

102 

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

104 word_fmt = '%.4x' 

105 

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

107 compact = False 

108 

109 

110def valid_str(addr, flags=0): 

111 """ 

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

113 

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

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

116 

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

118 """ 

119 if addr == '': 

120 raise AddrFormatError('Empty strings are not supported!') 

121 

122 try: 

123 _inet_pton(AF_INET6, addr) 

124 except: 

125 return False 

126 return True 

127 

128 

129def str_to_int(addr, flags=0): 

130 """ 

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

132 

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

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

135 

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

137 """ 

138 try: 

139 packed_int = _inet_pton(AF_INET6, addr) 

140 return packed_to_int(packed_int) 

141 except Exception: 

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

143 

144 

145def int_to_str(int_val, dialect=None): 

146 """ 

147 :param int_val: An unsigned integer. 

148 

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

150 

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

152 unsigned integer provided. 

153 """ 

154 if dialect is None: 

155 dialect = ipv6_compact 

156 

157 addr = None 

158 

159 try: 

160 packed_int = int_to_packed(int_val) 

161 if dialect.compact: 

162 # Default return value. 

163 addr = _inet_ntop(AF_INET6, packed_int) 

164 else: 

165 # Custom return value. 

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

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

168 addr = word_sep.join(tokens) 

169 except Exception: 

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

171 

172 return addr 

173 

174 

175def int_to_arpa(int_val): 

176 """ 

177 :param int_val: An unsigned integer. 

178 

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

180 order integer form. 

181 """ 

182 addr = int_to_str(int_val, ipv6_verbose) 

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

184 tokens.reverse() 

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

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

187 return '.'.join(tokens) 

188 

189 

190def int_to_packed(int_val): 

191 """ 

192 :param int_val: the integer to be packed. 

193 

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

195 unsigned integer. 

196 """ 

197 words = int_to_words(int_val, 4, 32) 

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

199 

200 

201def packed_to_int(packed_int): 

202 """ 

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

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

205 

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

207 represented by packed binary string. 

208 """ 

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

210 

211 int_val = 0 

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

213 word = num 

214 word = word << 32 * i 

215 int_val = int_val | word 

216 

217 return int_val 

218 

219 

220def valid_words(words): 

221 return _valid_words(words, word_size, num_words) 

222 

223 

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

225 if num_words is None: 

226 num_words = globals()['num_words'] 

227 if word_size is None: 

228 word_size = globals()['word_size'] 

229 return _int_to_words(int_val, word_size, num_words) 

230 

231 

232def words_to_int(words): 

233 return _words_to_int(words, word_size, num_words) 

234 

235 

236def valid_bits(bits): 

237 return _valid_bits(bits, width, word_sep) 

238 

239 

240def bits_to_int(bits): 

241 return _bits_to_int(bits, width, word_sep) 

242 

243 

244def int_to_bits(int_val, word_sep=None): 

245 if word_sep is None: 

246 word_sep = globals()['word_sep'] 

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

248 

249 

250def valid_bin(bin_val): 

251 return _valid_bin(bin_val, width) 

252 

253 

254def int_to_bin(int_val): 

255 return _int_to_bin(int_val, width) 

256 

257 

258def bin_to_int(bin_val): 

259 return _bin_to_int(bin_val, width)