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

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

105 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"""IPv4 address logic.""" 

7 

8import sys as _sys 

9import struct as _struct 

10 

11from socket import inet_aton as _inet_aton 

12 

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

14if _sys.platform in ('win32', 'cygwin'): 

15 # inet_pton() not available on Windows. inet_pton() under cygwin 

16 # behaves exactly like inet_aton() and is therefore highly unreliable. 

17 from netaddr.fbsocket import inet_pton as _inet_pton, AF_INET 

18else: 

19 # All other cases, use all functions from the socket module. 

20 from socket import inet_pton as _inet_pton, AF_INET 

21 

22from netaddr.core import AddrFormatError, ZEROFILL, INET_ATON, INET_PTON 

23 

24from netaddr.strategy import ( 

25 valid_words as _valid_words, 

26 valid_bits as _valid_bits, 

27 bits_to_int as _bits_to_int, 

28 int_to_bits as _int_to_bits, 

29 valid_bin as _valid_bin, 

30 int_to_bin as _int_to_bin, 

31 bin_to_int as _bin_to_int, 

32) 

33 

34 

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

36width = 32 

37 

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

39word_size = 8 

40 

41#: The format string to be used when converting words to string values. 

42word_fmt = '%d' 

43 

44#: The separator character used between each word. 

45word_sep = '.' 

46 

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

48family = AF_INET 

49 

50#: A friendly string name address type. 

51family_name = 'IPv4' 

52 

53#: The version of this address type. 

54version = 4 

55 

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

57word_base = 10 

58 

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

60max_int = 2**width - 1 

61 

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

63num_words = width // word_size 

64 

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

66max_word = 2**word_size - 1 

67 

68#: A dictionary mapping IPv4 CIDR prefixes to the equivalent netmasks. 

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

70 

71#: A dictionary mapping IPv4 netmasks to their equivalent CIDR prefixes. 

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

73 

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

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

76 

77#: A dictionary mapping IPv4 hostmasks to their equivalent CIDR prefixes. 

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

79 

80 

81def valid_str(addr, flags=0): 

82 """ 

83 :param addr: An IPv4 address in presentation (string) format. 

84 

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

86 addr value. Supported constants are INET_PTON and ZEROFILL. See the 

87 :class:`IPAddress` documentation for details. 

88 

89 .. versionchanged:: 0.10.1 

90 ``flags`` is scheduled to default to :data:`INET_PTON` instead of :data:`INET_ATON` 

91 in the future. 

92 

93 :return: ``True`` if IPv4 address is valid, ``False`` otherwise. 

94 

95 .. versionchanged:: 1.0.0 

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

97 """ 

98 if not isinstance(addr, str): 

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

100 try: 

101 str_to_int(addr, flags) 

102 except AddrFormatError: 

103 return False 

104 return True 

105 

106 

107def str_to_int(addr, flags=0): 

108 """ 

109 :param addr: An IPv4 dotted decimal address in string form. 

110 

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

112 addr value. Supported constants are INET_PTON and ZEROFILL. See the 

113 :class:`IPAddress` documentation for details. 

114 

115 :return: The equivalent unsigned integer for a given IPv4 address. 

116 """ 

117 error = AddrFormatError('%r is not a valid IPv4 address string!' % (addr,)) 

118 if ':' in addr: 

119 raise error 

120 pton_mode = flags & INET_PTON or not flags & INET_ATON 

121 if flags & ZEROFILL: 

122 addr = '.'.join(['%d' % int(i) for i in addr.split('.')]) 

123 elif pton_mode and any(len(p) > 1 and p.startswith('0') for p in addr.split('.')): 

124 raise error 

125 

126 try: 

127 if pton_mode: 

128 packed = _inet_pton(AF_INET, addr) 

129 else: 

130 packed = _inet_aton(addr) 

131 except OSError: 

132 raise error 

133 return _struct.unpack('>I', packed)[0] 

134 

135 

136def int_to_str(int_val, dialect=None): 

137 """ 

138 :param int_val: An unsigned integer. 

139 

140 :param dialect: (unused) Any value passed in is ignored. 

141 

142 :return: The IPv4 presentation (string) format address equivalent to the 

143 unsigned integer provided. 

144 """ 

