author | Pascal Volk <user@localhost.localdomain.org> |
Sat, 08 Jun 2013 15:12:16 +0000 | |
branch | v0.7.x |
changeset 698 | 18a528d44055 |
parent 676 | 2bc11dada296 |
child 711 | 2a75058fc064 |
permissions | -rw-r--r-- |
421
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
1 |
# -*- coding: UTF-8 -*- |
675
d24f094d1cb5
Updated copyright notices to include the year 2013.
Pascal Volk <user@localhost.localdomain.org>
parents:
568
diff
changeset
|
2 |
# Copyright (c) 2011 - 2013, Pascal Volk |
421
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
3 |
# See COPYING for distribution information. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
4 |
""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
5 |
VirtualMailManager.network |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
6 |
~~~~~~~~~~~~~~~~~~~~~~~~~~ |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
7 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
8 |
Network/IP address related class and function |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
9 |
""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
10 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
11 |
import socket |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
12 |
|
672
d3fd9bb0a5ea
VMM/network: Post-2to3 fix. s/addr.encode('hex')/b2a_hex(addr).
Pascal Volk <user@localhost.localdomain.org>
parents:
643
diff
changeset
|
13 |
from binascii import b2a_hex |
d3fd9bb0a5ea
VMM/network: Post-2to3 fix. s/addr.encode('hex')/b2a_hex(addr).
Pascal Volk <user@localhost.localdomain.org>
parents:
643
diff
changeset
|
14 |
|
421
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
15 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
16 |
class NetInfo(object): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
17 |
"""Simple class for CIDR network addresses an IP addresses.""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
18 |
__slots__ = ('_addr', '_prefix', '_bits_max', '_family', '_nw_addr') |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
19 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
20 |
def __init__(self, nw_address): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
21 |
"""Creates a new `NetInfo` instance. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
22 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
23 |
Argument: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
24 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
25 |
`nw_address` : basestring |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
26 |
string representation of an IPv4/IPv6 address or network address. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
27 |
E.g. 192.0.2.13, 192.0.2.0/24, 2001:db8::/32 or ::1 |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
28 |
When the address has no netmask the prefix length will be set to |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
29 |
32 for IPv4 addresses and 128 for IPv6 addresses. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
30 |
""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
31 |
self._addr = None |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
32 |
self._prefix = 0 |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
33 |
self._bits_max = 0 |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
34 |
self._family = 0 |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
35 |
self._nw_addr = nw_address |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
36 |
self._parse_net_range() |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
37 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
38 |
def __hash__(self): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
39 |
return hash((self._addr, self._family, self._prefix)) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
40 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
41 |
def __repr__(self): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
42 |
return "NetInfo('%s')" % self._nw_addr |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
43 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
44 |
def _parse_net_range(self): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
45 |
"""Parse the network range of `self._nw_addr and assign values |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
46 |
to the class attributes. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
47 |
`""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
48 |
sep = '/' |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
49 |
if self._nw_addr.count(sep): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
50 |
ip_address, sep, self._prefix = self._nw_addr.partition(sep) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
51 |
self._family, self._addr = get_ip_addr_info(ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
52 |
else: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
53 |
self._family, self._addr = get_ip_addr_info(self._nw_addr) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
54 |
self._bits_max = (128, 32)[self._family is socket.AF_INET] |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
55 |
if self._prefix is 0: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
56 |
self._prefix = self._bits_max |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
57 |
else: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
58 |
try: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
59 |
self._prefix = int(self._prefix) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
60 |
except ValueError: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
61 |
raise ValueError('Invalid prefix length: %r' % self._prefix) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
62 |
if self._prefix > self._bits_max or self._prefix < 0: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
63 |
raise ValueError('Invalid prefix length: %r' % self._prefix) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
64 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
65 |
@property |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
66 |
def family(self): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
67 |
"""Address family: `socket.AF_INET` or `socket.AF_INET6`""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
68 |
return self._family |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
69 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
70 |
def address_in_net(self, ip_address): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
71 |
"""Checks if the `ip_address` belongs to the same subnet.""" |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
72 |
family, address = get_ip_addr_info(ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
73 |
if family != self._family: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
74 |
return False |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
75 |
return address >> self._bits_max - self._prefix == \ |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
76 |
self._addr >> self._bits_max - self._prefix |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
77 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
78 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
79 |
def get_ip_addr_info(ip_address): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
80 |
"""Checks if the string `ip_address` is a valid IPv4 or IPv6 address. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
81 |
|
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
82 |
When the `ip_address` could be validated successfully a tuple |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
83 |
`(address_family, address_as_long)` will be returned. The |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
84 |
`address_family`will be either `socket.AF_INET` or `socket.AF_INET6`. |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
85 |
""" |
643
df1e3b67882a
Ran 2to3 from Python 3.2.3.
Pascal Volk <user@localhost.localdomain.org>
parents:
568
diff
changeset
|
86 |
if not isinstance(ip_address, str) or not ip_address: |
421
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
87 |
raise TypeError('ip_address must be a non empty string.') |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
88 |
if not ip_address.count(':'): |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
89 |
family = socket.AF_INET |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
90 |
try: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
91 |
address = socket.inet_aton(ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
92 |
except socket.error: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
93 |
raise ValueError('Not a valid IPv4 address: %r' % ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
94 |
elif not socket.has_ipv6: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
95 |
raise ValueError('Unsupported IP address (IPv6): %r' % ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
96 |
else: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
97 |
family = socket.AF_INET6 |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
98 |
try: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
99 |
address = socket.inet_pton(family, ip_address) |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
100 |
except socket.error: |
ff2a61e155db
VMM/network: Added new module network.
Pascal Volk <neverseen@users.sourceforge.net>
parents:
diff
changeset
|
101 |
raise ValueError('Not a valid IPv6 address: %r' % ip_address) |
672
d3fd9bb0a5ea
VMM/network: Post-2to3 fix. s/addr.encode('hex')/b2a_hex(addr).
Pascal Volk <user@localhost.localdomain.org>
parents:
643
diff
changeset
|
102 |
return (family, int(b2a_hex(address), 16)) |