diff options
-rw-r--r-- | scripts/rpki/resource_set.py | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/scripts/rpki/resource_set.py b/scripts/rpki/resource_set.py index 3f4336ae..d5f350ee 100644 --- a/scripts/rpki/resource_set.py +++ b/scripts/rpki/resource_set.py @@ -12,6 +12,8 @@ We also provide some basic set operations (union, intersection, etc). import re, ipaddrs +inherit_token = "<inherit>" + class resource_range(object): """Generic resource range type. @@ -122,11 +124,15 @@ class resource_set(list): use this type directly. """ + inherit = False + def __init__(self, ini = None): """Initialize a resource_set.""" if isinstance(ini, long): ini = str(ini) - if isinstance(ini, str) and len(ini): + if ini == inherit_token: + self.inherit = True + elif isinstance(ini, str) and len(ini): self.extend(map(self.parse_str, ini.split(","))) elif isinstance(ini, tuple): self.parse_tuple(ini) @@ -134,6 +140,7 @@ class resource_set(list): self.extend(ini) else: assert ini is None or ini == "" + assert not self.inherit or not self self.sort() if __debug__: for i in range(0, len(self) - 1): @@ -141,7 +148,10 @@ class resource_set(list): def __str__(self): """Convert a resource_set to string format.""" - return ",".join(map(str, self)) + if self.inherit: + return inherit_token + else: + return ",".join(map(str, self)) def _comm(self, other): """Like comm(1), sort of. @@ -151,6 +161,7 @@ class resource_set(list): efficiently) as the basis for most set operations on resource sets. """ + assert not self.inherit assert type(self) is type(other), "Type mismatch %s %s" % (repr(type(self)), repr(type(other))) set1 = self[:] set2 = other[:] @@ -176,6 +187,7 @@ class resource_set(list): def union(self, other): """Set union for resource sets.""" + assert not self.inherit assert type(self) is type(other) set1 = self[:] set2 = other[:] @@ -211,6 +223,7 @@ class resource_set(list): def contains(self, item): """Set membership test for resource sets.""" + assert not self.inherit for i in self: if isinstance(item, type(i)) and i.min <= item.min and i.max >= item.max: return True @@ -260,20 +273,25 @@ class resource_set_as(resource_set): def parse_tuple(self, x): """Parse AS resource sets from intermediate form generated by ASN.1 decoder.""" - assert x[0] == "asIdsOrRanges" # Not handling "inherit" yet - for aor in x[1]: - if aor[0] == "range": - min = aor[1][0] - max = aor[1][1] - else: - min = aor[1] - max = min - self.append(resource_range_as(min, max)) + if x[0] == "asIdsOrRanges": + for aor in x[1]: + if aor[0] == "range": + min = aor[1][0] + max = aor[1][1] + else: + min = aor[1] + max = min + self.append(resource_range_as(min, max)) + else: + assert x[0] == "inherit" + self.inherit = True def to_tuple(self): """Encode AS resource set into intermediate form used by ASN.1 encoder.""" if self: return ("asIdsOrRanges", tuple(a.to_tuple() for a in self)) + elif self.inherit: + return ("inherit", "") else: return None @@ -300,23 +318,28 @@ class resource_set_ip(resource_set): def parse_tuple(self, x): """Parse IP address resource sets from intermediate form generated by ASN.1 decoder.""" - assert x[0] == "addressesOrRanges" # Not handling "inherit" yet - for aor in x[1]: - if aor[0] == "addressRange": - min = _bs2long(aor[1][0]) << (self.range_type.datum_type.bits - len(aor[1][0])) - max = _bs2long(aor[1][1]) << (self.range_type.datum_type.bits - len(aor[1][1])) - mask = (1L << (self.range_type.datum_type.bits - len(aor[1][1]))) - 1 - else: - min = _bs2long(aor[1]) << (self.range_type.datum_type.bits - len(aor[1])) - mask = (1L << (self.range_type.datum_type.bits - len(aor[1]))) - 1 - assert (min & mask) == 0, "Resource not in canonical form: %s" % (str(x)) - max = min | mask - self.append(self.range_type(self.range_type.datum_type(min), self.range_type.datum_type(max))) + if x[0] == "addressesOrRanges": + for aor in x[1]: + if aor[0] == "addressRange": + min = _bs2long(aor[1][0]) << (self.range_type.datum_type.bits - len(aor[1][0])) + max = _bs2long(aor[1][1]) << (self.range_type.datum_type.bits - len(aor[1][1])) + mask = (1L << (self.range_type.datum_type.bits - len(aor[1][1]))) - 1 + else: + min = _bs2long(aor[1]) << (self.range_type.datum_type.bits - len(aor[1])) + mask = (1L << (self.range_type.datum_type.bits - len(aor[1]))) - 1 + assert (min & mask) == 0, "Resource not in canonical form: %s" % (str(x)) + max = min | mask + self.append(self.range_type(self.range_type.datum_type(min), self.range_type.datum_type(max))) + else: + assert x[0] == "inherit" + self.inherit = True def to_tuple(self): """Encode IP resource set into intermediate form used by ASN.1 encoder.""" if self: return (self.afi, ("addressesOrRanges", tuple(a.to_tuple() for a in self))) + elif self.inherit: + return (self.afi, ("inherit", "")) else: return None @@ -367,10 +390,10 @@ def parse_extensions(exts): as = resource_set_as(x[2][0]) if x[0] == (1, 3, 6, 1, 5, 5, 7, 1, 7): # sbgp-ipAddrBlock for fam in x[2]: - if fam[0] == "\x00\x01": + if fam[0] == resource_set_ipv4.afi: assert v4 is None v4 = resource_set_ipv4(fam[1]) - if fam[0] == "\x00\x02": + if fam[0] == resource_set_ipv6.afi: assert v6 is None v6 = resource_set_ipv6(fam[1]) return as, v4, v6 |