endif
check: eax-aes-test.confirm eax-serpent-test.confirm \
- eax-serpentbe-test.confirm
+ eax-serpentbe-test.confirm check-ipaddrset
version.c: Makefile
echo "#include \"secnet.h\"" >$@.new
./$< <$(srcdir)/eax-$*-test.vectors >$@.new
mv -f $@.new $@
+check-ipaddrset: ipaddrset-test.py ipaddrset.py ipaddrset-test.expected
+ $(srcdir)/ipaddrset-test.py >ipaddrset-test.new
+ diff -u ipaddrset-test.expected ipaddrset-test.new
+
.PRECIOUS: eax-%-test
installdirs:
$(INSTALL_PROGRAM) secnet $(sbindir)/`echo secnet|sed '$(transform)'`
$(INSTALL_PROGRAM) ${srcdir}/make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'`
$(INSTALL) ${srcdir}/ipaddr.py $(prefix)/share/secnet/ipaddr.py
+ $(INSTALL) ${srcdir}/ipaddrset.py $(prefix)/share/secnet/ipaddrset.py
$(INSTALL) secnet.8 $(mandir)/man8/secnet.8
clean:
--- /dev/null
+#!/usr/bin/python
+
+import sys
+import copy
+import os
+saved_path=copy.copy(sys.path)
+for p in ['','.',os.getcwd()]:
+ try: sys.path.remove(p)
+ except ValueError: pass
+
+import ipaddr
+from ipaddr import IPNetwork, IPAddress
+
+sys.path=saved_path
+
+import ipaddrset
+from ipaddrset import IPAddressSet
+
+v4a=IPAddress('172.18.45.6')
+
+s=IPAddressSet()
+print 's =', s
+s.append([IPNetwork('172.18.45.0/24')])
+s.append([IPNetwork('2001:23:24::/40')])
+print s
+
+t=IPAddressSet(map(IPNetwork,['172.31.80.8/32','172.18.45.192/28']))
+print 't =', t
+print t <= s
+print t == s
+
+for n1s in ['172.18.44.0/23','172.18.45.6/32','172.18.45.0/24']:
+ n1=IPNetwork(n1s)
+ print n1
+ print s.contains(n1)
+ print t.contains(n1)
+
+n=s.networks()[0]
+
+a=ipaddrset.complete_set()
+print 'a =', a
+print a >= s
+print a >= t
+
+print '^'
+print s.intersection(t)
+print t.intersection(s)
+
+print 'u'
+print s.union(t)
+print t.union(s)
--- /dev/null
+"""IP address set manipulation, built on top of ipaddr.py"""
+
+# Copyright 2014 Ian Jackson
+#
+# This file is Free Software. It was originally written for secnet.
+#
+# You may redistribute it and/or modify it under the terms of the GNU
+# General Public License as published by the Free Software
+# Foundation; either version 2, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import ipaddr
+
+_vsns = [6,4]
+
+class IPAddressSet:
+ "A set of IP addresses"
+
+ # constructors
+ def __init__(self,l=[]):
+ "New set contains each ipaddr.IPNetwork in the sequence l"
+ self._v = {}
+ for v in _vsns:
+ self._v[v] = [ ]
+ self.append(l)
+
+ # housekeeping and representation
+ def _compact(self):
+ for v in _vsns:
+ self._v[v] = ipaddr.collapse_address_list(self._v[v])
+ def __repr__(self):
+ return "IPAddressSet(%s)" % self.networks()
+ def str(self,comma=",",none="-"):
+ "Human-readable string with controllable delimiters"
+ if self:
+ return comma.join(map(str, self.networks()))
+ else:
+ return none
+ def __str__(self):
+ return self.str()
+
+ # mutators
+ def append(self,l):
+ "Appends each ipaddr.IPNetwork in the sequence l to self"
+ self._append(l)
+ self._compact()
+
+ def _append(self,l):
+ "Appends each ipaddr.IPNetwork in the sequence l to self"
+ for a in l:
+ self._v[a.version].append(a)
+
+ # enquirers including standard comparisons
+ def __nonzero__(self):
+ for v in _vsns:
+ if self._v[v]:
+ return True
+ return False
+
+ def __eq__(self,other):
+ for v in _vsns:
+ if self._v[v] != other._v[v]:
+ return False
+ return True
+ def __ne__(self,other): return not self.__eq__(other)
+ def __ge__(self,other):
+ """True iff self completely contains IPAddressSet other"""
+ for o in other:
+ if not self._contains_net(o):
+ return False
+ return True
+ def __le__(self,other): return other.__ge__(self)
+ def __gt__(self,other): return self!=other and other.__ge__(self)
+ def __lt__(self,other): return other.__gt__(self)
+
+ def __cmp__(self,other):
+ if self==other: return 0
+ if self>=other: return +1
+ if self<=other: return -1
+ return NotImplemented
+
+ def __iter__(self):
+ "Iterates over minimal list of distinct IPNetworks in this set"
+ for v in _vsns:
+ for i in self._v[v]:
+ yield i
+
+ def networks(self):
+ "Returns miminal list of distinct IPNetworks in this set"
+ return [i for i in self]
+
+ # set operations
+ def intersection(self,other):
+ "Returns the intersection; does not modify self"
+ r = IPAddressSet()
+ for v in _vsns:
+ for i in self._v[v]:
+ for j in other._v[v]:
+ if i.overlaps(j):
+ if i.prefixlen > j.prefixlen:
+ r._append([i])
+ else:
+ r._append([j])
+ return r
+ def union(self,other):
+ "Returns the union; does not modify self"
+ r = IPAddressSet()
+ r._append(self.networks())
+ r._append(other.networks())
+ r._compact()
+ return r
+
+ def _contains_net(self,n):
+ """True iff self completely contains IPNetwork n"""
+ for i in self:
+ if i.overlaps(n) and n.prefixlen >= i.prefixlen:
+ return True
+ return False
+
+ def contains(self,thing):
+ """Returns True iff self completely contains thing.
+ thing may be an IPNetwork or an IPAddressSet"""
+ try:
+ v = [thing.version]
+ except KeyError:
+ v = None
+ if v:
+ return self._contains_net(ipaddr.IPNetwork(thing))
+ else:
+ return self.__ge__(thing)
+
+def complete_set():
+ "Returns a set containing all addresses"
+ s=IPAddressSet()
+ for v in _vsns:
+ a=ipaddr.IPAddress(0,v)
+ n=ipaddr.IPNetwork("%s/0" % a)
+ s.append([n])
+ return s