+
+ def is_ipv6(self):
+ if isinstance(self, CidrV6): return True
+ return False
+
+ def is_valid_cidr(self, address):
+ if "/" in address:
+ addr, netlen = address.split("/", 1)
+ netlen = int(netlen)
+ else:
+ addr, netlen = address, 0
+ return self._is_valid_address(addr) and self.is_valid_netlen(netlen)
+
+ def is_valid_netlen(self, netlen):
+ if netlen < 0: return False
+ if netlen > self._max_netlen(): return False
+ return True
+
+
+class CidrV4(Cidr):
+ """A class representing a CIDRized IPv4 network value.
+
+ Specifically, it is representing a contiguous IPv4 network block
+ that can be expressed as a ip-address/network-length pair."""
+
+ def __init__(self, address, netlen = -1):
+ """This takes either a formatted string in CIDR notation:
+ (e.g., "127.0.0.1/32"), A tuple consisting of an formatting
+ string IPv4 address and a numeric network length, or the same
+ as two arguments."""
+
+ self._initialize(address, netlen)
+
+ def _is_valid_address(self, address):
+ """Returns True if the address is a legal IPv4 address."""
+ try:
+ self._convert_ipstr(address)
+ return True
+ except socket.error:
+ return False
+
+ def _base_mask(self, numaddr):
+ return numaddr & 0xFFFFFFFFL
+
+ def _max_netlen(self):
+ return 32
+
+ def _convert_ipstr(self, addr):
+ packed_numaddr = socket.inet_aton(addr)
+ return struct.unpack("!I", packed_numaddr)[0]
+
+ def _convert_ipaddr(self, numaddr):
+ packed_numaddr = struct.pack("!I", numaddr)
+ return socket.inet_ntoa(packed_numaddr)
+
+ def _mask(self, len):
+ return self._base_mask(0xFFFFFFFF << (32 - len))
+
+
+class CidrV6(Cidr):
+ """A class representing a CIDRized IPv6 network value.
+
+ Specifically, it is representing a contiguous IPv6 network block
+ that can be expressed as a ipv6-address/network-length pair."""
+
+ ip6_base_mask = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL # 128-bits of all ones.
+ ip6_lower_mask = 0x0000000000000000FFFFFFFFFFFFFFFFL
+ ip6_upper_mask = 0xFFFFFFFFFFFFFFFF0000000000000000L
+
+ def __init__(self, address, netlen = -1):
+
+ self._initialize(address, netlen)
+
+ def _is_valid_address(self, address):
+ try:
+ self._convert_ipstr(address)
+ return True
+ except socket.error, e:
+ print "Failed to convert address string '%s': " + str(e) % (address)
+ return False
+
+ def _base_mask(self, numaddr):
+ return numaddr & CidrV6.ip6_base_mask
+
+ def _max_netlen(self):
+ return 128
+
+ def _convert_ipstr(self, addr):
+ packed_numaddr = socket.inet_pton(socket.AF_INET6, addr)
+ upper, lower = struct.unpack("!QQ", packed_numaddr);
+ return (upper << 64) | lower
+
+ def _convert_ipaddr(self, numaddr):
+ upper = (numaddr & CidrV6.ip6_upper_mask) >> 64;
+ lower = numaddr & CidrV6.ip6_lower_mask;
+ packed_numaddr = struct.pack("!QQ", upper, lower)
+ return socket.inet_ntop(socket.AF_INET6, packed_numaddr)
+
+ def _mask(self, len):
+ return self._base_mask(CidrV6.ip6_base_mask << (128 - len))