diff options
author | Rob Austein <sra@hactrn.net> | 2009-03-31 17:27:56 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2009-03-31 17:27:56 +0000 |
commit | 3546b3df24a634e9b9ea7ac9076434b12138ef16 (patch) | |
tree | 714e564608370edafa8b03a87bd1b9fee3974480 /rtr-origin/updater.py | |
parent | 4d0e0f0cc33ba786478ecdfa11a448c6ffe3ccb4 (diff) |
Checkpoint
svn path=/rtr-origin/updater.py; revision=2287
Diffstat (limited to 'rtr-origin/updater.py')
-rwxr-xr-x | rtr-origin/updater.py | 89 |
1 files changed, 67 insertions, 22 deletions
diff --git a/rtr-origin/updater.py b/rtr-origin/updater.py index 469c7ba9..8db49580 100755 --- a/rtr-origin/updater.py +++ b/rtr-origin/updater.py @@ -23,14 +23,21 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -import sys, os, struct, rpki.x509, rpki.ipaddrs - -rcynic_dir = "../rcynic/rcynic-data/authenticated" +import sys, os, struct, rpki.x509, rpki.ipaddrs, rpki.sundial class prefix(object): + """Object representing one prefix. This corresponds closely to one + PDU in the rpki-router protocol, so closely that we use lexical + ordering of the wire format of the PDU as the ordering for this + class. + """ + + version = 0 # Protocol version + source = 0 # Source (0 == RPKI) @classmethod def from_asn1(cls, asn, t): + """Read a prefix from a ROA in the tuple format used by our ASN.1 decoder.""" x = 0L for y in t[0]: x = (x << 1) | y @@ -41,6 +48,7 @@ class prefix(object): self.prefix = cls.addr_type(x) self.prefixlen = len(t[0]) self.max_prefixlen = self.prefixlen if t[1] is None else t[1] + self.color = 0 self.pdu = self.to_pdu() return self @@ -50,39 +58,76 @@ class prefix(object): def __cmp__(self, other): return cmp(self.pdu, other.pdu) - def to_pdu(self, announce = 1, color = 0): - return (struct.pack("!BBHBBBB", 0, self.pdu_type, color, announce, self.prefixlen, self.max_prefixlen, 0) + + def to_pdu(self, announce = 1): + """Generate the wire format PDU for this prefix. The announce bit + is handled via an optional argument because of the way we use it + when generating diffs. + """ + return (struct.pack("!BBHBBBB", self.version, self.pdu_type, self.color, announce, self.prefixlen, self.max_prefixlen, self.source) + self.prefix.to_bytes() + struct.pack("!L", self.asn)) + @classmethod + def from_pdu_file(cls, f): + """Read one wire format PDU from a file. This is intended to be + used in an iterator, so it raises StopIteration on end of file. + """ + b = f.read(8) + if b == "": + raise StopIteration + version, pdu_type, color, announce, prefixlen, max_prefixlen, source = struct.unpack("!BBHBBBB", b) + assert version == self.version, "PDU version is %d, expected %d" % (version, self.version) + assert announce == 1 and source == self.source + self = cls.pdu_map[pdu_type]() + self.prefixlen = prefixlen + self.max_prefixlen = max_prefixlen + self.color = color + self.prefix = self.addr_type.from_bytes(f.read(self.addr_type.bits / 8)) + self.asn = struct.unpack("!L", f.read(4)) + return self + class v4prefix(prefix): + """IPv4 flavor of a prefix.""" addr_type = rpki.ipaddrs.v4addr pdu_type = 4 class v6prefix(prefix): + """IPv6 flavor of a prefix.""" addr_type = rpki.ipaddrs.v6addr pdu_type = 6 -prefix.map = { "\x00\x01" : v4prefix, - "\x00\x02" : v6prefix } +prefix.afi_map = { "\x00\x01" : v4prefix, "\x00\x02" : v6prefix } +prefix.pdu_map = { 4 : v4prefix, 6 : v6prefix } -prefixes = [] +class prefix_set(list): + """Object representing a set of prefixes, that is, one versioned and + (theoretically) consistant set of prefixes extracted from rcynic's + output. + """ -for root, dirs, files in os.walk(rcynic_dir): - for f in files: - if f.endswith(".roa"): - roa = rpki.x509.ROA(DER_file = os.path.join(root, f)).extract().get() - assert roa[0] == 0, "ROA version is %d, expected 0" % roa[0] - asn = roa[1] - for afi, addrs in roa[2]: - for addr in addrs: - prefixes.append(prefix.map[afi].from_asn1(asn, addr)) - -prefixes.sort() + @classmethod + def from_rcynic(cls, rcynic_dir): + """Parse ROAS fetched (and validated!) by rcynic to create a new + prefix_set. + """ + self = cls() + self.timestamp = rpki.sundial.now() + for root, dirs, files in os.walk(rcynic_dir): + for f in files: + if f.endswith(".roa"): + roa = rpki.x509.ROA(DER_file = os.path.join(root, f)).extract().get() + assert roa[0] == 0, "ROA version is %d, expected 0" % roa[0] + asn = roa[1] + for afi, addrs in roa[2]: + for addr in addrs: + self.append(prefix.afi_map[afi].from_asn1(asn, addr)) + self.sort() + for i in xrange(len(self) - 2, -1, -1): + if self[i] == self[i + 1]: + del self[i + 1] + return self -for i in xrange(len(prefixes) - 2, -1, -1): - if prefixes[i] == prefixes[i + 1]: - del prefixes[i + 1] +prefixes = prefix_set.from_rcynic("../rcynic/rcynic-data/authenticated") for p in prefixes: print "%-40s %s" % (p, ":".join(("%02X" % ord(i) for i in p.to_pdu()))) |