aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/rpki/resource_set.py73
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