def handle_map_register(received_message, control_plane_sockets, data_plane_sockets):
    map_register = received_message.message
    assert isinstance(map_register, MapRegisterMessage)

    processed_records = []
    saved_key = ""
    for record in map_register.records:
        assert isinstance(record, MapRegisterRecord)

        # Look up the address in the tree
        instance_id, afi, prefix = determine_instance_id_and_afi(record.eid_prefix)
        tree_node = resolve(instance_id, afi, prefix)

        if isinstance(tree_node, MapServerNode):
            try:
                tree_node.handle_map_register_record(
                    received_message, record, control_plane_sockets, data_plane_sockets
                )

                # Record processed: store the record, and keep the authentication key in case we want to send back a notify
                processed_records.append(record)
                saved_key = tree_node.key
            except MapServerException, e:
                logger.error("MapServerNode could not process record {0}: {1}".format(record, e.message))
        else:
            logger.warn(
                u"Received a Map-Register message for {0}"
                ", but we are not a MapServer for that EID space".format(prefix)
            )
def handle_map_request(received_message, control_plane_sockets, data_plane_sockets):
    map_request = received_message.message
    assert isinstance(map_request, MapRequestMessage)

    if len(map_request.eid_prefixes) != 1:
        logger.warn(u"Ignoring message {0}: Map-Request with eid-prefix count != 1".format(received_message.message_nr))
        return

    eid_prefix = map_request.eid_prefixes[0]
    instance_id, afi, eid_prefix = determine_instance_id_and_afi(eid_prefix)
    nodes = resolve_path(instance_id, afi, eid_prefix)
    if not nodes:
        logger.warn(
            u"Ignoring message {0}: Map-Request for unknown"
            " instance {1} with AFI {2}".format(received_message.message_nr, instance_id, afi)
        )
        return

    if not isinstance(nodes[0], ETRNode):
        # Not for us: drop
        logger.warn(
            u"Ignoring message {0}: Map-Request for prefix {1} in instance {2} "
            "for which we are not an ETR".format(received_message.message_nr, eid_prefix, instance_id)
        )
        return

    nodes[0].handle_map_request(received_message, eid_prefix, control_plane_sockets, data_plane_sockets)
    def handle_map_register_record(self, received_message, record, control_plane_sockets, data_plane_sockets):
        assert isinstance(received_message, ReceivedMessage)
        assert isinstance(record, MapRegisterRecord)

        map_register = received_message.message
        assert isinstance(map_register, MapRegisterMessage)

        # Before we go any further we check the authentication data
        if not map_register.verify_authentication_data(self.key):
            raise MapServerAuthenticationError(u"Ignoring a MapRegister message for {0} "
                                               "with invalid authentication data".format(record.eid_prefix))

        # Extract the prefix info
        dummy, dummy, prefix = determine_instance_id_and_afi(record.eid_prefix)

        # Check for invalid prefixes
        if not prefix.overlaps(self.prefix) \
        or prefix.prefixlen < self.prefix.prefixlen:
            raise MapServerScopeError(u"MapRegister message received by Map-Server {0} for prefix {1}".format(self.prefix, prefix))

        # Check for more-specifics
        if prefix.prefixlen > self.prefix.prefixlen \
        and not self.allow_more_specifics:
            raise MapServerScopeError(u'ETR tried to register more-specific {0} in {1}'.format(prefix, self.prefix))

        # Determine canonical source
        if map_register.xtr_id:
            source = '{site_id:x}-{xtr_id:x}'.format(site_id=map_register.site_id,
                                                 xtr_id=map_register.xtr_id)
        else:
            source = received_message.source[0]

        # Store the data for now
        with self.registrations_lock:
            if prefix not in self.registrations:
                self.registrations[prefix] = {}

            # Store registration
            locators = ', '.join(map(lambda locator: unicode(locator.address), record.locator_records))
            if source not in self.registrations[prefix]:
                logger.info('New MapServerRegistration from {source} for {prefix}: {locators}'.format(source=source, prefix=prefix,
                                                                                                      locators=locators))
            else:
                logger.debug('Updating MapServerRegistration from {source} for {prefix}: {locators}'.format(source=source, prefix=prefix,
                                                                                                      locators=locators))

            self.registrations[prefix][source] = MapServerRegistration(proxy_map_reply=map_register.proxy_map_reply,
                                                                       record=record)
