1 """IP address set manipulation, built on top of ipaddress.py"""
3 # This file is Free Software. It was originally written for secnet.
5 # Copyright 2014 Ian Jackson
7 # You may redistribute secnet as a whole and/or modify it under the
8 # terms of the GNU General Public License as published by the Free
9 # Software Foundation; either version 3, or (at your option) any
12 # You may redistribute this file and/or modify it under the terms of
13 # the GNU General Public License as published by the Free Software
14 # Foundation; either version 2, or (at your option) any later version.
15 # Note however that this version of ipaddrset.py uses the Python
16 # ipaddr library from Google, which is licenced only under the Apache
17 # Licence, version 2.0, which is only compatible with the GNU GPL v3
18 # (or perhaps later versions), and not with the GNU GPL v2.
20 # This software is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this software; if not, see
27 # https://www.gnu.org/licenses/gpl.html.
34 "A set of IP addresses"
37 def __init__(self,l=[]):
38 "New set contains each IP*Network in the sequence l"
44 # housekeeping and representation
48 ipaddress.collapse_addresses(self._v[v]))
50 return "IPAddressSet(%s)" % self.networks()
51 def str(self,comma=",",none="-"):
52 "Human-readable string with controllable delimiters"
54 return comma.join(map(str, self.networks()))
62 "Appends each IP*Network in the sequence l to self"
67 "Appends each IP*Network in the sequence l to self"
69 self._v[a.version].append(a)
71 # enquirers including standard comparisons
77 __nonzero__=__bool__ # for python2
79 def __eq__(self,other):
81 if self._v[v] != other._v[v]:
84 def __ne__(self,other): return not self.__eq__(other)
85 def __ge__(self,other):
86 """True iff self completely contains IPAddressSet other"""
88 if not self._contains_net(o):
91 def __le__(self,other): return other.__ge__(self)
92 def __gt__(self,other): return self!=other and other.__ge__(self)
93 def __lt__(self,other): return other.__gt__(self)
95 def __cmp__(self,other):
96 if self==other: return 0
97 if self>=other: return +1
98 if self<=other: return -1
102 "Iterates over minimal list of distinct IPNetworks in this set"
108 "Returns miminal list of distinct IPNetworks in this set"
109 return [i for i in self]
112 def intersection(self,other):
113 "Returns the intersection; does not modify self"
117 for j in other._v[v]:
119 if i.prefixlen > j.prefixlen:
124 def union(self,other):
125 "Returns the union; does not modify self"
127 r._append(self.networks())
128 r._append(other.networks())
132 def _contains_net(self,n):
133 """True iff self completely contains IPNetwork n"""
135 if i.overlaps(n) and n.prefixlen >= i.prefixlen:
139 def contains(self,thing):
140 """Returns True iff self completely contains thing.
141 thing may be an IPNetwork or an IPAddressSet"""
147 return self._contains_net(ipaddress.ip_network(thing))
149 return self.__ge__(thing)
152 "Returns a set containing all addresses"
155 if v==6: a=ipaddress.IPv6Address(0)
156 elif v==4: a=ipaddress.IPv4Address(0)
157 else: raise "internal error"
158 n=ipaddress.ip_network("%s/0" % a)