aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rpkid/rpki/resource_set.py59
1 files changed, 53 insertions, 6 deletions
diff --git a/rpkid/rpki/resource_set.py b/rpkid/rpki/resource_set.py
index f435c9fb..9b708543 100644
--- a/rpkid/rpki/resource_set.py
+++ b/rpkid/rpki/resource_set.py
@@ -117,6 +117,15 @@ class resource_range_ip(resource_range):
raise rpki.exceptions.MustBePrefix, "%s cannot be expressed as a prefix" % str(self)
return _long2bs(self.min, self.datum_type.bits, prefixlen = prefixlen)
+ @classmethod
+ def make_prefix(cls, address, prefixlen):
+ """Construct a resource range corresponding to a prefix."""
+ assert isinstance(address, cls.datum_type) and isinstance(prefixlen, (int, long))
+ assert prefixlen >= 0 and prefixlen <= cls.datum_type.bits, "Nonsensical prefix length: %s" % prefixlen
+ mask = (1 << (cls.datum_type.bits - prefixlen)) - 1
+ assert (address & mask) == 0, "Resource not in canonical form: %s/s" % (address, prefixlen)
+ return cls(cls.datum_type(address), cls.datum_type(address | mask))
+
class resource_range_ipv4(resource_range_ip):
"""Range of IPv4 addresses."""
@@ -336,12 +345,7 @@ class resource_set_ip(resource_set):
return self.range_type(self.range_type.datum_type(r.group(1)), self.range_type.datum_type(r.group(2)))
r = re.match("^([0-9:.a-fA-F]+)/([0-9]+)$", x)
if r:
- min = self.range_type.datum_type(r.group(1))
- prefixlen = int(r.group(2))
- mask = (1 << (self.range_type.datum_type.bits - prefixlen)) - 1
- assert (min & mask) == 0, "Resource not in canonical form: %s" % (x)
- max = self.range_type.datum_type(min | mask)
- return self.range_type(min, max)
+ return self.range_type.make_prefix(self.range_type.datum_type(r.group(1)), int(r.group(2)))
raise RuntimeError, 'Bad IP resource "%s"' % (x)
def parse_rfc3779_tuple(self, x):
@@ -503,6 +507,49 @@ class resource_bag(object):
s += "V6: %s" % self.v6
return s
+# Sadly, there are enough differences between RFC 3779 and the data
+# structures in the latest proposed ROA format that we can't just use
+# the RFC 3779 code for ROAs. So we need a separate set of classes
+# that are similar in concept but different in detail, with conversion
+# functions. Such is life. I suppose it might be possible to do this
+# with multiple inheritance, but that's probably more bother than it's
+# worth.
+
+class roa_prefix(object):
+ """ROA prefix. This is similar to the resource_range_ip class, but
+ differs in that it only represents prefixes, never ranges, and
+ includes the maximum prefix length as an additional value.
+ """
+
+ def __init__(self, address, prefixlen, max_prefixlen = None):
+ """Initialize a ROA prefix. max_prefixlen is optional and
+ defaults to prefixlen. max_prefixlen must not be smaller than
+ prefixlen.
+ """
+ if max_prefixlen is None:
+ max_prefixlen = prefixlen
+ assert max_prefixlen >= prefixlen, "Bad max_prefixlen: %d must not be shorter than %d" % (max_prefixlen, prefixlen)
+ self.address = address
+ self.prefixlen = prefixlen
+ self.max_prefixlen = max_prefixlen
+
+ def __cmp__(self, other):
+ """Compare two ROA prefix objects. Comparision is based on
+ address, prefixlen, and max_prefixlen, in that order.
+ """
+ c = self.address - other.address
+ if c == 0: c = self.prefixlen - other.prefixlen
+ if c == 0: c = self.max_prefixlen - other.max_prefixlen
+ if c < 0: c = -1
+ if c > 0: c = 1
+ return c
+
+ def __str__(self):
+ """Convert a ROA prefix to string format."""
+ return str(self.address) + "/" + str(self.prefixlen) + "-" + str(self.max_prefixlen)
+
+ # CONTINUE HERE
+
# Test suite for set operations. This will probably go away eventually
if __name__ == "__main__":