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
« 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
11OPT_IMPORTS = False
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)
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)
36#: The width (in bits) of this address type.
37width = 128
39#: The individual word size (in bits) of this address type.
40word_size = 16
42#: The separator character used between each word.
43word_sep = ':'
45#: The AF_* constant value of this address type.
46family = AF_INET6
48#: A friendly string name address type.
49family_name = 'IPv6'
51#: The version of this address type.
52version = 6
54#: The number base to be used when interpreting word values as integers.
55word_base = 16
57#: The maximum integer value that can be represented by this address type.
58max_int = 2 ** width - 1
60#: The number of words in this address type.
61num_words = width // word_size
63#: The maximum integer value for an individual word in this address type.
64max_word = 2 ** word_size - 1
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)])
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)])
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)])
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)])
82#-----------------------------------------------------------------------------
83# Dialect classes.
84#-----------------------------------------------------------------------------
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'
91 #: Boolean flag indicating if IPv6 compaction algorithm should be used.
92 compact = True
94class ipv6_full(ipv6_compact):
95 """An IPv6 dialect class - 'all zeroes' form."""
97 #: Boolean flag indicating if IPv6 compaction algorithm should be used.
98 compact = False
100class ipv6_verbose(ipv6_compact):
101 """An IPv6 dialect class - extra wide 'all zeroes' form."""
103 #: The format string used to converting words into string values.
104 word_fmt = '%.4x'
106 #: Boolean flag indicating if IPv6 compaction algorithm should be used.
107 compact = False
110def valid_str(addr, flags=0):
111 """
112 :param addr: An IPv6 address in presentation (string) format.
114 :param flags: decides which rules are applied to the interpretation of the
115 addr value. Future use - currently has no effect.
117 :return: ``True`` if IPv6 address is valid, ``False`` otherwise.
118 """
119 if addr == '':
120 raise AddrFormatError('Empty strings are not supported!')
122 try:
123 _inet_pton(AF_INET6, addr)
124 except:
125 return False
126 return True
129def str_to_int(addr, flags=0):
130 """
131 :param addr: An IPv6 address in string form.
133 :param flags: decides which rules are applied to the interpretation of the
134 addr value. Future use - currently has no effect.
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,))
145def int_to_str(int_val, dialect=None):
146 """
147 :param int_val: An unsigned integer.
149 :param dialect: (optional) a Python class defining formatting options.
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
157 addr = None
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,))
172 return addr
175def int_to_arpa(int_val):
176 """
177 :param int_val: An unsigned integer.
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)
190def int_to_packed(int_val):
191 """
192 :param int_val: the integer to be packed.
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)
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.
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))
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
217 return int_val
220def valid_words(words):
221 return _valid_words(words, word_size, num_words)
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)
232def words_to_int(words):
233 return _words_to_int(words, word_size, num_words)
236def valid_bits(bits):
237 return _valid_bits(bits, width, word_sep)
240def bits_to_int(bits):
241 return _bits_to_int(bits, width, word_sep)
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)
250def valid_bin(bin_val):
251 return _valid_bin(bin_val, width)
254def int_to_bin(int_val):
255 return _int_to_bin(int_val, width)
258def bin_to_int(bin_val):
259 return _bin_to_int(bin_val, width)