1 | """Utility classes and definitions.""" |
||
2 | 1 | import struct |
|
3 | |||
4 | |||
5 | 1 | class IPv4AddressWithMask: |
|
6 | """Class to represent an IPv4 address with netmask.""" |
||
7 | |||
8 | 1 | def __init__(self, address=0, netmask=0): |
|
9 | """Instatiate with given ip address and netmask.""" |
||
10 | 1 | self.address = address |
|
11 | 1 | self.netmask = netmask |
|
12 | |||
13 | 1 | def __repr__(self): |
|
14 | return f'<{self.__class__.__name__}: {self.as_dot_string()}>' |
||
15 | |||
16 | 1 | def __str__(self): |
|
17 | return self.as_dot_string() |
||
18 | |||
19 | 1 | def as_dot_string(self): |
|
20 | # pylint: disable=W0631 |
||
21 | """Represent an IPv4 address with mask as 0.0.0.0/0.""" |
||
22 | 1 | packed = struct.pack('!I', self.address) |
|
23 | 1 | unpacked_bytes = struct.unpack('!4B', packed) |
|
24 | 1 | address = '.'.join([str(x) for x in unpacked_bytes]) |
|
25 | 1 | for i in range(1, 33): |
|
26 | 1 | stripped_mask = self.netmask >> i << i |
|
27 | 1 | if stripped_mask != self.netmask: |
|
28 | 1 | break |
|
29 | 1 | mask = 33 - i |
|
0 ignored issues
–
show
introduced
by
![]() |
|||
30 | 1 | return f'{address}/{mask}' |
|
31 | |||
32 | 1 | def unpack(self, buffer, start=0): |
|
33 | """Unpack IPv4 address and netmask.""" |
||
34 | self.address, self.netmask = struct.unpack('!2I', |
||
35 | buffer[start:start+8]) |
||
36 | |||
37 | |||
38 | 1 | class IPv6AddressWithMask: |
|
39 | """Class to represent an IPv6 address with netmask.""" |
||
40 | |||
41 | 1 | def __init__(self, address=0, netmask=0): |
|
42 | """Instantiate with given ip address and netmask.""" |
||
43 | 1 | self.address = address |
|
44 | 1 | self.netmask = netmask |
|
45 | |||
46 | 1 | def __repr__(self): |
|
47 | return f'<{self.__class__.__name__}: {self.as_comma_string()}>' |
||
48 | |||
49 | 1 | def __str__(self): |
|
50 | return self.as_comma_string() |
||
51 | |||
52 | 1 | def as_comma_string(self): |
|
53 | # pylint: disable=W0631 |
||
54 | """Represent an IPv6 address with mask as ffff::0/0.""" |
||
55 | 1 | address = [] |
|
56 | 1 | addrs = divmod(self.address, 2**64) |
|
57 | 1 | for addr in addrs: |
|
58 | 1 | packed = struct.pack('!Q', addr) |
|
59 | 1 | unpacked_bytes = struct.unpack('!4H', packed) |
|
60 | 1 | address.append(':'.join([f'{b:x}' for b in unpacked_bytes])) |
|
61 | 1 | address = ':'.join(address) |
|
62 | 1 | for i in range(1, 129): |
|
63 | 1 | stripped_mask = self.netmask >> i << i |
|
64 | 1 | if stripped_mask != self.netmask: |
|
65 | 1 | break |
|
66 | 1 | mask = 129 - i |
|
0 ignored issues
–
show
|
|||
67 | 1 | return f'{address}/{mask}' |
|
68 | |||
69 | 1 | def unpack(self, buffer, start=0): |
|
70 | """Unpack IPv6 address and mask.""" |
||
71 | self.address = int.from_bytes(buffer[start:start+16], 'big') |
||
72 | self.netmask = int.from_bytes(buffer[start+16:start+32], 'big') |
||
73 |