synapse 2.180.0__py311-none-any.whl → 2.181.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (88) hide show
  1. synapse/assets/__init__.py +35 -0
  2. synapse/assets/storm/migrations/model-0.2.28.storm +355 -0
  3. synapse/common.py +2 -1
  4. synapse/cortex.py +49 -35
  5. synapse/cryotank.py +1 -1
  6. synapse/datamodel.py +30 -0
  7. synapse/lib/ast.py +12 -7
  8. synapse/lib/cell.py +1 -1
  9. synapse/lib/certdir.py +4 -4
  10. synapse/lib/chop.py +0 -1
  11. synapse/lib/drive.py +8 -8
  12. synapse/lib/layer.py +55 -13
  13. synapse/lib/lmdbslab.py +26 -5
  14. synapse/lib/modelrev.py +28 -1
  15. synapse/lib/modules.py +1 -0
  16. synapse/lib/nexus.py +1 -1
  17. synapse/lib/node.py +5 -0
  18. synapse/lib/parser.py +23 -16
  19. synapse/lib/scrape.py +1 -1
  20. synapse/lib/slabseqn.py +2 -2
  21. synapse/lib/snap.py +129 -0
  22. synapse/lib/storm.lark +16 -2
  23. synapse/lib/storm.py +3 -0
  24. synapse/lib/storm_format.py +1 -0
  25. synapse/lib/stormhttp.py +34 -1
  26. synapse/lib/stormlib/auth.py +1 -1
  27. synapse/lib/stormlib/cortex.py +5 -2
  28. synapse/lib/stormlib/ipv6.py +2 -2
  29. synapse/lib/stormlib/model.py +114 -12
  30. synapse/lib/stormlib/project.py +1 -1
  31. synapse/lib/stormtypes.py +81 -7
  32. synapse/lib/types.py +7 -0
  33. synapse/lib/version.py +2 -2
  34. synapse/lib/view.py +47 -0
  35. synapse/models/inet.py +10 -3
  36. synapse/models/infotech.py +2 -1
  37. synapse/models/language.py +4 -0
  38. synapse/models/math.py +50 -0
  39. synapse/models/orgs.py +8 -0
  40. synapse/models/risk.py +9 -0
  41. synapse/tests/files/stormcov/pragma-nocov.storm +18 -0
  42. synapse/tests/test_assets.py +25 -0
  43. synapse/tests/test_cortex.py +129 -0
  44. synapse/tests/test_datamodel.py +6 -0
  45. synapse/tests/test_lib_aha.py +2 -1
  46. synapse/tests/test_lib_certdir.py +9 -0
  47. synapse/tests/test_lib_grammar.py +7 -1
  48. synapse/tests/test_lib_layer.py +35 -0
  49. synapse/tests/test_lib_lmdbslab.py +11 -9
  50. synapse/tests/test_lib_modelrev.py +655 -1
  51. synapse/tests/test_lib_slabseqn.py +5 -4
  52. synapse/tests/test_lib_snap.py +4 -0
  53. synapse/tests/test_lib_storm.py +72 -1
  54. synapse/tests/test_lib_stormhttp.py +99 -1
  55. synapse/tests/test_lib_stormlib_cortex.py +21 -4
  56. synapse/tests/test_lib_stormlib_iters.py +8 -5
  57. synapse/tests/test_lib_stormlib_model.py +45 -6
  58. synapse/tests/test_lib_stormtypes.py +158 -2
  59. synapse/tests/test_lib_types.py +6 -0
  60. synapse/tests/test_model_inet.py +10 -0
  61. synapse/tests/test_model_language.py +4 -0
  62. synapse/tests/test_model_math.py +22 -0
  63. synapse/tests/test_model_orgs.py +6 -2
  64. synapse/tests/test_model_risk.py +4 -0
  65. synapse/tests/test_utils_stormcov.py +5 -0
  66. synapse/tests/utils.py +18 -5
  67. synapse/utils/stormcov/plugin.py +31 -1
  68. synapse/vendor/cpython/LICENSE +279 -0
  69. synapse/vendor/cpython/__init__.py +0 -0
  70. synapse/vendor/cpython/lib/__init__.py +0 -0
  71. synapse/vendor/cpython/lib/email/__init__.py +0 -0
  72. synapse/vendor/cpython/lib/email/_parseaddr.py +560 -0
  73. synapse/vendor/cpython/lib/email/utils.py +505 -0
  74. synapse/vendor/cpython/lib/ipaddress.py +2366 -0
  75. synapse/vendor/cpython/lib/test/__init__.py +0 -0
  76. synapse/vendor/cpython/lib/test/support/__init__.py +114 -0
  77. synapse/vendor/cpython/lib/test/test_email/__init__.py +0 -0
  78. synapse/vendor/cpython/lib/test/test_email/test_email.py +480 -0
  79. synapse/vendor/cpython/lib/test/test_email/test_utils.py +167 -0
  80. synapse/vendor/cpython/lib/test/test_ipaddress.py +2672 -0
  81. synapse/vendor/utils.py +4 -3
  82. {synapse-2.180.0.dist-info → synapse-2.181.0.dist-info}/METADATA +2 -2
  83. {synapse-2.180.0.dist-info → synapse-2.181.0.dist-info}/RECORD +86 -69
  84. {synapse-2.180.0.dist-info → synapse-2.181.0.dist-info}/WHEEL +1 -1
  85. synapse/lib/jupyter.py +0 -505
  86. synapse/tests/test_lib_jupyter.py +0 -224
  87. {synapse-2.180.0.dist-info → synapse-2.181.0.dist-info}/LICENSE +0 -0
  88. {synapse-2.180.0.dist-info → synapse-2.181.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,2366 @@
1
+ ##############################################################################
2
+ # Taken from the cpython 3.11 source branch after the 3.11.10 release.
3
+ ##############################################################################
4
+ # Copyright 2007 Google Inc.
5
+ # Licensed to PSF under a Contributor Agreement.
6
+
7
+ """A fast, lightweight IPv4/IPv6 manipulation library in Python.
8
+
9
+ This library is used to create/poke/manipulate IPv4 and IPv6 addresses
10
+ and networks.
11
+
12
+ """
13
+
14
+ __version__ = '1.0'
15
+
16
+
17
+ import functools
18
+
19
+ IPV4LENGTH = 32
20
+ IPV6LENGTH = 128
21
+
22
+
23
+ class AddressValueError(ValueError):
24
+ """A Value Error related to the address."""
25
+
26
+
27
+ class NetmaskValueError(ValueError):
28
+ """A Value Error related to the netmask."""
29
+
30
+
31
+ def ip_address(address):
32
+ """Take an IP string/int and return an object of the correct type.
33
+
34
+ Args:
35
+ address: A string or integer, the IP address. Either IPv4 or
36
+ IPv6 addresses may be supplied; integers less than 2**32 will
37
+ be considered to be IPv4 by default.
38
+
39
+ Returns:
40
+ An IPv4Address or IPv6Address object.
41
+
42
+ Raises:
43
+ ValueError: if the *address* passed isn't either a v4 or a v6
44
+ address
45
+
46
+ """
47
+ try:
48
+ return IPv4Address(address)
49
+ except (AddressValueError, NetmaskValueError):
50
+ pass
51
+
52
+ try:
53
+ return IPv6Address(address)
54
+ except (AddressValueError, NetmaskValueError):
55
+ pass
56
+
57
+ raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 address')
58
+
59
+
60
+ def ip_network(address, strict=True):
61
+ """Take an IP string/int and return an object of the correct type.
62
+
63
+ Args:
64
+ address: A string or integer, the IP network. Either IPv4 or
65
+ IPv6 networks may be supplied; integers less than 2**32 will
66
+ be considered to be IPv4 by default.
67
+
68
+ Returns:
69
+ An IPv4Network or IPv6Network object.
70
+
71
+ Raises:
72
+ ValueError: if the string passed isn't either a v4 or a v6
73
+ address. Or if the network has host bits set.
74
+
75
+ """
76
+ try:
77
+ return IPv4Network(address, strict)
78
+ except (AddressValueError, NetmaskValueError):
79
+ pass
80
+
81
+ try:
82
+ return IPv6Network(address, strict)
83
+ except (AddressValueError, NetmaskValueError):
84
+ pass
85
+
86
+ raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 network')
87
+
88
+
89
+ def ip_interface(address):
90
+ """Take an IP string/int and return an object of the correct type.
91
+
92
+ Args:
93
+ address: A string or integer, the IP address. Either IPv4 or
94
+ IPv6 addresses may be supplied; integers less than 2**32 will
95
+ be considered to be IPv4 by default.
96
+
97
+ Returns:
98
+ An IPv4Interface or IPv6Interface object.
99
+
100
+ Raises:
101
+ ValueError: if the string passed isn't either a v4 or a v6
102
+ address.
103
+
104
+ Notes:
105
+ The IPv?Interface classes describe an Address on a particular
106
+ Network, so they're basically a combination of both the Address
107
+ and Network classes.
108
+
109
+ """
110
+ try:
111
+ return IPv4Interface(address)
112
+ except (AddressValueError, NetmaskValueError):
113
+ pass
114
+
115
+ try:
116
+ return IPv6Interface(address)
117
+ except (AddressValueError, NetmaskValueError):
118
+ pass
119
+
120
+ raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 interface')
121
+
122
+
123
+ def v4_int_to_packed(address):
124
+ """Represent an address as 4 packed bytes in network (big-endian) order.
125
+
126
+ Args:
127
+ address: An integer representation of an IPv4 IP address.
128
+
129
+ Returns:
130
+ The integer address packed as 4 bytes in network (big-endian) order.
131
+
132
+ Raises:
133
+ ValueError: If the integer is negative or too large to be an
134
+ IPv4 IP address.
135
+
136
+ """
137
+ try:
138
+ return address.to_bytes(4) # big endian
139
+ except OverflowError:
140
+ raise ValueError("Address negative or too large for IPv4")
141
+
142
+
143
+ def v6_int_to_packed(address):
144
+ """Represent an address as 16 packed bytes in network (big-endian) order.
145
+
146
+ Args:
147
+ address: An integer representation of an IPv6 IP address.
148
+
149
+ Returns:
150
+ The integer address packed as 16 bytes in network (big-endian) order.
151
+
152
+ """
153
+ try:
154
+ return address.to_bytes(16) # big endian
155
+ except OverflowError:
156
+ raise ValueError("Address negative or too large for IPv6")
157
+
158
+
159
+ def _split_optional_netmask(address):
160
+ """Helper to split the netmask and raise AddressValueError if needed"""
161
+ addr = str(address).split('/')
162
+ if len(addr) > 2:
163
+ raise AddressValueError(f"Only one '/' permitted in {address!r}")
164
+ return addr
165
+
166
+
167
+ def _find_address_range(addresses):
168
+ """Find a sequence of sorted deduplicated IPv#Address.
169
+
170
+ Args:
171
+ addresses: a list of IPv#Address objects.
172
+
173
+ Yields:
174
+ A tuple containing the first and last IP addresses in the sequence.
175
+
176
+ """
177
+ it = iter(addresses)
178
+ first = last = next(it)
179
+ for ip in it:
180
+ if ip._ip != last._ip + 1:
181
+ yield first, last
182
+ first = ip
183
+ last = ip
184
+ yield first, last
185
+
186
+
187
+ def _count_righthand_zero_bits(number, bits):
188
+ """Count the number of zero bits on the right hand side.
189
+
190
+ Args:
191
+ number: an integer.
192
+ bits: maximum number of bits to count.
193
+
194
+ Returns:
195
+ The number of zero bits on the right hand side of the number.
196
+
197
+ """
198
+ if number == 0:
199
+ return bits
200
+ return min(bits, (~number & (number - 1)).bit_length())
201
+
202
+
203
+ def summarize_address_range(first, last):
204
+ """Summarize a network range given the first and last IP addresses.
205
+
206
+ Example:
207
+ >>> list(summarize_address_range(IPv4Address('192.0.2.0'),
208
+ ... IPv4Address('192.0.2.130')))
209
+ ... #doctest: +NORMALIZE_WHITESPACE
210
+ [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'),
211
+ IPv4Network('192.0.2.130/32')]
212
+
213
+ Args:
214
+ first: the first IPv4Address or IPv6Address in the range.
215
+ last: the last IPv4Address or IPv6Address in the range.
216
+
217
+ Returns:
218
+ An iterator of the summarized IPv(4|6) network objects.
219
+
220
+ Raise:
221
+ TypeError:
222
+ If the first and last objects are not IP addresses.
223
+ If the first and last objects are not the same version.
224
+ ValueError:
225
+ If the last object is not greater than the first.
226
+ If the version of the first address is not 4 or 6.
227
+
228
+ """
229
+ if (not (isinstance(first, _BaseAddress) and
230
+ isinstance(last, _BaseAddress))):
231
+ raise TypeError('first and last must be IP addresses, not networks')
232
+ if first.version != last.version:
233
+ raise TypeError("%s and %s are not of the same version" % (
234
+ first, last))
235
+ if first > last:
236
+ raise ValueError('last IP address must be greater than first')
237
+
238
+ if first.version == 4:
239
+ ip = IPv4Network
240
+ elif first.version == 6:
241
+ ip = IPv6Network
242
+ else:
243
+ raise ValueError('unknown IP version')
244
+
245
+ ip_bits = first._max_prefixlen
246
+ first_int = first._ip
247
+ last_int = last._ip
248
+ while first_int <= last_int:
249
+ nbits = min(_count_righthand_zero_bits(first_int, ip_bits),
250
+ (last_int - first_int + 1).bit_length() - 1)
251
+ net = ip((first_int, ip_bits - nbits))
252
+ yield net
253
+ first_int += 1 << nbits
254
+ if first_int - 1 == ip._ALL_ONES:
255
+ break
256
+
257
+
258
+ def _collapse_addresses_internal(addresses):
259
+ """Loops through the addresses, collapsing concurrent netblocks.
260
+
261
+ Example:
262
+
263
+ ip1 = IPv4Network('192.0.2.0/26')
264
+ ip2 = IPv4Network('192.0.2.64/26')
265
+ ip3 = IPv4Network('192.0.2.128/26')
266
+ ip4 = IPv4Network('192.0.2.192/26')
267
+
268
+ _collapse_addresses_internal([ip1, ip2, ip3, ip4]) ->
269
+ [IPv4Network('192.0.2.0/24')]
270
+
271
+ This shouldn't be called directly; it is called via
272
+ collapse_addresses([]).
273
+
274
+ Args:
275
+ addresses: A list of IPv4Network's or IPv6Network's
276
+
277
+ Returns:
278
+ A list of IPv4Network's or IPv6Network's depending on what we were
279
+ passed.
280
+
281
+ """
282
+ # First merge
283
+ to_merge = list(addresses)
284
+ subnets = {}
285
+ while to_merge:
286
+ net = to_merge.pop()
287
+ supernet = net.supernet()
288
+ existing = subnets.get(supernet)
289
+ if existing is None:
290
+ subnets[supernet] = net
291
+ elif existing != net:
292
+ # Merge consecutive subnets
293
+ del subnets[supernet]
294
+ to_merge.append(supernet)
295
+ # Then iterate over resulting networks, skipping subsumed subnets
296
+ last = None
297
+ for net in sorted(subnets.values()):
298
+ if last is not None:
299
+ # Since they are sorted, last.network_address <= net.network_address
300
+ # is a given.
301
+ if last.broadcast_address >= net.broadcast_address:
302
+ continue
303
+ yield net
304
+ last = net
305
+
306
+
307
+ def collapse_addresses(addresses):
308
+ """Collapse a list of IP objects.
309
+
310
+ Example:
311
+ collapse_addresses([IPv4Network('192.0.2.0/25'),
312
+ IPv4Network('192.0.2.128/25')]) ->
313
+ [IPv4Network('192.0.2.0/24')]
314
+
315
+ Args:
316
+ addresses: An iterator of IPv4Network or IPv6Network objects.
317
+
318
+ Returns:
319
+ An iterator of the collapsed IPv(4|6)Network objects.
320
+
321
+ Raises:
322
+ TypeError: If passed a list of mixed version objects.
323
+
324
+ """
325
+ addrs = []
326
+ ips = []
327
+ nets = []
328
+
329
+ # split IP addresses and networks
330
+ for ip in addresses:
331
+ if isinstance(ip, _BaseAddress):
332
+ if ips and ips[-1]._version != ip._version:
333
+ raise TypeError("%s and %s are not of the same version" % (
334
+ ip, ips[-1]))
335
+ ips.append(ip)
336
+ elif ip._prefixlen == ip._max_prefixlen:
337
+ if ips and ips[-1]._version != ip._version:
338
+ raise TypeError("%s and %s are not of the same version" % (
339
+ ip, ips[-1]))
340
+ try:
341
+ ips.append(ip.ip)
342
+ except AttributeError:
343
+ ips.append(ip.network_address)
344
+ else:
345
+ if nets and nets[-1]._version != ip._version:
346
+ raise TypeError("%s and %s are not of the same version" % (
347
+ ip, nets[-1]))
348
+ nets.append(ip)
349
+
350
+ # sort and dedup
351
+ ips = sorted(set(ips))
352
+
353
+ # find consecutive address ranges in the sorted sequence and summarize them
354
+ if ips:
355
+ for first, last in _find_address_range(ips):
356
+ addrs.extend(summarize_address_range(first, last))
357
+
358
+ return _collapse_addresses_internal(addrs + nets)
359
+
360
+
361
+ def get_mixed_type_key(obj):
362
+ """Return a key suitable for sorting between networks and addresses.
363
+
364
+ Address and Network objects are not sortable by default; they're
365
+ fundamentally different so the expression
366
+
367
+ IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24')
368
+
369
+ doesn't make any sense. There are some times however, where you may wish
370
+ to have ipaddress sort these for you anyway. If you need to do this, you
371
+ can use this function as the key= argument to sorted().
372
+
373
+ Args:
374
+ obj: either a Network or Address object.
375
+ Returns:
376
+ appropriate key.
377
+
378
+ """
379
+ if isinstance(obj, _BaseNetwork):
380
+ return obj._get_networks_key()
381
+ elif isinstance(obj, _BaseAddress):
382
+ return obj._get_address_key()
383
+ return NotImplemented
384
+
385
+
386
+ class _IPAddressBase:
387
+
388
+ """The mother class."""
389
+
390
+ __slots__ = ()
391
+
392
+ @property
393
+ def exploded(self):
394
+ """Return the longhand version of the IP address as a string."""
395
+ return self._explode_shorthand_ip_string()
396
+
397
+ @property
398
+ def compressed(self):
399
+ """Return the shorthand version of the IP address as a string."""
400
+ return str(self)
401
+
402
+ @property
403
+ def reverse_pointer(self):
404
+ """The name of the reverse DNS pointer for the IP address, e.g.:
405
+ >>> ipaddress.ip_address("127.0.0.1").reverse_pointer
406
+ '1.0.0.127.in-addr.arpa'
407
+ >>> ipaddress.ip_address("2001:db8::1").reverse_pointer
408
+ '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa'
409
+
410
+ """
411
+ return self._reverse_pointer()
412
+
413
+ @property
414
+ def version(self):
415
+ msg = '%200s has no version specified' % (type(self),)
416
+ raise NotImplementedError(msg)
417
+
418
+ def _check_int_address(self, address):
419
+ if address < 0:
420
+ msg = "%d (< 0) is not permitted as an IPv%d address"
421
+ raise AddressValueError(msg % (address, self._version))
422
+ if address > self._ALL_ONES:
423
+ msg = "%d (>= 2**%d) is not permitted as an IPv%d address"
424
+ raise AddressValueError(msg % (address, self._max_prefixlen,
425
+ self._version))
426
+
427
+ def _check_packed_address(self, address, expected_len):
428
+ address_len = len(address)
429
+ if address_len != expected_len:
430
+ msg = "%r (len %d != %d) is not permitted as an IPv%d address"
431
+ raise AddressValueError(msg % (address, address_len,
432
+ expected_len, self._version))
433
+
434
+ @classmethod
435
+ def _ip_int_from_prefix(cls, prefixlen):
436
+ """Turn the prefix length into a bitwise netmask
437
+
438
+ Args:
439
+ prefixlen: An integer, the prefix length.
440
+
441
+ Returns:
442
+ An integer.
443
+
444
+ """
445
+ return cls._ALL_ONES ^ (cls._ALL_ONES >> prefixlen)
446
+
447
+ @classmethod
448
+ def _prefix_from_ip_int(cls, ip_int):
449
+ """Return prefix length from the bitwise netmask.
450
+
451
+ Args:
452
+ ip_int: An integer, the netmask in expanded bitwise format
453
+
454
+ Returns:
455
+ An integer, the prefix length.
456
+
457
+ Raises:
458
+ ValueError: If the input intermingles zeroes & ones
459
+ """
460
+ trailing_zeroes = _count_righthand_zero_bits(ip_int,
461
+ cls._max_prefixlen)
462
+ prefixlen = cls._max_prefixlen - trailing_zeroes
463
+ leading_ones = ip_int >> trailing_zeroes
464
+ all_ones = (1 << prefixlen) - 1
465
+ if leading_ones != all_ones:
466
+ byteslen = cls._max_prefixlen // 8
467
+ details = ip_int.to_bytes(byteslen, 'big')
468
+ msg = 'Netmask pattern %r mixes zeroes & ones'
469
+ raise ValueError(msg % details)
470
+ return prefixlen
471
+
472
+ @classmethod
473
+ def _report_invalid_netmask(cls, netmask_str):
474
+ msg = '%r is not a valid netmask' % netmask_str
475
+ raise NetmaskValueError(msg) from None
476
+
477
+ @classmethod
478
+ def _prefix_from_prefix_string(cls, prefixlen_str):
479
+ """Return prefix length from a numeric string
480
+
481
+ Args:
482
+ prefixlen_str: The string to be converted
483
+
484
+ Returns:
485
+ An integer, the prefix length.
486
+
487
+ Raises:
488
+ NetmaskValueError: If the input is not a valid netmask
489
+ """
490
+ # int allows a leading +/- as well as surrounding whitespace,
491
+ # so we ensure that isn't the case
492
+ if not (prefixlen_str.isascii() and prefixlen_str.isdigit()):
493
+ cls._report_invalid_netmask(prefixlen_str)
494
+ try:
495
+ prefixlen = int(prefixlen_str)
496
+ except ValueError:
497
+ cls._report_invalid_netmask(prefixlen_str)
498
+ if not (0 <= prefixlen <= cls._max_prefixlen):
499
+ cls._report_invalid_netmask(prefixlen_str)
500
+ return prefixlen
501
+
502
+ @classmethod
503
+ def _prefix_from_ip_string(cls, ip_str):
504
+ """Turn a netmask/hostmask string into a prefix length
505
+
506
+ Args:
507
+ ip_str: The netmask/hostmask to be converted
508
+
509
+ Returns:
510
+ An integer, the prefix length.
511
+
512
+ Raises:
513
+ NetmaskValueError: If the input is not a valid netmask/hostmask
514
+ """
515
+ # Parse the netmask/hostmask like an IP address.
516
+ try:
517
+ ip_int = cls._ip_int_from_string(ip_str)
518
+ except AddressValueError:
519
+ cls._report_invalid_netmask(ip_str)
520
+
521
+ # Try matching a netmask (this would be /1*0*/ as a bitwise regexp).
522
+ # Note that the two ambiguous cases (all-ones and all-zeroes) are
523
+ # treated as netmasks.
524
+ try:
525
+ return cls._prefix_from_ip_int(ip_int)
526
+ except ValueError:
527
+ pass
528
+
529
+ # Invert the bits, and try matching a /0+1+/ hostmask instead.
530
+ ip_int ^= cls._ALL_ONES
531
+ try:
532
+ return cls._prefix_from_ip_int(ip_int)
533
+ except ValueError:
534
+ cls._report_invalid_netmask(ip_str)
535
+
536
+ @classmethod
537
+ def _split_addr_prefix(cls, address):
538
+ """Helper function to parse address of Network/Interface.
539
+
540
+ Arg:
541
+ address: Argument of Network/Interface.
542
+
543
+ Returns:
544
+ (addr, prefix) tuple.
545
+ """
546
+ # a packed address or integer
547
+ if isinstance(address, (bytes, int)):
548
+ return address, cls._max_prefixlen
549
+
550
+ if not isinstance(address, tuple):
551
+ # Assume input argument to be string or any object representation
552
+ # which converts into a formatted IP prefix string.
553
+ address = _split_optional_netmask(address)
554
+
555
+ # Constructing from a tuple (addr, [mask])
556
+ if len(address) > 1:
557
+ return address
558
+ return address[0], cls._max_prefixlen
559
+
560
+ def __reduce__(self):
561
+ return self.__class__, (str(self),)
562
+
563
+
564
+ _address_fmt_re = None
565
+
566
+ @functools.total_ordering
567
+ class _BaseAddress(_IPAddressBase):
568
+
569
+ """A generic IP object.
570
+
571
+ This IP class contains the version independent methods which are
572
+ used by single IP addresses.
573
+ """
574
+
575
+ __slots__ = ()
576
+
577
+ def __int__(self):
578
+ return self._ip
579
+
580
+ def __eq__(self, other):
581
+ try:
582
+ return (self._ip == other._ip
583
+ and self._version == other._version)
584
+ except AttributeError:
585
+ return NotImplemented
586
+
587
+ def __lt__(self, other):
588
+ if not isinstance(other, _BaseAddress):
589
+ return NotImplemented
590
+ if self._version != other._version:
591
+ raise TypeError('%s and %s are not of the same version' % (
592
+ self, other))
593
+ if self._ip != other._ip:
594
+ return self._ip < other._ip
595
+ return False
596
+
597
+ # Shorthand for Integer addition and subtraction. This is not
598
+ # meant to ever support addition/subtraction of addresses.
599
+ def __add__(self, other):
600
+ if not isinstance(other, int):
601
+ return NotImplemented
602
+ return self.__class__(int(self) + other)
603
+
604
+ def __sub__(self, other):
605
+ if not isinstance(other, int):
606
+ return NotImplemented
607
+ return self.__class__(int(self) - other)
608
+
609
+ def __repr__(self):
610
+ return '%s(%r)' % (self.__class__.__name__, str(self))
611
+
612
+ def __str__(self):
613
+ return str(self._string_from_ip_int(self._ip))
614
+
615
+ def __hash__(self):
616
+ return hash(hex(int(self._ip)))
617
+
618
+ def _get_address_key(self):
619
+ return (self._version, self)
620
+
621
+ def __reduce__(self):
622
+ return self.__class__, (self._ip,)
623
+
624
+ def __format__(self, fmt):
625
+ """Returns an IP address as a formatted string.
626
+
627
+ Supported presentation types are:
628
+ 's': returns the IP address as a string (default)
629
+ 'b': converts to binary and returns a zero-padded string
630
+ 'X' or 'x': converts to upper- or lower-case hex and returns a zero-padded string
631
+ 'n': the same as 'b' for IPv4 and 'x' for IPv6
632
+
633
+ For binary and hex presentation types, the alternate form specifier
634
+ '#' and the grouping option '_' are supported.
635
+ """
636
+
637
+ # Support string formatting
638
+ if not fmt or fmt[-1] == 's':
639
+ return format(str(self), fmt)
640
+
641
+ # From here on down, support for 'bnXx'
642
+ global _address_fmt_re
643
+ if _address_fmt_re is None:
644
+ import re
645
+ _address_fmt_re = re.compile('(#?)(_?)([xbnX])')
646
+
647
+ m = _address_fmt_re.fullmatch(fmt)
648
+ if not m:
649
+ return super().__format__(fmt)
650
+
651
+ alternate, grouping, fmt_base = m.groups()
652
+
653
+ # Set some defaults
654
+ if fmt_base == 'n':
655
+ if self._version == 4:
656
+ fmt_base = 'b' # Binary is default for ipv4
657
+ else:
658
+ fmt_base = 'x' # Hex is default for ipv6
659
+
660
+ if fmt_base == 'b':
661
+ padlen = self._max_prefixlen
662
+ else:
663
+ padlen = self._max_prefixlen // 4
664
+
665
+ if grouping:
666
+ padlen += padlen // 4 - 1
667
+
668
+ if alternate:
669
+ padlen += 2 # 0b or 0x
670
+
671
+ return format(int(self), f'{alternate}0{padlen}{grouping}{fmt_base}')
672
+
673
+
674
+ @functools.total_ordering
675
+ class _BaseNetwork(_IPAddressBase):
676
+ """A generic IP network object.
677
+
678
+ This IP class contains the version independent methods which are
679
+ used by networks.
680
+ """
681
+
682
+ def __repr__(self):
683
+ return '%s(%r)' % (self.__class__.__name__, str(self))
684
+
685
+ def __str__(self):
686
+ return '%s/%d' % (self.network_address, self.prefixlen)
687
+
688
+ def hosts(self):
689
+ """Generate Iterator over usable hosts in a network.
690
+
691
+ This is like __iter__ except it doesn't return the network
692
+ or broadcast addresses.
693
+
694
+ """
695
+ network = int(self.network_address)
696
+ broadcast = int(self.broadcast_address)
697
+ for x in range(network + 1, broadcast):
698
+ yield self._address_class(x)
699
+
700
+ def __iter__(self):
701
+ network = int(self.network_address)
702
+ broadcast = int(self.broadcast_address)
703
+ for x in range(network, broadcast + 1):
704
+ yield self._address_class(x)
705
+
706
+ def __getitem__(self, n):
707
+ network = int(self.network_address)
708
+ broadcast = int(self.broadcast_address)
709
+ if n >= 0:
710
+ if network + n > broadcast:
711
+ raise IndexError('address out of range')
712
+ return self._address_class(network + n)
713
+ else:
714
+ n += 1
715
+ if broadcast + n < network:
716
+ raise IndexError('address out of range')
717
+ return self._address_class(broadcast + n)
718
+
719
+ def __lt__(self, other):
720
+ if not isinstance(other, _BaseNetwork):
721
+ return NotImplemented
722
+ if self._version != other._version:
723
+ raise TypeError('%s and %s are not of the same version' % (
724
+ self, other))
725
+ if self.network_address != other.network_address:
726
+ return self.network_address < other.network_address
727
+ if self.netmask != other.netmask:
728
+ return self.netmask < other.netmask
729
+ return False
730
+
731
+ def __eq__(self, other):
732
+ try:
733
+ return (self._version == other._version and
734
+ self.network_address == other.network_address and
735
+ int(self.netmask) == int(other.netmask))
736
+ except AttributeError:
737
+ return NotImplemented
738
+
739
+ def __hash__(self):
740
+ return hash(int(self.network_address) ^ int(self.netmask))
741
+
742
+ def __contains__(self, other):
743
+ # always false if one is v4 and the other is v6.
744
+ if self._version != other._version:
745
+ return False
746
+ # dealing with another network.
747
+ if isinstance(other, _BaseNetwork):
748
+ return False
749
+ # dealing with another address
750
+ else:
751
+ # address
752
+ return other._ip & self.netmask._ip == self.network_address._ip
753
+
754
+ def overlaps(self, other):
755
+ """Tell if self is partly contained in other."""
756
+ return self.network_address in other or (
757
+ self.broadcast_address in other or (
758
+ other.network_address in self or (
759
+ other.broadcast_address in self)))
760
+
761
+ @functools.cached_property
762
+ def broadcast_address(self):
763
+ return self._address_class(int(self.network_address) |
764
+ int(self.hostmask))
765
+
766
+ @functools.cached_property
767
+ def hostmask(self):
768
+ return self._address_class(int(self.netmask) ^ self._ALL_ONES)
769
+
770
+ @property
771
+ def with_prefixlen(self):
772
+ return '%s/%d' % (self.network_address, self._prefixlen)
773
+
774
+ @property
775
+ def with_netmask(self):
776
+ return '%s/%s' % (self.network_address, self.netmask)
777
+
778
+ @property
779
+ def with_hostmask(self):
780
+ return '%s/%s' % (self.network_address, self.hostmask)
781
+
782
+ @property
783
+ def num_addresses(self):
784
+ """Number of hosts in the current subnet."""
785
+ return int(self.broadcast_address) - int(self.network_address) + 1
786
+
787
+ @property
788
+ def _address_class(self):
789
+ # Returning bare address objects (rather than interfaces) allows for
790
+ # more consistent behaviour across the network address, broadcast
791
+ # address and individual host addresses.
792
+ msg = '%200s has no associated address class' % (type(self),)
793
+ raise NotImplementedError(msg)
794
+
795
+ @property
796
+ def prefixlen(self):
797
+ return self._prefixlen
798
+
799
+ def address_exclude(self, other):
800
+ """Remove an address from a larger block.
801
+
802
+ For example:
803
+
804
+ addr1 = ip_network('192.0.2.0/28')
805
+ addr2 = ip_network('192.0.2.1/32')
806
+ list(addr1.address_exclude(addr2)) =
807
+ [IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'),
808
+ IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')]
809
+
810
+ or IPv6:
811
+
812
+ addr1 = ip_network('2001:db8::1/32')
813
+ addr2 = ip_network('2001:db8::1/128')
814
+ list(addr1.address_exclude(addr2)) =
815
+ [ip_network('2001:db8::1/128'),
816
+ ip_network('2001:db8::2/127'),
817
+ ip_network('2001:db8::4/126'),
818
+ ip_network('2001:db8::8/125'),
819
+ ...
820
+ ip_network('2001:db8:8000::/33')]
821
+
822
+ Args:
823
+ other: An IPv4Network or IPv6Network object of the same type.
824
+
825
+ Returns:
826
+ An iterator of the IPv(4|6)Network objects which is self
827
+ minus other.
828
+
829
+ Raises:
830
+ TypeError: If self and other are of differing address
831
+ versions, or if other is not a network object.
832
+ ValueError: If other is not completely contained by self.
833
+
834
+ """
835
+ if not self._version == other._version:
836
+ raise TypeError("%s and %s are not of the same version" % (
837
+ self, other))
838
+
839
+ if not isinstance(other, _BaseNetwork):
840
+ raise TypeError("%s is not a network object" % other)
841
+
842
+ if not other.subnet_of(self):
843
+ raise ValueError('%s not contained in %s' % (other, self))
844
+ if other == self:
845
+ return
846
+
847
+ # Make sure we're comparing the network of other.
848
+ other = other.__class__('%s/%s' % (other.network_address,
849
+ other.prefixlen))
850
+
851
+ s1, s2 = self.subnets()
852
+ while s1 != other and s2 != other:
853
+ if other.subnet_of(s1):
854
+ yield s2
855
+ s1, s2 = s1.subnets()
856
+ elif other.subnet_of(s2):
857
+ yield s1
858
+ s1, s2 = s2.subnets()
859
+ else:
860
+ # If we got here, there's a bug somewhere.
861
+ raise AssertionError('Error performing exclusion: '
862
+ 's1: %s s2: %s other: %s' %
863
+ (s1, s2, other))
864
+ if s1 == other:
865
+ yield s2
866
+ elif s2 == other:
867
+ yield s1
868
+ else:
869
+ # If we got here, there's a bug somewhere.
870
+ raise AssertionError('Error performing exclusion: '
871
+ 's1: %s s2: %s other: %s' %
872
+ (s1, s2, other))
873
+
874
+ def compare_networks(self, other):
875
+ """Compare two IP objects.
876
+
877
+ This is only concerned about the comparison of the integer
878
+ representation of the network addresses. This means that the
879
+ host bits aren't considered at all in this method. If you want
880
+ to compare host bits, you can easily enough do a
881
+ 'HostA._ip < HostB._ip'
882
+
883
+ Args:
884
+ other: An IP object.
885
+
886
+ Returns:
887
+ If the IP versions of self and other are the same, returns:
888
+
889
+ -1 if self < other:
890
+ eg: IPv4Network('192.0.2.0/25') < IPv4Network('192.0.2.128/25')
891
+ IPv6Network('2001:db8::1000/124') <
892
+ IPv6Network('2001:db8::2000/124')
893
+ 0 if self == other
894
+ eg: IPv4Network('192.0.2.0/24') == IPv4Network('192.0.2.0/24')
895
+ IPv6Network('2001:db8::1000/124') ==
896
+ IPv6Network('2001:db8::1000/124')
897
+ 1 if self > other
898
+ eg: IPv4Network('192.0.2.128/25') > IPv4Network('192.0.2.0/25')
899
+ IPv6Network('2001:db8::2000/124') >
900
+ IPv6Network('2001:db8::1000/124')
901
+
902
+ Raises:
903
+ TypeError if the IP versions are different.
904
+
905
+ """
906
+ # does this need to raise a ValueError?
907
+ if self._version != other._version:
908
+ raise TypeError('%s and %s are not of the same type' % (
909
+ self, other))
910
+ # self._version == other._version below here:
911
+ if self.network_address < other.network_address:
912
+ return -1
913
+ if self.network_address > other.network_address:
914
+ return 1
915
+ # self.network_address == other.network_address below here:
916
+ if self.netmask < other.netmask:
917
+ return -1
918
+ if self.netmask > other.netmask:
919
+ return 1
920
+ return 0
921
+
922
+ def _get_networks_key(self):
923
+ """Network-only key function.
924
+
925
+ Returns an object that identifies this address' network and
926
+ netmask. This function is a suitable "key" argument for sorted()
927
+ and list.sort().
928
+
929
+ """
930
+ return (self._version, self.network_address, self.netmask)
931
+
932
+ def subnets(self, prefixlen_diff=1, new_prefix=None):
933
+ """The subnets which join to make the current subnet.
934
+
935
+ In the case that self contains only one IP
936
+ (self._prefixlen == 32 for IPv4 or self._prefixlen == 128
937
+ for IPv6), yield an iterator with just ourself.
938
+
939
+ Args:
940
+ prefixlen_diff: An integer, the amount the prefix length
941
+ should be increased by. This should not be set if
942
+ new_prefix is also set.
943
+ new_prefix: The desired new prefix length. This must be a
944
+ larger number (smaller prefix) than the existing prefix.
945
+ This should not be set if prefixlen_diff is also set.
946
+
947
+ Returns:
948
+ An iterator of IPv(4|6) objects.
949
+
950
+ Raises:
951
+ ValueError: The prefixlen_diff is too small or too large.
952
+ OR
953
+ prefixlen_diff and new_prefix are both set or new_prefix
954
+ is a smaller number than the current prefix (smaller
955
+ number means a larger network)
956
+
957
+ """
958
+ if self._prefixlen == self._max_prefixlen:
959
+ yield self
960
+ return
961
+
962
+ if new_prefix is not None:
963
+ if new_prefix < self._prefixlen:
964
+ raise ValueError('new prefix must be longer')
965
+ if prefixlen_diff != 1:
966
+ raise ValueError('cannot set prefixlen_diff and new_prefix')
967
+ prefixlen_diff = new_prefix - self._prefixlen
968
+
969
+ if prefixlen_diff < 0:
970
+ raise ValueError('prefix length diff must be > 0')
971
+ new_prefixlen = self._prefixlen + prefixlen_diff
972
+
973
+ if new_prefixlen > self._max_prefixlen:
974
+ raise ValueError(
975
+ 'prefix length diff %d is invalid for netblock %s' % (
976
+ new_prefixlen, self))
977
+
978
+ start = int(self.network_address)
979
+ end = int(self.broadcast_address) + 1
980
+ step = (int(self.hostmask) + 1) >> prefixlen_diff
981
+ for new_addr in range(start, end, step):
982
+ current = self.__class__((new_addr, new_prefixlen))
983
+ yield current
984
+
985
+ def supernet(self, prefixlen_diff=1, new_prefix=None):
986
+ """The supernet containing the current network.
987
+
988
+ Args:
989
+ prefixlen_diff: An integer, the amount the prefix length of
990
+ the network should be decreased by. For example, given a
991
+ /24 network and a prefixlen_diff of 3, a supernet with a
992
+ /21 netmask is returned.
993
+
994
+ Returns:
995
+ An IPv4 network object.
996
+
997
+ Raises:
998
+ ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have
999
+ a negative prefix length.
1000
+ OR
1001
+ If prefixlen_diff and new_prefix are both set or new_prefix is a
1002
+ larger number than the current prefix (larger number means a
1003
+ smaller network)
1004
+
1005
+ """
1006
+ if self._prefixlen == 0:
1007
+ return self
1008
+
1009
+ if new_prefix is not None:
1010
+ if new_prefix > self._prefixlen:
1011
+ raise ValueError('new prefix must be shorter')
1012
+ if prefixlen_diff != 1:
1013
+ raise ValueError('cannot set prefixlen_diff and new_prefix')
1014
+ prefixlen_diff = self._prefixlen - new_prefix
1015
+
1016
+ new_prefixlen = self.prefixlen - prefixlen_diff
1017
+ if new_prefixlen < 0:
1018
+ raise ValueError(
1019
+ 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
1020
+ (self.prefixlen, prefixlen_diff))
1021
+ return self.__class__((
1022
+ int(self.network_address) & (int(self.netmask) << prefixlen_diff),
1023
+ new_prefixlen
1024
+ ))
1025
+
1026
+ @property
1027
+ def is_multicast(self):
1028
+ """Test if the address is reserved for multicast use.
1029
+
1030
+ Returns:
1031
+ A boolean, True if the address is a multicast address.
1032
+ See RFC 2373 2.7 for details.
1033
+
1034
+ """
1035
+ return (self.network_address.is_multicast and
1036
+ self.broadcast_address.is_multicast)
1037
+
1038
+ @staticmethod
1039
+ def _is_subnet_of(a, b):
1040
+ try:
1041
+ # Always false if one is v4 and the other is v6.
1042
+ if a._version != b._version:
1043
+ raise TypeError(f"{a} and {b} are not of the same version")
1044
+ return (b.network_address <= a.network_address and
1045
+ b.broadcast_address >= a.broadcast_address)
1046
+ except AttributeError:
1047
+ raise TypeError(f"Unable to test subnet containment "
1048
+ f"between {a} and {b}")
1049
+
1050
+ def subnet_of(self, other):
1051
+ """Return True if this network is a subnet of other."""
1052
+ return self._is_subnet_of(self, other)
1053
+
1054
+ def supernet_of(self, other):
1055
+ """Return True if this network is a supernet of other."""
1056
+ return self._is_subnet_of(other, self)
1057
+
1058
+ @property
1059
+ def is_reserved(self):
1060
+ """Test if the address is otherwise IETF reserved.
1061
+
1062
+ Returns:
1063
+ A boolean, True if the address is within one of the
1064
+ reserved IPv6 Network ranges.
1065
+
1066
+ """
1067
+ return (self.network_address.is_reserved and
1068
+ self.broadcast_address.is_reserved)
1069
+
1070
+ @property
1071
+ def is_link_local(self):
1072
+ """Test if the address is reserved for link-local.
1073
+
1074
+ Returns:
1075
+ A boolean, True if the address is reserved per RFC 4291.
1076
+
1077
+ """
1078
+ return (self.network_address.is_link_local and
1079
+ self.broadcast_address.is_link_local)
1080
+
1081
+ @property
1082
+ def is_private(self):
1083
+ """Test if this network belongs to a private range.
1084
+
1085
+ Returns:
1086
+ A boolean, True if the network is reserved per
1087
+ iana-ipv4-special-registry or iana-ipv6-special-registry.
1088
+
1089
+ """
1090
+ return any(self.network_address in priv_network and
1091
+ self.broadcast_address in priv_network
1092
+ for priv_network in self._constants._private_networks) and all(
1093
+ self.network_address not in network and
1094
+ self.broadcast_address not in network
1095
+ for network in self._constants._private_networks_exceptions
1096
+ )
1097
+
1098
+ @property
1099
+ def is_global(self):
1100
+ """Test if this address is allocated for public networks.
1101
+
1102
+ Returns:
1103
+ A boolean, True if the address is not reserved per
1104
+ iana-ipv4-special-registry or iana-ipv6-special-registry.
1105
+
1106
+ """
1107
+ return not self.is_private
1108
+
1109
+ @property
1110
+ def is_unspecified(self):
1111
+ """Test if the address is unspecified.
1112
+
1113
+ Returns:
1114
+ A boolean, True if this is the unspecified address as defined in
1115
+ RFC 2373 2.5.2.
1116
+
1117
+ """
1118
+ return (self.network_address.is_unspecified and
1119
+ self.broadcast_address.is_unspecified)
1120
+
1121
+ @property
1122
+ def is_loopback(self):
1123
+ """Test if the address is a loopback address.
1124
+
1125
+ Returns:
1126
+ A boolean, True if the address is a loopback address as defined in
1127
+ RFC 2373 2.5.3.
1128
+
1129
+ """
1130
+ return (self.network_address.is_loopback and
1131
+ self.broadcast_address.is_loopback)
1132
+
1133
+
1134
+ class _BaseConstants:
1135
+
1136
+ _private_networks = []
1137
+
1138
+
1139
+ _BaseNetwork._constants = _BaseConstants
1140
+
1141
+
1142
+ class _BaseV4:
1143
+
1144
+ """Base IPv4 object.
1145
+
1146
+ The following methods are used by IPv4 objects in both single IP
1147
+ addresses and networks.
1148
+
1149
+ """
1150
+
1151
+ __slots__ = ()
1152
+ _version = 4
1153
+ # Equivalent to 255.255.255.255 or 32 bits of 1's.
1154
+ _ALL_ONES = (2**IPV4LENGTH) - 1
1155
+
1156
+ _max_prefixlen = IPV4LENGTH
1157
+ # There are only a handful of valid v4 netmasks, so we cache them all
1158
+ # when constructed (see _make_netmask()).
1159
+ _netmask_cache = {}
1160
+
1161
+ def _explode_shorthand_ip_string(self):
1162
+ return str(self)
1163
+
1164
+ @classmethod
1165
+ def _make_netmask(cls, arg):
1166
+ """Make a (netmask, prefix_len) tuple from the given argument.
1167
+
1168
+ Argument can be:
1169
+ - an integer (the prefix length)
1170
+ - a string representing the prefix length (e.g. "24")
1171
+ - a string representing the prefix netmask (e.g. "255.255.255.0")
1172
+ """
1173
+ if arg not in cls._netmask_cache:
1174
+ if isinstance(arg, int):
1175
+ prefixlen = arg
1176
+ if not (0 <= prefixlen <= cls._max_prefixlen):
1177
+ cls._report_invalid_netmask(prefixlen)
1178
+ else:
1179
+ try:
1180
+ # Check for a netmask in prefix length form
1181
+ prefixlen = cls._prefix_from_prefix_string(arg)
1182
+ except NetmaskValueError:
1183
+ # Check for a netmask or hostmask in dotted-quad form.
1184
+ # This may raise NetmaskValueError.
1185
+ prefixlen = cls._prefix_from_ip_string(arg)
1186
+ netmask = IPv4Address(cls._ip_int_from_prefix(prefixlen))
1187
+ cls._netmask_cache[arg] = netmask, prefixlen
1188
+ return cls._netmask_cache[arg]
1189
+
1190
+ @classmethod
1191
+ def _ip_int_from_string(cls, ip_str):
1192
+ """Turn the given IP string into an integer for comparison.
1193
+
1194
+ Args:
1195
+ ip_str: A string, the IP ip_str.
1196
+
1197
+ Returns:
1198
+ The IP ip_str as an integer.
1199
+
1200
+ Raises:
1201
+ AddressValueError: if ip_str isn't a valid IPv4 Address.
1202
+
1203
+ """
1204
+ if not ip_str:
1205
+ raise AddressValueError('Address cannot be empty')
1206
+
1207
+ octets = ip_str.split('.')
1208
+ if len(octets) != 4:
1209
+ raise AddressValueError("Expected 4 octets in %r" % ip_str)
1210
+
1211
+ try:
1212
+ return int.from_bytes(map(cls._parse_octet, octets), 'big')
1213
+ except ValueError as exc:
1214
+ raise AddressValueError("%s in %r" % (exc, ip_str)) from None
1215
+
1216
+ @classmethod
1217
+ def _parse_octet(cls, octet_str):
1218
+ """Convert a decimal octet into an integer.
1219
+
1220
+ Args:
1221
+ octet_str: A string, the number to parse.
1222
+
1223
+ Returns:
1224
+ The octet as an integer.
1225
+
1226
+ Raises:
1227
+ ValueError: if the octet isn't strictly a decimal from [0..255].
1228
+
1229
+ """
1230
+ if not octet_str:
1231
+ raise ValueError("Empty octet not permitted")
1232
+ # Reject non-ASCII digits.
1233
+ if not (octet_str.isascii() and octet_str.isdigit()):
1234
+ msg = "Only decimal digits permitted in %r"
1235
+ raise ValueError(msg % octet_str)
1236
+ # We do the length check second, since the invalid character error
1237
+ # is likely to be more informative for the user
1238
+ if len(octet_str) > 3:
1239
+ msg = "At most 3 characters permitted in %r"
1240
+ raise ValueError(msg % octet_str)
1241
+ # Handle leading zeros as strict as glibc's inet_pton()
1242
+ # See security bug bpo-36384
1243
+ if octet_str != '0' and octet_str[0] == '0':
1244
+ msg = "Leading zeros are not permitted in %r"
1245
+ raise ValueError(msg % octet_str)
1246
+ # Convert to integer (we know digits are legal)
1247
+ octet_int = int(octet_str, 10)
1248
+ if octet_int > 255:
1249
+ raise ValueError("Octet %d (> 255) not permitted" % octet_int)
1250
+ return octet_int
1251
+
1252
+ @classmethod
1253
+ def _string_from_ip_int(cls, ip_int):
1254
+ """Turns a 32-bit integer into dotted decimal notation.
1255
+
1256
+ Args:
1257
+ ip_int: An integer, the IP address.
1258
+
1259
+ Returns:
1260
+ The IP address as a string in dotted decimal notation.
1261
+
1262
+ """
1263
+ return '.'.join(map(str, ip_int.to_bytes(4, 'big')))
1264
+
1265
+ def _reverse_pointer(self):
1266
+ """Return the reverse DNS pointer name for the IPv4 address.
1267
+
1268
+ This implements the method described in RFC1035 3.5.
1269
+
1270
+ """
1271
+ reverse_octets = str(self).split('.')[::-1]
1272
+ return '.'.join(reverse_octets) + '.in-addr.arpa'
1273
+
1274
+ @property
1275
+ def max_prefixlen(self):
1276
+ return self._max_prefixlen
1277
+
1278
+ @property
1279
+ def version(self):
1280
+ return self._version
1281
+
1282
+
1283
+ class IPv4Address(_BaseV4, _BaseAddress):
1284
+
1285
+ """Represent and manipulate single IPv4 Addresses."""
1286
+
1287
+ __slots__ = ('_ip', '__weakref__')
1288
+
1289
+ def __init__(self, address):
1290
+
1291
+ """
1292
+ Args:
1293
+ address: A string or integer representing the IP
1294
+
1295
+ Additionally, an integer can be passed, so
1296
+ IPv4Address('192.0.2.1') == IPv4Address(3221225985).
1297
+ or, more generally
1298
+ IPv4Address(int(IPv4Address('192.0.2.1'))) ==
1299
+ IPv4Address('192.0.2.1')
1300
+
1301
+ Raises:
1302
+ AddressValueError: If ipaddress isn't a valid IPv4 address.
1303
+
1304
+ """
1305
+ # Efficient constructor from integer.
1306
+ if isinstance(address, int):
1307
+ self._check_int_address(address)
1308
+ self._ip = address
1309
+ return
1310
+
1311
+ # Constructing from a packed address
1312
+ if isinstance(address, bytes):
1313
+ self._check_packed_address(address, 4)
1314
+ self._ip = int.from_bytes(address) # big endian
1315
+ return
1316
+
1317
+ # Assume input argument to be string or any object representation
1318
+ # which converts into a formatted IP string.
1319
+ addr_str = str(address)
1320
+ if '/' in addr_str:
1321
+ raise AddressValueError(f"Unexpected '/' in {address!r}")
1322
+ self._ip = self._ip_int_from_string(addr_str)
1323
+
1324
+ @property
1325
+ def packed(self):
1326
+ """The binary representation of this address."""
1327
+ return v4_int_to_packed(self._ip)
1328
+
1329
+ @property
1330
+ def is_reserved(self):
1331
+ """Test if the address is otherwise IETF reserved.
1332
+
1333
+ Returns:
1334
+ A boolean, True if the address is within the
1335
+ reserved IPv4 Network range.
1336
+
1337
+ """
1338
+ return self in self._constants._reserved_network
1339
+
1340
+ @property
1341
+ @functools.lru_cache()
1342
+ def is_private(self):
1343
+ """``True`` if the address is defined as not globally reachable by
1344
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1345
+ (for IPv6) with the following exceptions:
1346
+
1347
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
1348
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1349
+ semantics of the underlying IPv4 addresses and the following condition holds
1350
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1351
+
1352
+ address.is_private == address.ipv4_mapped.is_private
1353
+
1354
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
1355
+ IPv4 range where they are both ``False``.
1356
+ """
1357
+ return (
1358
+ any(self in net for net in self._constants._private_networks)
1359
+ and all(self not in net for net in self._constants._private_networks_exceptions)
1360
+ )
1361
+
1362
+ @property
1363
+ @functools.lru_cache()
1364
+ def is_global(self):
1365
+ """``True`` if the address is defined as globally reachable by
1366
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
1367
+ (for IPv6) with the following exception:
1368
+
1369
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
1370
+ semantics of the underlying IPv4 addresses and the following condition holds
1371
+ (see :attr:`IPv6Address.ipv4_mapped`)::
1372
+
1373
+ address.is_global == address.ipv4_mapped.is_global
1374
+
1375
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
1376
+ IPv4 range where they are both ``False``.
1377
+ """
1378
+ return self not in self._constants._public_network and not self.is_private
1379
+
1380
+ @property
1381
+ def is_multicast(self):
1382
+ """Test if the address is reserved for multicast use.
1383
+
1384
+ Returns:
1385
+ A boolean, True if the address is multicast.
1386
+ See RFC 3171 for details.
1387
+
1388
+ """
1389
+ return self in self._constants._multicast_network
1390
+
1391
+ @property
1392
+ def is_unspecified(self):
1393
+ """Test if the address is unspecified.
1394
+
1395
+ Returns:
1396
+ A boolean, True if this is the unspecified address as defined in
1397
+ RFC 5735 3.
1398
+
1399
+ """
1400
+ return self == self._constants._unspecified_address
1401
+
1402
+ @property
1403
+ def is_loopback(self):
1404
+ """Test if the address is a loopback address.
1405
+
1406
+ Returns:
1407
+ A boolean, True if the address is a loopback per RFC 3330.
1408
+
1409
+ """
1410
+ return self in self._constants._loopback_network
1411
+
1412
+ @property
1413
+ def is_link_local(self):
1414
+ """Test if the address is reserved for link-local.
1415
+
1416
+ Returns:
1417
+ A boolean, True if the address is link-local per RFC 3927.
1418
+
1419
+ """
1420
+ return self in self._constants._linklocal_network
1421
+
1422
+
1423
+ class IPv4Interface(IPv4Address):
1424
+
1425
+ def __init__(self, address):
1426
+ addr, mask = self._split_addr_prefix(address)
1427
+
1428
+ IPv4Address.__init__(self, addr)
1429
+ self.network = IPv4Network((addr, mask), strict=False)
1430
+ self.netmask = self.network.netmask
1431
+ self._prefixlen = self.network._prefixlen
1432
+
1433
+ @functools.cached_property
1434
+ def hostmask(self):
1435
+ return self.network.hostmask
1436
+
1437
+ def __str__(self):
1438
+ return '%s/%d' % (self._string_from_ip_int(self._ip),
1439
+ self._prefixlen)
1440
+
1441
+ def __eq__(self, other):
1442
+ address_equal = IPv4Address.__eq__(self, other)
1443
+ if address_equal is NotImplemented or not address_equal:
1444
+ return address_equal
1445
+ try:
1446
+ return self.network == other.network
1447
+ except AttributeError:
1448
+ # An interface with an associated network is NOT the
1449
+ # same as an unassociated address. That's why the hash
1450
+ # takes the extra info into account.
1451
+ return False
1452
+
1453
+ def __lt__(self, other):
1454
+ address_less = IPv4Address.__lt__(self, other)
1455
+ if address_less is NotImplemented:
1456
+ return NotImplemented
1457
+ try:
1458
+ return (self.network < other.network or
1459
+ self.network == other.network and address_less)
1460
+ except AttributeError:
1461
+ # We *do* allow addresses and interfaces to be sorted. The
1462
+ # unassociated address is considered less than all interfaces.
1463
+ return False
1464
+
1465
+ def __hash__(self):
1466
+ return hash((self._ip, self._prefixlen, int(self.network.network_address)))
1467
+
1468
+ __reduce__ = _IPAddressBase.__reduce__
1469
+
1470
+ @property
1471
+ def ip(self):
1472
+ return IPv4Address(self._ip)
1473
+
1474
+ @property
1475
+ def with_prefixlen(self):
1476
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
1477
+ self._prefixlen)
1478
+
1479
+ @property
1480
+ def with_netmask(self):
1481
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
1482
+ self.netmask)
1483
+
1484
+ @property
1485
+ def with_hostmask(self):
1486
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
1487
+ self.hostmask)
1488
+
1489
+
1490
+ class IPv4Network(_BaseV4, _BaseNetwork):
1491
+
1492
+ """This class represents and manipulates 32-bit IPv4 network + addresses..
1493
+
1494
+ Attributes: [examples for IPv4Network('192.0.2.0/27')]
1495
+ .network_address: IPv4Address('192.0.2.0')
1496
+ .hostmask: IPv4Address('0.0.0.31')
1497
+ .broadcast_address: IPv4Address('192.0.2.32')
1498
+ .netmask: IPv4Address('255.255.255.224')
1499
+ .prefixlen: 27
1500
+
1501
+ """
1502
+ # Class to use when creating address objects
1503
+ _address_class = IPv4Address
1504
+
1505
+ def __init__(self, address, strict=True):
1506
+ """Instantiate a new IPv4 network object.
1507
+
1508
+ Args:
1509
+ address: A string or integer representing the IP [& network].
1510
+ '192.0.2.0/24'
1511
+ '192.0.2.0/255.255.255.0'
1512
+ '192.0.2.0/0.0.0.255'
1513
+ are all functionally the same in IPv4. Similarly,
1514
+ '192.0.2.1'
1515
+ '192.0.2.1/255.255.255.255'
1516
+ '192.0.2.1/32'
1517
+ are also functionally equivalent. That is to say, failing to
1518
+ provide a subnetmask will create an object with a mask of /32.
1519
+
1520
+ If the mask (portion after the / in the argument) is given in
1521
+ dotted quad form, it is treated as a netmask if it starts with a
1522
+ non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
1523
+ starts with a zero field (e.g. 0.255.255.255 == /8), with the
1524
+ single exception of an all-zero mask which is treated as a
1525
+ netmask == /0. If no mask is given, a default of /32 is used.
1526
+
1527
+ Additionally, an integer can be passed, so
1528
+ IPv4Network('192.0.2.1') == IPv4Network(3221225985)
1529
+ or, more generally
1530
+ IPv4Interface(int(IPv4Interface('192.0.2.1'))) ==
1531
+ IPv4Interface('192.0.2.1')
1532
+
1533
+ Raises:
1534
+ AddressValueError: If ipaddress isn't a valid IPv4 address.
1535
+ NetmaskValueError: If the netmask isn't valid for
1536
+ an IPv4 address.
1537
+ ValueError: If strict is True and a network address is not
1538
+ supplied.
1539
+ """
1540
+ addr, mask = self._split_addr_prefix(address)
1541
+
1542
+ self.network_address = IPv4Address(addr)
1543
+ self.netmask, self._prefixlen = self._make_netmask(mask)
1544
+ packed = int(self.network_address)
1545
+ if packed & int(self.netmask) != packed:
1546
+ if strict:
1547
+ raise ValueError('%s has host bits set' % self)
1548
+ else:
1549
+ self.network_address = IPv4Address(packed &
1550
+ int(self.netmask))
1551
+
1552
+ if self._prefixlen == (self._max_prefixlen - 1):
1553
+ self.hosts = self.__iter__
1554
+ elif self._prefixlen == (self._max_prefixlen):
1555
+ self.hosts = lambda: [IPv4Address(addr)]
1556
+
1557
+ @property
1558
+ @functools.lru_cache()
1559
+ def is_global(self):
1560
+ """Test if this address is allocated for public networks.
1561
+
1562
+ Returns:
1563
+ A boolean, True if the address is not reserved per
1564
+ iana-ipv4-special-registry.
1565
+
1566
+ """
1567
+ return (not (self.network_address in IPv4Network('100.64.0.0/10') and
1568
+ self.broadcast_address in IPv4Network('100.64.0.0/10')) and
1569
+ not self.is_private)
1570
+
1571
+
1572
+ class _IPv4Constants:
1573
+ _linklocal_network = IPv4Network('169.254.0.0/16')
1574
+
1575
+ _loopback_network = IPv4Network('127.0.0.0/8')
1576
+
1577
+ _multicast_network = IPv4Network('224.0.0.0/4')
1578
+
1579
+ _public_network = IPv4Network('100.64.0.0/10')
1580
+
1581
+ # Not globally reachable address blocks listed on
1582
+ # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
1583
+ _private_networks = [
1584
+ IPv4Network('0.0.0.0/8'),
1585
+ IPv4Network('10.0.0.0/8'),
1586
+ IPv4Network('127.0.0.0/8'),
1587
+ IPv4Network('169.254.0.0/16'),
1588
+ IPv4Network('172.16.0.0/12'),
1589
+ IPv4Network('192.0.0.0/24'),
1590
+ IPv4Network('192.0.0.170/31'),
1591
+ IPv4Network('192.0.2.0/24'),
1592
+ IPv4Network('192.168.0.0/16'),
1593
+ IPv4Network('198.18.0.0/15'),
1594
+ IPv4Network('198.51.100.0/24'),
1595
+ IPv4Network('203.0.113.0/24'),
1596
+ IPv4Network('240.0.0.0/4'),
1597
+ IPv4Network('255.255.255.255/32'),
1598
+ ]
1599
+
1600
+ _private_networks_exceptions = [
1601
+ IPv4Network('192.0.0.9/32'),
1602
+ IPv4Network('192.0.0.10/32'),
1603
+ ]
1604
+
1605
+ _reserved_network = IPv4Network('240.0.0.0/4')
1606
+
1607
+ _unspecified_address = IPv4Address('0.0.0.0')
1608
+
1609
+
1610
+ IPv4Address._constants = _IPv4Constants
1611
+ IPv4Network._constants = _IPv4Constants
1612
+
1613
+
1614
+ class _BaseV6:
1615
+
1616
+ """Base IPv6 object.
1617
+
1618
+ The following methods are used by IPv6 objects in both single IP
1619
+ addresses and networks.
1620
+
1621
+ """
1622
+
1623
+ __slots__ = ()
1624
+ _version = 6
1625
+ _ALL_ONES = (2**IPV6LENGTH) - 1
1626
+ _HEXTET_COUNT = 8
1627
+ _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef')
1628
+ _max_prefixlen = IPV6LENGTH
1629
+
1630
+ # There are only a bunch of valid v6 netmasks, so we cache them all
1631
+ # when constructed (see _make_netmask()).
1632
+ _netmask_cache = {}
1633
+
1634
+ @classmethod
1635
+ def _make_netmask(cls, arg):
1636
+ """Make a (netmask, prefix_len) tuple from the given argument.
1637
+
1638
+ Argument can be:
1639
+ - an integer (the prefix length)
1640
+ - a string representing the prefix length (e.g. "24")
1641
+ - a string representing the prefix netmask (e.g. "255.255.255.0")
1642
+ """
1643
+ if arg not in cls._netmask_cache:
1644
+ if isinstance(arg, int):
1645
+ prefixlen = arg
1646
+ if not (0 <= prefixlen <= cls._max_prefixlen):
1647
+ cls._report_invalid_netmask(prefixlen)
1648
+ else:
1649
+ prefixlen = cls._prefix_from_prefix_string(arg)
1650
+ netmask = IPv6Address(cls._ip_int_from_prefix(prefixlen))
1651
+ cls._netmask_cache[arg] = netmask, prefixlen
1652
+ return cls._netmask_cache[arg]
1653
+
1654
+ @classmethod
1655
+ def _ip_int_from_string(cls, ip_str):
1656
+ """Turn an IPv6 ip_str into an integer.
1657
+
1658
+ Args:
1659
+ ip_str: A string, the IPv6 ip_str.
1660
+
1661
+ Returns:
1662
+ An int, the IPv6 address
1663
+
1664
+ Raises:
1665
+ AddressValueError: if ip_str isn't a valid IPv6 Address.
1666
+
1667
+ """
1668
+ if not ip_str:
1669
+ raise AddressValueError('Address cannot be empty')
1670
+
1671
+ parts = ip_str.split(':')
1672
+
1673
+ # An IPv6 address needs at least 2 colons (3 parts).
1674
+ _min_parts = 3
1675
+ if len(parts) < _min_parts:
1676
+ msg = "At least %d parts expected in %r" % (_min_parts, ip_str)
1677
+ raise AddressValueError(msg)
1678
+
1679
+ # If the address has an IPv4-style suffix, convert it to hexadecimal.
1680
+ if '.' in parts[-1]:
1681
+ try:
1682
+ ipv4_int = IPv4Address(parts.pop())._ip
1683
+ except AddressValueError as exc:
1684
+ raise AddressValueError("%s in %r" % (exc, ip_str)) from None
1685
+ parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF))
1686
+ parts.append('%x' % (ipv4_int & 0xFFFF))
1687
+
1688
+ # An IPv6 address can't have more than 8 colons (9 parts).
1689
+ # The extra colon comes from using the "::" notation for a single
1690
+ # leading or trailing zero part.
1691
+ _max_parts = cls._HEXTET_COUNT + 1
1692
+ if len(parts) > _max_parts:
1693
+ msg = "At most %d colons permitted in %r" % (_max_parts - 1, ip_str)
1694
+ raise AddressValueError(msg)
1695
+
1696
+ # Disregarding the endpoints, find '::' with nothing in between.
1697
+ # This indicates that a run of zeroes has been skipped.
1698
+ skip_index = None
1699
+ for i in range(1, len(parts) - 1):
1700
+ if not parts[i]:
1701
+ if skip_index is not None:
1702
+ # Can't have more than one '::'
1703
+ msg = "At most one '::' permitted in %r" % ip_str
1704
+ raise AddressValueError(msg)
1705
+ skip_index = i
1706
+
1707
+ # parts_hi is the number of parts to copy from above/before the '::'
1708
+ # parts_lo is the number of parts to copy from below/after the '::'
1709
+ if skip_index is not None:
1710
+ # If we found a '::', then check if it also covers the endpoints.
1711
+ parts_hi = skip_index
1712
+ parts_lo = len(parts) - skip_index - 1
1713
+ if not parts[0]:
1714
+ parts_hi -= 1
1715
+ if parts_hi:
1716
+ msg = "Leading ':' only permitted as part of '::' in %r"
1717
+ raise AddressValueError(msg % ip_str) # ^: requires ^::
1718
+ if not parts[-1]:
1719
+ parts_lo -= 1
1720
+ if parts_lo:
1721
+ msg = "Trailing ':' only permitted as part of '::' in %r"
1722
+ raise AddressValueError(msg % ip_str) # :$ requires ::$
1723
+ parts_skipped = cls._HEXTET_COUNT - (parts_hi + parts_lo)
1724
+ if parts_skipped < 1:
1725
+ msg = "Expected at most %d other parts with '::' in %r"
1726
+ raise AddressValueError(msg % (cls._HEXTET_COUNT - 1, ip_str))
1727
+ else:
1728
+ # Otherwise, allocate the entire address to parts_hi. The
1729
+ # endpoints could still be empty, but _parse_hextet() will check
1730
+ # for that.
1731
+ if len(parts) != cls._HEXTET_COUNT:
1732
+ msg = "Exactly %d parts expected without '::' in %r"
1733
+ raise AddressValueError(msg % (cls._HEXTET_COUNT, ip_str))
1734
+ if not parts[0]:
1735
+ msg = "Leading ':' only permitted as part of '::' in %r"
1736
+ raise AddressValueError(msg % ip_str) # ^: requires ^::
1737
+ if not parts[-1]:
1738
+ msg = "Trailing ':' only permitted as part of '::' in %r"
1739
+ raise AddressValueError(msg % ip_str) # :$ requires ::$
1740
+ parts_hi = len(parts)
1741
+ parts_lo = 0
1742
+ parts_skipped = 0
1743
+
1744
+ try:
1745
+ # Now, parse the hextets into a 128-bit integer.
1746
+ ip_int = 0
1747
+ for i in range(parts_hi):
1748
+ ip_int <<= 16
1749
+ ip_int |= cls._parse_hextet(parts[i])
1750
+ ip_int <<= 16 * parts_skipped
1751
+ for i in range(-parts_lo, 0):
1752
+ ip_int <<= 16
1753
+ ip_int |= cls._parse_hextet(parts[i])
1754
+ return ip_int
1755
+ except ValueError as exc:
1756
+ raise AddressValueError("%s in %r" % (exc, ip_str)) from None
1757
+
1758
+ @classmethod
1759
+ def _parse_hextet(cls, hextet_str):
1760
+ """Convert an IPv6 hextet string into an integer.
1761
+
1762
+ Args:
1763
+ hextet_str: A string, the number to parse.
1764
+
1765
+ Returns:
1766
+ The hextet as an integer.
1767
+
1768
+ Raises:
1769
+ ValueError: if the input isn't strictly a hex number from
1770
+ [0..FFFF].
1771
+
1772
+ """
1773
+ # Reject non-ASCII digits.
1774
+ if not cls._HEX_DIGITS.issuperset(hextet_str):
1775
+ raise ValueError("Only hex digits permitted in %r" % hextet_str)
1776
+ # We do the length check second, since the invalid character error
1777
+ # is likely to be more informative for the user
1778
+ if len(hextet_str) > 4:
1779
+ msg = "At most 4 characters permitted in %r"
1780
+ raise ValueError(msg % hextet_str)
1781
+ # Length check means we can skip checking the integer value
1782
+ return int(hextet_str, 16)
1783
+
1784
+ @classmethod
1785
+ def _compress_hextets(cls, hextets):
1786
+ """Compresses a list of hextets.
1787
+
1788
+ Compresses a list of strings, replacing the longest continuous
1789
+ sequence of "0" in the list with "" and adding empty strings at
1790
+ the beginning or at the end of the string such that subsequently
1791
+ calling ":".join(hextets) will produce the compressed version of
1792
+ the IPv6 address.
1793
+
1794
+ Args:
1795
+ hextets: A list of strings, the hextets to compress.
1796
+
1797
+ Returns:
1798
+ A list of strings.
1799
+
1800
+ """
1801
+ best_doublecolon_start = -1
1802
+ best_doublecolon_len = 0
1803
+ doublecolon_start = -1
1804
+ doublecolon_len = 0
1805
+ for index, hextet in enumerate(hextets):
1806
+ if hextet == '0':
1807
+ doublecolon_len += 1
1808
+ if doublecolon_start == -1:
1809
+ # Start of a sequence of zeros.
1810
+ doublecolon_start = index
1811
+ if doublecolon_len > best_doublecolon_len:
1812
+ # This is the longest sequence of zeros so far.
1813
+ best_doublecolon_len = doublecolon_len
1814
+ best_doublecolon_start = doublecolon_start
1815
+ else:
1816
+ doublecolon_len = 0
1817
+ doublecolon_start = -1
1818
+
1819
+ if best_doublecolon_len > 1:
1820
+ best_doublecolon_end = (best_doublecolon_start +
1821
+ best_doublecolon_len)
1822
+ # For zeros at the end of the address.
1823
+ if best_doublecolon_end == len(hextets):
1824
+ hextets += ['']
1825
+ hextets[best_doublecolon_start:best_doublecolon_end] = ['']
1826
+ # For zeros at the beginning of the address.
1827
+ if best_doublecolon_start == 0:
1828
+ hextets = [''] + hextets
1829
+
1830
+ return hextets
1831
+
1832
+ @classmethod
1833
+ def _string_from_ip_int(cls, ip_int=None):
1834
+ """Turns a 128-bit integer into hexadecimal notation.
1835
+
1836
+ Args:
1837
+ ip_int: An integer, the IP address.
1838
+
1839
+ Returns:
1840
+ A string, the hexadecimal representation of the address.
1841
+
1842
+ Raises:
1843
+ ValueError: The address is bigger than 128 bits of all ones.
1844
+
1845
+ """
1846
+ if ip_int is None:
1847
+ ip_int = int(cls._ip)
1848
+
1849
+ if ip_int > cls._ALL_ONES:
1850
+ raise ValueError('IPv6 address is too large')
1851
+
1852
+ hex_str = '%032x' % ip_int
1853
+ hextets = ['%x' % int(hex_str[x:x + 4], 16) for x in range(0, 32, 4)]
1854
+
1855
+ hextets = cls._compress_hextets(hextets)
1856
+ return ':'.join(hextets)
1857
+
1858
+ def _explode_shorthand_ip_string(self):
1859
+ """Expand a shortened IPv6 address.
1860
+
1861
+ Args:
1862
+ ip_str: A string, the IPv6 address.
1863
+
1864
+ Returns:
1865
+ A string, the expanded IPv6 address.
1866
+
1867
+ """
1868
+ if isinstance(self, IPv6Network):
1869
+ ip_str = str(self.network_address)
1870
+ elif isinstance(self, IPv6Interface):
1871
+ ip_str = str(self.ip)
1872
+ else:
1873
+ ip_str = str(self)
1874
+
1875
+ ip_int = self._ip_int_from_string(ip_str)
1876
+ hex_str = '%032x' % ip_int
1877
+ parts = [hex_str[x:x + 4] for x in range(0, 32, 4)]
1878
+ if isinstance(self, (_BaseNetwork, IPv6Interface)):
1879
+ return '%s/%d' % (':'.join(parts), self._prefixlen)
1880
+ return ':'.join(parts)
1881
+
1882
+ def _reverse_pointer(self):
1883
+ """Return the reverse DNS pointer name for the IPv6 address.
1884
+
1885
+ This implements the method described in RFC3596 2.5.
1886
+
1887
+ """
1888
+ reverse_chars = self.exploded[::-1].replace(':', '')
1889
+ return '.'.join(reverse_chars) + '.ip6.arpa'
1890
+
1891
+ @staticmethod
1892
+ def _split_scope_id(ip_str):
1893
+ """Helper function to parse IPv6 string address with scope id.
1894
+
1895
+ See RFC 4007 for details.
1896
+
1897
+ Args:
1898
+ ip_str: A string, the IPv6 address.
1899
+
1900
+ Returns:
1901
+ (addr, scope_id) tuple.
1902
+
1903
+ """
1904
+ addr, sep, scope_id = ip_str.partition('%')
1905
+ if not sep:
1906
+ scope_id = None
1907
+ elif not scope_id or '%' in scope_id:
1908
+ raise AddressValueError('Invalid IPv6 address: "%r"' % ip_str)
1909
+ return addr, scope_id
1910
+
1911
+ @property
1912
+ def max_prefixlen(self):
1913
+ return self._max_prefixlen
1914
+
1915
+ @property
1916
+ def version(self):
1917
+ return self._version
1918
+
1919
+
1920
+ class IPv6Address(_BaseV6, _BaseAddress):
1921
+
1922
+ """Represent and manipulate single IPv6 Addresses."""
1923
+
1924
+ __slots__ = ('_ip', '_scope_id', '__weakref__')
1925
+
1926
+ def __init__(self, address):
1927
+ """Instantiate a new IPv6 address object.
1928
+
1929
+ Args:
1930
+ address: A string or integer representing the IP
1931
+
1932
+ Additionally, an integer can be passed, so
1933
+ IPv6Address('2001:db8::') ==
1934
+ IPv6Address(42540766411282592856903984951653826560)
1935
+ or, more generally
1936
+ IPv6Address(int(IPv6Address('2001:db8::'))) ==
1937
+ IPv6Address('2001:db8::')
1938
+
1939
+ Raises:
1940
+ AddressValueError: If address isn't a valid IPv6 address.
1941
+
1942
+ """
1943
+ # Efficient constructor from integer.
1944
+ if isinstance(address, int):
1945
+ self._check_int_address(address)
1946
+ self._ip = address
1947
+ self._scope_id = None
1948
+ return
1949
+
1950
+ # Constructing from a packed address
1951
+ if isinstance(address, bytes):
1952
+ self._check_packed_address(address, 16)
1953
+ self._ip = int.from_bytes(address, 'big')
1954
+ self._scope_id = None
1955
+ return
1956
+
1957
+ # Assume input argument to be string or any object representation
1958
+ # which converts into a formatted IP string.
1959
+ addr_str = str(address)
1960
+ if '/' in addr_str:
1961
+ raise AddressValueError(f"Unexpected '/' in {address!r}")
1962
+ addr_str, self._scope_id = self._split_scope_id(addr_str)
1963
+
1964
+ self._ip = self._ip_int_from_string(addr_str)
1965
+
1966
+ def __str__(self):
1967
+ ip_str = super().__str__()
1968
+ return ip_str + '%' + self._scope_id if self._scope_id else ip_str
1969
+
1970
+ def __hash__(self):
1971
+ return hash((self._ip, self._scope_id))
1972
+
1973
+ def __eq__(self, other):
1974
+ address_equal = super().__eq__(other)
1975
+ if address_equal is NotImplemented:
1976
+ return NotImplemented
1977
+ if not address_equal:
1978
+ return False
1979
+ return self._scope_id == getattr(other, '_scope_id', None)
1980
+
1981
+ def __reduce__(self):
1982
+ return (self.__class__, (str(self),))
1983
+
1984
+ @property
1985
+ def scope_id(self):
1986
+ """Identifier of a particular zone of the address's scope.
1987
+
1988
+ See RFC 4007 for details.
1989
+
1990
+ Returns:
1991
+ A string identifying the zone of the address if specified, else None.
1992
+
1993
+ """
1994
+ return self._scope_id
1995
+
1996
+ @property
1997
+ def packed(self):
1998
+ """The binary representation of this address."""
1999
+ return v6_int_to_packed(self._ip)
2000
+
2001
+ @property
2002
+ def is_multicast(self):
2003
+ """Test if the address is reserved for multicast use.
2004
+
2005
+ Returns:
2006
+ A boolean, True if the address is a multicast address.
2007
+ See RFC 2373 2.7 for details.
2008
+
2009
+ """
2010
+ return self in self._constants._multicast_network
2011
+
2012
+ @property
2013
+ def is_reserved(self):
2014
+ """Test if the address is otherwise IETF reserved.
2015
+
2016
+ Returns:
2017
+ A boolean, True if the address is within one of the
2018
+ reserved IPv6 Network ranges.
2019
+
2020
+ """
2021
+ return any(self in x for x in self._constants._reserved_networks)
2022
+
2023
+ @property
2024
+ def is_link_local(self):
2025
+ """Test if the address is reserved for link-local.
2026
+
2027
+ Returns:
2028
+ A boolean, True if the address is reserved per RFC 4291.
2029
+
2030
+ """
2031
+ return self in self._constants._linklocal_network
2032
+
2033
+ @property
2034
+ def is_site_local(self):
2035
+ """Test if the address is reserved for site-local.
2036
+
2037
+ Note that the site-local address space has been deprecated by RFC 3879.
2038
+ Use is_private to test if this address is in the space of unique local
2039
+ addresses as defined by RFC 4193.
2040
+
2041
+ Returns:
2042
+ A boolean, True if the address is reserved per RFC 3513 2.5.6.
2043
+
2044
+ """
2045
+ return self in self._constants._sitelocal_network
2046
+
2047
+ @property
2048
+ @functools.lru_cache()
2049
+ def is_private(self):
2050
+ """``True`` if the address is defined as not globally reachable by
2051
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2052
+ (for IPv6) with the following exceptions:
2053
+
2054
+ * ``is_private`` is ``False`` for ``100.64.0.0/10``
2055
+ * For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2056
+ semantics of the underlying IPv4 addresses and the following condition holds
2057
+ (see :attr:`IPv6Address.ipv4_mapped`)::
2058
+
2059
+ address.is_private == address.ipv4_mapped.is_private
2060
+
2061
+ ``is_private`` has value opposite to :attr:`is_global`, except for the ``100.64.0.0/10``
2062
+ IPv4 range where they are both ``False``.
2063
+ """
2064
+ ipv4_mapped = self.ipv4_mapped
2065
+ if ipv4_mapped is not None:
2066
+ return ipv4_mapped.is_private
2067
+ return (
2068
+ any(self in net for net in self._constants._private_networks)
2069
+ and all(self not in net for net in self._constants._private_networks_exceptions)
2070
+ )
2071
+
2072
+ @property
2073
+ def is_global(self):
2074
+ """``True`` if the address is defined as globally reachable by
2075
+ iana-ipv4-special-registry_ (for IPv4) or iana-ipv6-special-registry_
2076
+ (for IPv6) with the following exception:
2077
+
2078
+ For IPv4-mapped IPv6-addresses the ``is_private`` value is determined by the
2079
+ semantics of the underlying IPv4 addresses and the following condition holds
2080
+ (see :attr:`IPv6Address.ipv4_mapped`)::
2081
+
2082
+ address.is_global == address.ipv4_mapped.is_global
2083
+
2084
+ ``is_global`` has value opposite to :attr:`is_private`, except for the ``100.64.0.0/10``
2085
+ IPv4 range where they are both ``False``.
2086
+ """
2087
+ return not self.is_private
2088
+
2089
+ @property
2090
+ def is_unspecified(self):
2091
+ """Test if the address is unspecified.
2092
+
2093
+ Returns:
2094
+ A boolean, True if this is the unspecified address as defined in
2095
+ RFC 2373 2.5.2.
2096
+
2097
+ """
2098
+ return self._ip == 0
2099
+
2100
+ @property
2101
+ def is_loopback(self):
2102
+ """Test if the address is a loopback address.
2103
+
2104
+ Returns:
2105
+ A boolean, True if the address is a loopback address as defined in
2106
+ RFC 2373 2.5.3.
2107
+
2108
+ """
2109
+ return self._ip == 1
2110
+
2111
+ @property
2112
+ def ipv4_mapped(self):
2113
+ """Return the IPv4 mapped address.
2114
+
2115
+ Returns:
2116
+ If the IPv6 address is a v4 mapped address, return the
2117
+ IPv4 mapped address. Return None otherwise.
2118
+
2119
+ """
2120
+ if (self._ip >> 32) != 0xFFFF:
2121
+ return None
2122
+ return IPv4Address(self._ip & 0xFFFFFFFF)
2123
+
2124
+ @property
2125
+ def teredo(self):
2126
+ """Tuple of embedded teredo IPs.
2127
+
2128
+ Returns:
2129
+ Tuple of the (server, client) IPs or None if the address
2130
+ doesn't appear to be a teredo address (doesn't start with
2131
+ 2001::/32)
2132
+
2133
+ """
2134
+ if (self._ip >> 96) != 0x20010000:
2135
+ return None
2136
+ return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF),
2137
+ IPv4Address(~self._ip & 0xFFFFFFFF))
2138
+
2139
+ @property
2140
+ def sixtofour(self):
2141
+ """Return the IPv4 6to4 embedded address.
2142
+
2143
+ Returns:
2144
+ The IPv4 6to4-embedded address if present or None if the
2145
+ address doesn't appear to contain a 6to4 embedded address.
2146
+
2147
+ """
2148
+ if (self._ip >> 112) != 0x2002:
2149
+ return None
2150
+ return IPv4Address((self._ip >> 80) & 0xFFFFFFFF)
2151
+
2152
+
2153
+ class IPv6Interface(IPv6Address):
2154
+
2155
+ def __init__(self, address):
2156
+ addr, mask = self._split_addr_prefix(address)
2157
+
2158
+ IPv6Address.__init__(self, addr)
2159
+ self.network = IPv6Network((addr, mask), strict=False)
2160
+ self.netmask = self.network.netmask
2161
+ self._prefixlen = self.network._prefixlen
2162
+
2163
+ @functools.cached_property
2164
+ def hostmask(self):
2165
+ return self.network.hostmask
2166
+
2167
+ def __str__(self):
2168
+ return '%s/%d' % (super().__str__(),
2169
+ self._prefixlen)
2170
+
2171
+ def __eq__(self, other):
2172
+ address_equal = IPv6Address.__eq__(self, other)
2173
+ if address_equal is NotImplemented or not address_equal:
2174
+ return address_equal
2175
+ try:
2176
+ return self.network == other.network
2177
+ except AttributeError:
2178
+ # An interface with an associated network is NOT the
2179
+ # same as an unassociated address. That's why the hash
2180
+ # takes the extra info into account.
2181
+ return False
2182
+
2183
+ def __lt__(self, other):
2184
+ address_less = IPv6Address.__lt__(self, other)
2185
+ if address_less is NotImplemented:
2186
+ return address_less
2187
+ try:
2188
+ return (self.network < other.network or
2189
+ self.network == other.network and address_less)
2190
+ except AttributeError:
2191
+ # We *do* allow addresses and interfaces to be sorted. The
2192
+ # unassociated address is considered less than all interfaces.
2193
+ return False
2194
+
2195
+ def __hash__(self):
2196
+ return hash((self._ip, self._prefixlen, int(self.network.network_address)))
2197
+
2198
+ __reduce__ = _IPAddressBase.__reduce__
2199
+
2200
+ @property
2201
+ def ip(self):
2202
+ return IPv6Address(self._ip)
2203
+
2204
+ @property
2205
+ def with_prefixlen(self):
2206
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
2207
+ self._prefixlen)
2208
+
2209
+ @property
2210
+ def with_netmask(self):
2211
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
2212
+ self.netmask)
2213
+
2214
+ @property
2215
+ def with_hostmask(self):
2216
+ return '%s/%s' % (self._string_from_ip_int(self._ip),
2217
+ self.hostmask)
2218
+
2219
+ @property
2220
+ def is_unspecified(self):
2221
+ return self._ip == 0 and self.network.is_unspecified
2222
+
2223
+ @property
2224
+ def is_loopback(self):
2225
+ return self._ip == 1 and self.network.is_loopback
2226
+
2227
+
2228
+ class IPv6Network(_BaseV6, _BaseNetwork):
2229
+
2230
+ """This class represents and manipulates 128-bit IPv6 networks.
2231
+
2232
+ Attributes: [examples for IPv6('2001:db8::1000/124')]
2233
+ .network_address: IPv6Address('2001:db8::1000')
2234
+ .hostmask: IPv6Address('::f')
2235
+ .broadcast_address: IPv6Address('2001:db8::100f')
2236
+ .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0')
2237
+ .prefixlen: 124
2238
+
2239
+ """
2240
+
2241
+ # Class to use when creating address objects
2242
+ _address_class = IPv6Address
2243
+
2244
+ def __init__(self, address, strict=True):
2245
+ """Instantiate a new IPv6 Network object.
2246
+
2247
+ Args:
2248
+ address: A string or integer representing the IPv6 network or the
2249
+ IP and prefix/netmask.
2250
+ '2001:db8::/128'
2251
+ '2001:db8:0000:0000:0000:0000:0000:0000/128'
2252
+ '2001:db8::'
2253
+ are all functionally the same in IPv6. That is to say,
2254
+ failing to provide a subnetmask will create an object with
2255
+ a mask of /128.
2256
+
2257
+ Additionally, an integer can be passed, so
2258
+ IPv6Network('2001:db8::') ==
2259
+ IPv6Network(42540766411282592856903984951653826560)
2260
+ or, more generally
2261
+ IPv6Network(int(IPv6Network('2001:db8::'))) ==
2262
+ IPv6Network('2001:db8::')
2263
+
2264
+ strict: A boolean. If true, ensure that we have been passed
2265
+ A true network address, eg, 2001:db8::1000/124 and not an
2266
+ IP address on a network, eg, 2001:db8::1/124.
2267
+
2268
+ Raises:
2269
+ AddressValueError: If address isn't a valid IPv6 address.
2270
+ NetmaskValueError: If the netmask isn't valid for
2271
+ an IPv6 address.
2272
+ ValueError: If strict was True and a network address was not
2273
+ supplied.
2274
+ """
2275
+ addr, mask = self._split_addr_prefix(address)
2276
+
2277
+ self.network_address = IPv6Address(addr)
2278
+ self.netmask, self._prefixlen = self._make_netmask(mask)
2279
+ packed = int(self.network_address)
2280
+ if packed & int(self.netmask) != packed:
2281
+ if strict:
2282
+ raise ValueError('%s has host bits set' % self)
2283
+ else:
2284
+ self.network_address = IPv6Address(packed &
2285
+ int(self.netmask))
2286
+
2287
+ if self._prefixlen == (self._max_prefixlen - 1):
2288
+ self.hosts = self.__iter__
2289
+ elif self._prefixlen == self._max_prefixlen:
2290
+ self.hosts = lambda: [IPv6Address(addr)]
2291
+
2292
+ def hosts(self):
2293
+ """Generate Iterator over usable hosts in a network.
2294
+
2295
+ This is like __iter__ except it doesn't return the
2296
+ Subnet-Router anycast address.
2297
+
2298
+ """
2299
+ network = int(self.network_address)
2300
+ broadcast = int(self.broadcast_address)
2301
+ for x in range(network + 1, broadcast + 1):
2302
+ yield self._address_class(x)
2303
+
2304
+ @property
2305
+ def is_site_local(self):
2306
+ """Test if the address is reserved for site-local.
2307
+
2308
+ Note that the site-local address space has been deprecated by RFC 3879.
2309
+ Use is_private to test if this address is in the space of unique local
2310
+ addresses as defined by RFC 4193.
2311
+
2312
+ Returns:
2313
+ A boolean, True if the address is reserved per RFC 3513 2.5.6.
2314
+
2315
+ """
2316
+ return (self.network_address.is_site_local and
2317
+ self.broadcast_address.is_site_local)
2318
+
2319
+
2320
+ class _IPv6Constants:
2321
+
2322
+ _linklocal_network = IPv6Network('fe80::/10')
2323
+
2324
+ _multicast_network = IPv6Network('ff00::/8')
2325
+
2326
+ # Not globally reachable address blocks listed on
2327
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
2328
+ _private_networks = [
2329
+ IPv6Network('::1/128'),
2330
+ IPv6Network('::/128'),
2331
+ IPv6Network('::ffff:0:0/96'),
2332
+ IPv6Network('64:ff9b:1::/48'),
2333
+ IPv6Network('100::/64'),
2334
+ IPv6Network('2001::/23'),
2335
+ IPv6Network('2001:db8::/32'),
2336
+ # IANA says N/A, let's consider it not globally reachable to be safe
2337
+ IPv6Network('2002::/16'),
2338
+ IPv6Network('fc00::/7'),
2339
+ IPv6Network('fe80::/10'),
2340
+ ]
2341
+
2342
+ _private_networks_exceptions = [
2343
+ IPv6Network('2001:1::1/128'),
2344
+ IPv6Network('2001:1::2/128'),
2345
+ IPv6Network('2001:3::/32'),
2346
+ IPv6Network('2001:4:112::/48'),
2347
+ IPv6Network('2001:20::/28'),
2348
+ IPv6Network('2001:30::/28'),
2349
+ ]
2350
+
2351
+ _reserved_networks = [
2352
+ IPv6Network('::/8'), IPv6Network('100::/8'),
2353
+ IPv6Network('200::/7'), IPv6Network('400::/6'),
2354
+ IPv6Network('800::/5'), IPv6Network('1000::/4'),
2355
+ IPv6Network('4000::/3'), IPv6Network('6000::/3'),
2356
+ IPv6Network('8000::/3'), IPv6Network('A000::/3'),
2357
+ IPv6Network('C000::/3'), IPv6Network('E000::/4'),
2358
+ IPv6Network('F000::/5'), IPv6Network('F800::/6'),
2359
+ IPv6Network('FE00::/9'),
2360
+ ]
2361
+
2362
+ _sitelocal_network = IPv6Network('fec0::/10')
2363
+
2364
+
2365
+ IPv6Address._constants = _IPv6Constants
2366
+ IPv6Network._constants = _IPv6Constants