diff options
Diffstat (limited to 'scripts/rpki')
-rw-r--r-- | scripts/rpki/left_right.py | 158 |
1 files changed, 118 insertions, 40 deletions
diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py index 3c503bd4..a4d86a48 100644 --- a/scripts/rpki/left_right.py +++ b/scripts/rpki/left_right.py @@ -2,62 +2,121 @@ import base64, sax_utils, resource_set -Broken = True - -assert ! Broken - -# This still isn't right, although it's not as broken as it was. I -# don't see any sane way to avoid keeping a stack of objects under -# construction, probably in our sax_handler object. Passing SAX -# events along to the current object is ok, but passing every SAX -# event down through the chain of objects under construction is just -# nuts. So probably want push and pop methods in the sax_handler so -# that the current object can create a child and push it onto the -# stack, and so that a current object can pop itself off the stack. +# This is still pretty nasty, feels much too complex for a relatively +# simple task. class base_elt(object): """ Base type for left-right message elements. """ - def __init__(self, up=None): - self.up = up - for key in self.multivalue: - setattr(self, key, []) - + # This isn't quite right, as_number is only multivalue in some elements. + # Live with it for the moment, fix after code stablizes. + multivalue = ("peer_contact", "signing_cert", "extension_preference", "resource_class", "as_number", "as_range", "subset_as_number", "subset_as_range", "ipv4_prefix", "ipv4_range", "subset_ipv4_prefix", "subset_ipv4_range", "ipv6_prefix", "ipv6_range", "subset_ipv6_prefix", "subset_ipv6_range") + b64content = ("peer_ta", "pkcs10_cert_request", "public_key", "signing_cert") + + pdu_objects = ("self", "child", "parent", "bsc", "repository", "route_origin", + "list_resources", "report_error") + def store(self, key, val): - if key in self.multivalue: + if key not in self.multivalue: + assert not getattr(self, key) + setattr(self, key, val) + elif hasattr(self, key): getattr(self, key).append(val) else: - setattr(self, key, val) + setattr(self, key, [val]) - b64content = ("peer_ta", "pkcs10_cert_request", "public_key", "signing_cert") + def startElement(self, stack, name, attrs): + if name not in type_map: + getattr(self, "handle_" + name)(stack, name, attrs) + elif type(self) is type_map(name): + sax_utils.snarf_attribute(self, attrs, self.attributes) + else: + elt = type_map[name]() + stack.append(elt) + self.store(name, elt) + elt.startElement(stack, name, attrs) - def endElement(self, name, text): + def endElement(self, stack, name, text): if name in self.b64content: self.store(name, base64.b64decode(text)) + if name in type_map: + stack.pop() + + def boolean_handler(stack, name, attrs): + setattr(self, name, True) + + handle_publish_world_now = boolean_handler + handle_reissue = boolean_handler + handle_rekey = boolean_handler + handle_revoke = boolean_handler + handle_run_now = boolean_handler + handle_suppress_publication = boolean_handler + + def handle_generate_keypair(stack, name, attrs): + self.boolean_handler(stack, name, attrs) + sax_utils.snarf_attribute(self, attrs, ("key_type", "hash_alg", "key_length")) + + def id_handler(stack, name, attrs): + sax_utils.snarf_attribute(self, attrs, "id") + + handle_bsc_link = id_handler + handle_child_db_id = id_handler + handle_repository_link = id_handler + handle_sia_base = id_handler + + def handle_peer_contact(stack, name, attrs): + self.peer_contact = attrs.getValue("uri").encode("ascii") + + # Mumble, really should be using resource_set types here, more + # idiocy due to premature optimization + + # Special case for dumb reasons, fix later + def handle_as_number(stack, name, attrs): + asn = long(attrs.getValue("asn")) + if isinstance(self, route_origin_elt): + assert not hasattr(self, name) + self.as_number = asn + else: + self.store(name, resource_range_as(asn, asn)) - pdu_objects = ("self", "child", "parent", "bsc", "repository", "route_origin", - "list_resources", "report_error") + def handle_subset_as_number(stack, name, attrs): + asn = long(attrs.getValue("asn")) + self.store(name, resource_range_as(asn, asn)) - def startElement(self, name, attrs): - if name in pdu_objects: - sax_utils.snarf_attribute(self, attrs, self.attributes) - else: - getattr(self, "handle_" + name)(name, attrs) + def handle_as_range(stack, name, attrs): + self.store(name, resource_range_as(long(attrs.getValue("min")), + long(attrs.getValue("max")))) + + handle_subset_as_range = handle_as_range + + def handle_ipv4_range(stack, name, attrs): + self.store(name, resource_range_ipv4(ipaddrs.v4addr(attrs.getValue("min")), + ipaddrs.v4addr(attrs.getValue("max")))) + + handle_subset_ipv4_range = handle_ipv4_range + + def handle_ipv6_range(stack, name, attrs): + self.store(name, resource_range_ipv6(ipaddrs.v6addr(attrs.getValue("min")), + ipaddrs.v6addr(attrs.getValue("max")))) + + handle_subset_ipv6_range = handle_ipv6_range + + # Haven't written (subset_)?ipv[46]_prefix() handlers yet. Some of the code for + # that might belong in resource_set.py instead of here. - # handle_xxx methods not yet written class self_elt(base_elt): attributes = ("action", "self_id") class bsc_elt(base_elt): - attributes = ("action", "self_id", "biz_signing_context_id") + attributes = ("action", "self_id", "bsc_id") class parent_elt(base_elt): attributes = ("action", "self_id", "parent_id") @@ -95,18 +154,21 @@ class msg(list): "list_resources" : list_resources_elt, "report_error" : report_error_elt } - def startElement(self, name, attrs): + def startElement(self, stack, name, attrs): if name == "msg": sax_utils.snarf_attribute(self, attrs, "version", int) sax_utils.snarf_attribute(self, attrs, "type") assert self.version == 1 else: - if name in self.dispatch: - self.append(self.dispatch[name](self)) - self[-1].startElement(name, attrs) + assert name in self.dispatch + elt = self.dispatch[name](self) + self.append(elt) + stack.append(elt) + elt.startElement(stack, name, attrs) - def endElement(self, name, text): - self[-1].endElement(name, text) + def endElement(self, stack, name, text): + assert name == "msg" + assert len(stack) == 1 def __str__(self): return ('<?xml version="1.0" encoding="US-ASCII" ?>\n' @@ -121,12 +183,28 @@ class sax_handler(sax_utils.handler): def startElement(self, name, attrs): if name == "msg": - self.set_obj(msg()) - self.obj.startElement(name, attrs) + self.stack = [msg()] + self.stack[-1].startElement(self.stack, name, attrs) def endElement(self, name): - self.obj.endElement(name, self.get_text()) - + self.stack[-1].endElement(self.stack, name, self.get_text()) + if name == "msg": + assert len(self.stack) == 1 + self.set_obj(self.stack[0]) + +type_map = { + "msg" : msg_elt, + "self" : self_elt, + "child" : child_elt, + "parent" : parent_elt, + "repository" : repository_elt, + "route_origin" : route_origin_elt, + "bsc" : bsc_elt, + "list_resources" : list_resources_elt, + "report_error" : report_error_elt, + "extension_preference" : extension_preference_elt, + "resource_class" : resource_class_elt +} # bsc_link ; attribute-only element # child_db_id ; attribute-only element |