145 if 0 <= int_val <= max_int: 

146 return '%d.%d.%d.%d' % ( 

147 int_val >> 24, 

148 (int_val >> 16) & 0xFF, 

149 (int_val >> 8) & 0xFF, 

150 int_val & 0xFF, 

151 ) 

152 else: 

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

154 

155 

156def int_to_arpa(int_val): 

157 """ 

158 :param int_val: An unsigned integer. 

159 

160 :return: The reverse DNS lookup for an IPv4 address in network byte 

161 order integer form. 

162 """ 

163 words = ['%d' % i for i in int_to_words(int_val)] 

164 words.reverse() 

165 words.extend(['in-addr', 'arpa', '']) 

166 return '.'.join(words) 

167 

168 

169def int_to_packed(int_val): 

170 """ 

171 :param int_val: the integer to be packed. 

172 

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

174 unsigned integer. 

175 """ 

176 return _struct.pack('>I', int_val) 

177 

178 

179def packed_to_int(packed_int): 

180 """ 

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

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

183 

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

185 represented by packed binary string. 

186 """ 

187 return _struct.unpack('>I', packed_int)[0] 

188 

189 

190def valid_words(words): 

191 return _valid_words(words, word_size, num_words) 

192 

193 

194def int_to_words(int_val): 

195 """ 

196 :param int_val: An unsigned integer. 

197 

198 :return: An integer word (octet) sequence that is equivalent to value 

199 represented by an unsigned integer. 

200 """ 

201 if not 0 <= int_val <= max_int: 

202 raise ValueError( 

203 '%r is not a valid integer value supported by' 'this address type!' % (int_val,) 

204 ) 

205 return (int_val >> 24, (int_val >> 16) & 0xFF, (int_val >> 8) & 0xFF, int_val & 0xFF) 

206 

207 

208def words_to_int(words): 

209 """ 

210 :param words: A list or tuple containing integer octets. 

211 

212 :return: An unsigned integer that is equivalent to value represented 

213 by word (octet) sequence. 

214 """ 

215 if not valid_words(words): 

216 raise ValueError('%r is not a valid octet list for an IPv4 address!' % (words,)) 

217 return _struct.unpack('>I', _struct.pack('4B', *words))[0] 

218 

219 

220def valid_bits(bits): 

221 return _valid_bits(bits, width, word_sep) 

222 

223 

224def bits_to_int(bits): 

225 return _bits_to_int(bits, width, word_sep) 

226 

227 

228def int_to_bits(int_val, word_sep=None): 

229 if word_sep is None: 

230 word_sep = globals()['word_sep'] 

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

232 

233 

234def valid_bin(bin_val): 

235 return _valid_bin(bin_val, width) 

236 

237 

238def int_to_bin(int_val): 

239 return _int_to_bin(int_val, width) 

240 

241 

242def bin_to_int(bin_val): 

243 return _bin_to_int(bin_val, width) 

244 

245 

246def expand_partial_address(addr): 

247 """ 

248 Expands a partial IPv4 address into a full 4-octet version. 

249 

250 :param addr: an partial or abbreviated IPv4 address 

251 

252 :return: an expanded IP address in presentation format (x.x.x.x) 

253 

254 >>> expand_partial_address('1.2') 

255 '1.2.0.0' 

256 

257 .. versionadded:: 1.1.0 

258 """ 

259 tokens = [] 

260 

261 error = AddrFormatError('invalid partial IPv4 address: %r!' % addr) 

262 

263 if isinstance(addr, str): 

264 if ':' in addr: 

265 # Ignore IPv6 ... 

266 raise error 

267 

268 try: 

269 if '.' in addr: 

270 tokens = ['%d' % int(o) for o in addr.split('.')] 

271 else: 

272 tokens = ['%d' % int(addr)] 

273 except ValueError: 

274 raise error 

275 

276 if 1 <= len(tokens) <= 4: 

277 for i in range(4 - len(tokens)): 

278 tokens.append('0') 

279 else: 

280 raise error 

281 

282 if not tokens: 

283 raise error 

284 

285 return '%s.%s.%s.%s' % tuple(tokens)