def handle_map_notify(received_message, control_plane_sockets, data_plane_sockets):
    map_notify = received_message.message
    assert isinstance(map_notify, MapNotifyMessage)

    for record in map_notify.records:
        assert isinstance(record, MapRegisterRecord)

        # Look up the address in the tree
        instance_id, afi, prefix = determine_instance_id_and_afi(record.eid_prefix)
        tree_node = resolve(instance_id, afi, prefix)

        if isinstance(tree_node, ETRNode):
            tree_node.handle_map_notify_record(received_message, record, control_plane_sockets, data_plane_sockets)
        else:
            logger.warn(
                u"Received a Map-Notify message for {0}"
                ", but we are not a MapServerClient for that EID space".format(prefix)
            )
def handle_info_message(received_message, control_plane_sockets, data_plane_sockets):
    info_message = received_message.message
    assert isinstance(info_message, InfoMessage)

    logger.debug("HANDLING {0!r}".format(received_message))

    if not received_message.message.is_reply:
        logger.error(u"We are not an RTR, we can only handle InfoMessage replies")
        return

    eid_prefix = info_message.eid_prefix
    instance_id, afi, eid_prefix = determine_instance_id_and_afi(eid_prefix)
    node = resolve(instance_id, afi, eid_prefix)
    if not isinstance(node, ETRNode):
        # Not for us: drop
        logger.warn(
            u"Ignoring message {0}: Info-Message for prefix {1} in instance {2} "
            "for which we are not an ETR".format(received_message.message_nr, eid_prefix, instance_id)
        )
        return

    node.handle_info_message_reply(received_message, control_plane_sockets, data_plane_sockets)
def handle_ddt_map_request(received_message, control_plane_sockets, data_plane_sockets):
    ecm = received_message.message

    # TODO: Implement security [LISP-Security]
    if ecm.security:
        logger.error("We can't handle LISP-Security yet")
        return

    # Look up the address in the tree
    map_request = received_message.inner_message
    instance_id, afi, req_prefix = determine_instance_id_and_afi(map_request.eid_prefixes[0])
    tree_nodes = resolve_path(instance_id, afi, req_prefix)

    # Find the handling node and its children
    auth_node = None
    handling_node = None
    more_specific_nodes = []
    for tree_node in tree_nodes[::-1]:
        # Mark that we are authoritative for this request
        if isinstance(tree_node, (AuthContainerNode, MapServerNode)):
            auth_node = tree_node

        # Do we already have a handler?
        if handling_node is not None:
            # We have a handler, collect the more specific nodes
            more_specific_nodes.append(tree_node)
        else:
            if isinstance(tree_node, DDTReferralNode):
                # DDTReferralNodes are an answer by themselves
                handling_node = tree_node
                break

            elif isinstance(tree_node, MapServerNode):
                # MapServerNodes handle themselves
                handling_node = tree_node
                break

            else:
                # We don't really care about other node types
                pass

    # Didn't find any handling node
    if not handling_node:
        # We are not authoritative
        send_not_authoritative(received_message)
        return

    # We have all the information: handle it
    if isinstance(handling_node, DDTReferralNode):
        # Handle this as a DDT referral
        referral = handling_node.get_referral()
        send_answer(received_message, referral)
        return

    elif isinstance(tree_node, MapServerNode):
        # Handle this as a DDT Map-Server

        # Let he MapServerNode send the Map-Request to the ETR or answer as a proxy
        handled = handling_node.handle_map_request(received_message, control_plane_sockets, data_plane_sockets)

        # Send DDT response
        if handled:
            send_ms_ack(received_message=received_message,
                        ms_prefix=handling_node.prefix,
                        other_map_servers=(auth_node and auth_node.ddt_nodes or []))
        else:
            send_ms_not_registered(received_message=received_message,
                                   ms_prefix=handling_node.prefix,
                                   other_map_servers=(auth_node and auth_node.ddt_nodes or []))

    elif auth_node:
        # We are authoritative and no matching targets, we seem to have a hole
        send_delegation_hole(received_message)

    else:
        # We are not authoritative
        send_not_authoritative(received_message)