示例#1
0
int process_not_authoritative_reply(
        lispd_referral_cache_entry              *referral_entry,
        lispd_pending_referral_cache_entry      *pending_referral_entry)
{
    lispd_log_msg(LISP_LOG_DEBUG_2,"process_not_authoritative_reply: Node %s is not authoritative for the requested prefix %s/%d. "
            "Asking next ddt node.", get_char_from_lisp_addr_t(referral_entry->src_inf_ddt_node_locator_addr),
            get_char_from_lisp_addr_t(pending_referral_entry->map_cache_entry->mapping->eid_prefix),
            pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);

    err = try_next_referral_node_or_go_through_root (pending_referral_entry);
    if (err != GOOD){
        if (err == ERR_DST_ADDR){
            err = activate_negative_map_cache (pending_referral_entry->map_cache_entry, referral_entry->mapping->eid_prefix,
                    referral_entry->mapping->eid_prefix_length,1,MAPPING_ACT_NO_ACTION);
            if (err != GOOD){
                del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                        pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
            }
        }
        remove_pending_referral_cache_entry_from_list(pending_referral_entry);
    }
    free_referral_cache_entry(referral_entry);

    return (err);
}
示例#2
0
int send_map_request_miss(timer *t, void *arg)
{
    timer_map_request_argument *argument = (timer_map_request_argument *)arg;
    lispd_map_cache_entry *map_cache_entry = argument->map_cache_entry;
    nonces_list *nonces = map_cache_entry->nonces;
    lisp_addr_t *dst_rloc = NULL;

    if (nonces == NULL){
        nonces = new_nonces_list();
        if (nonces==NULL){
            lispd_log_msg(LISP_LOG_WARNING,"Send_map_request_miss: Unable to allocate memory for nonces.");
            return (BAD);
        }
        map_cache_entry->nonces = nonces;
    }

    if (nonces->retransmits - 1 < map_request_retries ){

        if (map_cache_entry->request_retry_timer == NULL){
            map_cache_entry->request_retry_timer = create_timer (MAP_REQUEST_RETRY_TIMER);
        }

        if (nonces->retransmits > 0){
            lispd_log_msg(LISP_LOG_DEBUG_1,"Retransmiting Map Request for EID: %s (%d retries)",
                    get_char_from_lisp_addr_t(map_cache_entry->mapping->eid_prefix),
                    nonces->retransmits);
        }

        /* Get the RLOC of the Map Resolver to be used */
        dst_rloc = get_map_resolver();

        if ((dst_rloc == NULL) || (build_and_send_map_request_msg(
                map_cache_entry->mapping,
                &(argument->src_eid),
                dst_rloc,
                1,
                0,
                0,
                0,
                &nonces->nonce[nonces->retransmits]))==BAD){
            lispd_log_msg (LISP_LOG_DEBUG_1, "send_map_request_miss: Couldn't send map request for a new map cache entry");

        }

        nonces->retransmits ++;
        start_timer(map_cache_entry->request_retry_timer, LISPD_INITIAL_MRQ_TIMEOUT,
                send_map_request_miss, (void *)argument);

    }else{
        lispd_log_msg(LISP_LOG_DEBUG_1,"No Map Reply fot EID %s/%d after %d retries. Removing map cache entry ...",
                        get_char_from_lisp_addr_t(map_cache_entry->mapping->eid_prefix),
                        map_cache_entry->mapping->eid_prefix_length,
                        nonces->retransmits -1);
        del_map_cache_entry_from_db(map_cache_entry->mapping->eid_prefix,
                map_cache_entry->mapping->eid_prefix_length);

    }
    return GOOD;
}
示例#3
0
int process_ms_not_registered_reply(
        lispd_referral_cache_entry              *referral_entry,
        lispd_pending_referral_cache_entry      *pending_referral_entry)
{
    lispd_referral_cache_entry              *db_referral_entry = NULL;

    db_referral_entry = lookup_referral_cache_exact(
            referral_entry->mapping->eid_prefix, referral_entry->mapping->eid_prefix_length, DDT_END_PREFIX_DATABASES);

    /* Add referral cache entry to database */
    if (db_referral_entry == NULL){
        if (add_referral_cache_entry_to_db(referral_entry) != GOOD){
            lispd_log_msg(LISP_LOG_DEBUG_1,"process_ms_not_registered_reply: Coudn't add referral cache entry for prefix %s/%d",
                    get_char_from_lisp_addr_t(referral_entry->mapping->eid_prefix), referral_entry->mapping->eid_prefix_length);
            free_referral_cache_entry(referral_entry);
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
            return (BAD);
        }
        add_referral_cache_entry_to_tree(pending_referral_entry->previous_referral,referral_entry);
        pending_referral_entry->previous_referral = referral_entry;
    }else{
        /* Entry already exist. Replace it with the new data. Valid if the previous entry was a ms ack or ms not registered ack */
        update_referral_cache_data(db_referral_entry, referral_entry);
        free_referral_cache_entry(referral_entry);
        referral_entry = db_referral_entry;
    }
    /* Try with the next ddt node*/
    pending_referral_entry->tried_locators = pending_referral_entry->tried_locators + 1;
    lispd_log_msg(LISP_LOG_DEBUG_1,"process_ms_not_registered_reply: Receive a MS_NOT_REGISTERED referral. Trying next node");
    err = send_ddt_map_request_miss(NULL,(void *)pending_referral_entry);
    /* If we asked to all MS where prefix is delegated and all reply  MS_NOT_REGISTERED, remove entry from pending list
     * and activate map cache*/
    if (err == ERR_DST_ADDR){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_ms_not_registered_reply: Tried all noedes. Activate negative map reply");
        if (activate_negative_map_cache (pending_referral_entry->map_cache_entry, referral_entry->mapping->eid_prefix,
                referral_entry->mapping->eid_prefix_length,referral_entry->ttl,MAPPING_ACT_NO_ACTION) != GOOD){
            del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                    pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
        }
        remove_pending_referral_cache_entry_from_list(pending_referral_entry);
        /* Program expiry time */
        program_referral_expiry_timer(referral_entry);
    }
    return (GOOD);
}
示例#4
0
int process_delegation_hole_reply(
        lispd_referral_cache_entry              *referral_entry,
        lispd_pending_referral_cache_entry      *pending_referral_entry)
{

    lispd_referral_cache_entry              *db_referral_entry = NULL;

    db_referral_entry = lookup_referral_cache_exact(
            referral_entry->mapping->eid_prefix, referral_entry->mapping->eid_prefix_length, DDT_END_PREFIX_DATABASES);

    if (db_referral_entry != NULL && db_referral_entry->act_entry_type != DELEGATION_HOLE){
        del_referral_cache_entry_from_db(db_referral_entry);
        db_referral_entry = NULL;
    }
    if (db_referral_entry == NULL){
        /* Add referral cache entry to database */

        if (add_referral_cache_entry_to_db(referral_entry) != GOOD){
            lispd_log_msg(LISP_LOG_DEBUG_1,"process_delegation_hole_reply: Coudn't add referral cache entry for prefix %s/%d",
                    get_char_from_lisp_addr_t(referral_entry->mapping->eid_prefix), referral_entry->mapping->eid_prefix_length);
            free_referral_cache_entry(referral_entry);
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
            return (BAD);
        }
        add_referral_cache_entry_to_tree(pending_referral_entry->previous_referral,referral_entry);
    }else{
        /* Entry already exist. Replace it with the new data.*/
        update_referral_cache_data(db_referral_entry, referral_entry);
        free_referral_cache_entry(referral_entry);
        referral_entry = db_referral_entry;
    }
    /*Remove entry from pending list and activate map cache*/
    if (activate_negative_map_cache (pending_referral_entry->map_cache_entry, referral_entry->mapping->eid_prefix,
            referral_entry->mapping->eid_prefix_length,referral_entry->ttl,MAPPING_ACT_NO_ACTION)!=GOOD){
        del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                           pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
    }
    remove_pending_referral_cache_entry_from_list(pending_referral_entry);
    /* Program expiry time */
    program_referral_expiry_timer(referral_entry);
    return(GOOD);
}
示例#5
0
int process_ms_referral_reply(
        lispd_referral_cache_entry              *referral_entry,
        lispd_pending_referral_cache_entry      *pending_referral_entry)
{
    lispd_referral_cache_entry              *db_referral_entry = NULL;

    if (pending_referral_entry->previous_referral->act_entry_type == MS_NOT_REGISTERED ){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_node_referral_reply: Previous ddt referral was a MS_NOT_REGISTERED "
                "reply and the current one is a NODE REFERRAL. This should never happend. Try next node");
        /* Try with the next ddt node*/
        err = try_next_referral_node_or_go_through_root (pending_referral_entry);
        if (err != GOOD){
            if (err == ERR_DST_ADDR){
                lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_referral_record: Error detected in the ddt process-> "
                        "error in the ddt tree");
                err = activate_negative_map_cache (pending_referral_entry->map_cache_entry,
                        pending_referral_entry->previous_referral->mapping->eid_prefix,
                        pending_referral_entry->previous_referral->mapping->eid_prefix_length,
                        1,MAPPING_ACT_NO_ACTION);
                if (err != GOOD){
                    del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                            pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
                }
            }
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
        }

        free_referral_cache_entry(referral_entry);
        return (BAD);
    }

    db_referral_entry = lookup_referral_cache_exact(
            referral_entry->mapping->eid_prefix, referral_entry->mapping->eid_prefix_length, DDT_NOT_END_PREFIX_DATABASES);
    if (db_referral_entry == NULL){
        /*
         * If we receive a node referral mesage for and EID prefix for which we have ms-ack in the database but not a node-referral,
         * then remove the ms-ack entry from the database and add the node referral entry with same prefix. Probably the ms-ack entry
         * will be generated again in the next iteration of ddt.
         */
        db_referral_entry = lookup_referral_cache_exact(
                referral_entry->mapping->eid_prefix, referral_entry->mapping->eid_prefix_length, DDT_END_PREFIX_DATABASES);
        if (db_referral_entry != NULL){
            del_referral_cache_entry_from_db(db_referral_entry);
            db_referral_entry = NULL;
        }
    }else{
        /* Entry already exist. Replace it with the new data. Valid if the previous entry was a node referral, ms referral or delegation hole */
        update_referral_cache_data(db_referral_entry, referral_entry);
        free_referral_cache_entry(referral_entry);
        referral_entry = db_referral_entry;
    }
    /* Add referral cache entry to database */
    if (db_referral_entry == NULL){
        if (add_referral_cache_entry_to_db(referral_entry) != GOOD){
            lispd_log_msg(LISP_LOG_DEBUG_1,"process_ms_referral_reply: Coudn't add referral cache entry for prefix %s/%d",
                    get_char_from_lisp_addr_t(referral_entry->mapping->eid_prefix), referral_entry->mapping->eid_prefix_length);
            free_referral_cache_entry(referral_entry);
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
            return (BAD);
        }
        add_referral_cache_entry_to_tree(pending_referral_entry->previous_referral,referral_entry);
    }
    /* Program expiry time */
    program_referral_expiry_timer(referral_entry);
    /* Update pending referral cache and proceed with the search in the ddt tree */
    pending_referral_entry->previous_referral = referral_entry;
    pending_referral_entry->tried_locators = 0;
    if (send_ddt_map_request_miss(NULL,(void *)pending_referral_entry)!=GOOD){
        return (BAD);
    }

    return (GOOD);
}
示例#6
0
int process_map_referral_record(
        uint8_t **offset,
        uint64_t nonce)
{
    uint8_t                                 *cur_ptr                    = NULL;
    lispd_pkt_referral_mapping_record_t     *record                     = NULL;
    lispd_referral_cache_entry              *referral_entry             = NULL;
    lispd_referral_cache_entry              *previous_referral_entry    = NULL;
    lispd_mapping_elt                       *referral_mapping           = NULL;
    lispd_pending_referral_cache_entry      *pending_referral_entry     = NULL;
    lispd_map_cache_entry                   *map_cache_entry            = NULL;
    lisp_addr_t                             ddt_node_locator_addr       = {.afi=AF_UNSPEC};
    lisp_addr_t                             aux_eid_prefix;
    int                                     aux_eid_prefix_length       = 0;
    int                                     aux_iid                     = 0;
    int                                     ctr                         = 0;
    int                                     result                      = GOOD;
    int                                     detected_loop               = FALSE;

    cur_ptr = *offset;

    record = (lispd_pkt_referral_mapping_record_t *)(cur_ptr);


    pending_referral_entry = lookup_pending_referral_cache_entry_by_nonce (nonce);

    if (pending_referral_entry == NULL){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_referral_record:  The nonce of the Map-Referral doesn't match the nonce of any generated Map-Request. Discarding message ...");
        free_mapping_elt(referral_mapping);
        return (BAD);
    }else {
        if (pending_referral_entry->previous_referral->act_entry_type == MS_NOT_REGISTERED){
            previous_referral_entry = pending_referral_entry->previous_referral->parent_node;
            ddt_node_locator_addr = get_ddt_locator_addr_at_position(pending_referral_entry->previous_referral->parent_node,
                    ctrl_supported_afi, pending_referral_entry->tried_locators);
        }else{
            previous_referral_entry = pending_referral_entry->previous_referral;
            ddt_node_locator_addr = get_ddt_locator_addr_at_position(pending_referral_entry->previous_referral,
                    ctrl_supported_afi, pending_referral_entry->tried_locators);
        }
    }

    free(pending_referral_entry->nonces);
    pending_referral_entry->nonces = NULL;

    /* Stop the timer to not retry to send the map request */
    stop_timer(pending_referral_entry->ddt_request_retry_timer);
    pending_referral_entry->ddt_request_retry_timer = NULL;


    /* Fill a auxiliar mapping with the information of the packet */
    referral_mapping = new_mapping(aux_eid_prefix,aux_eid_prefix_length,aux_iid);
    if (referral_mapping == NULL){
        return (BAD);
    }
    cur_ptr = (uint8_t *)&(record->eid_prefix_afi);
    if (pkt_process_eid_afi(&cur_ptr,referral_mapping) != GOOD){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_referral_record:  Error processing the EID of the map reply record");
        free_mapping_elt(referral_mapping);
        return (BAD);
    }
    referral_mapping->eid_prefix_length = record->eid_prefix_length;

    /* Check that the requested EID belongs to the returned prefix in the referral */
    if (is_prefix_b_part_of_a (
            referral_mapping->eid_prefix,
            referral_mapping->eid_prefix_length,
            pending_referral_entry->map_cache_entry->mapping->eid_prefix,
            pending_referral_entry->map_cache_entry->mapping->eid_prefix_length) == FALSE){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_referral_record: The requested EID doesn't belong to the prefix received "
                            "in the map referral: EID: %s  -   received prefix: %s/%d",
                            get_char_from_lisp_addr_t(pending_referral_entry->map_cache_entry->mapping->eid_prefix),
                            get_char_from_lisp_addr_t(referral_mapping->eid_prefix),referral_mapping->eid_prefix_length);
        err = try_next_referral_node_or_go_through_root (pending_referral_entry);
        if (err != GOOD){
            if (err == ERR_DST_ADDR){
                err = activate_negative_map_cache (pending_referral_entry->map_cache_entry,
                        pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                        pending_referral_entry->map_cache_entry->mapping->eid_prefix_length,
                        1,MAPPING_ACT_NO_ACTION);
                if (err != GOOD){
                    del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                            pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
                }
            }
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
        }
        free_mapping_elt(referral_mapping);

        return (BAD);
    }


    /*
     * Avoid loops:
     *   - Check that the returned referral has a more specific prefix than the previous referral
     *   - If received referral is: MS_REFERRAL or NODE_REFERRAL, Check that its prefix is diferent from the previous one.
     */

    if (is_prefix_b_part_of_a (
            previous_referral_entry->mapping->eid_prefix,
            previous_referral_entry->mapping->eid_prefix_length,
            referral_mapping->eid_prefix,
            referral_mapping->eid_prefix_length) == FALSE){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_referral_record: Loop detected in the ddt process-> "
                "received prefix: %s/%d  -   previous prefix: %s/%d. Trying next ddt node",
                get_char_from_lisp_addr_t(referral_mapping->eid_prefix),referral_mapping->eid_prefix_length,
                get_char_from_lisp_addr_t(previous_referral_entry->mapping->eid_prefix),
                previous_referral_entry->mapping->eid_prefix_length);
        detected_loop = TRUE;
    }else if ((previous_referral_entry->mapping->eid_prefix_length == referral_mapping->eid_prefix_length) &&
            (record->action == NODE_REFERRAL || record->action == MS_REFERRAL)){
        lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_referral_record: Loop detected in the ddt process-> "
                "%s message contains same prefix as last referral iteration : %s/%d",
                (record->action == NODE_REFERRAL ? "Node referral" : "MS referral"),
                get_char_from_lisp_addr_t(referral_mapping->eid_prefix),
                referral_mapping->eid_prefix_length);
        detected_loop = TRUE;
    }

    if ( detected_loop == TRUE){
        /* Try with the next ddt node*/
        err = try_next_referral_node_or_go_through_root (pending_referral_entry);
        if (err != GOOD){
            if (err == ERR_DST_ADDR){
                lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_referral_record: Loop detected in the ddt process-> "
                        "error in the ddt tree");
                err = activate_negative_map_cache (pending_referral_entry->map_cache_entry,
                        previous_referral_entry->mapping->eid_prefix,
                        previous_referral_entry->mapping->eid_prefix_length,
                        1,MAPPING_ACT_NO_ACTION);
                if (err != GOOD){
                    del_map_cache_entry_from_db(pending_referral_entry->map_cache_entry->mapping->eid_prefix,
                            pending_referral_entry->map_cache_entry->mapping->eid_prefix_length);
                }
            }
            remove_pending_referral_cache_entry_from_list(pending_referral_entry);
        }

        free_mapping_elt(referral_mapping);
        return (BAD);
    }

    map_cache_entry = pending_referral_entry->map_cache_entry;

    if (map_cache_entry->mapping->iid != referral_mapping->iid){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_referral_record:  Instance ID of the map referral doesn't match with the pending referral cache entry");
        free_mapping_elt(referral_mapping);
        remove_pending_referral_cache_entry_from_list(pending_referral_entry);
        return (BAD);
    }
    /* Create the referral cache entry */
    referral_entry = new_referral_cache_entry(referral_mapping, record->action, ntohl(record->ttl));
    referral_entry->src_inf_ddt_node_locator_addr = ddt_node_locator_addr;

    /* Get the locators list */
    for (ctr=0 ; ctr < record->locator_count ; ctr++){
        if ((process_map_referral_locator (&cur_ptr, referral_entry->mapping)) != GOOD){
            return(BAD);
        }
    }

    lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_referral_record:Answer from %s : Authoritative: %d , Incomplete: %d",
            get_char_from_lisp_addr_t(referral_entry->src_inf_ddt_node_locator_addr),record->authoritative,record->incomplete);

    dump_referral_cache_entry(referral_entry,LISP_LOG_DEBUG_2);

    switch (referral_entry->act_entry_type){
        case NODE_REFERRAL:
            result = process_node_referral_reply(referral_entry,pending_referral_entry);
            break;
        case MS_REFERRAL:
            result = process_ms_referral_reply(referral_entry,pending_referral_entry);
            break;
        case MS_ACK:
            result = process_ms_ack_reply(referral_entry,pending_referral_entry);
            break;
        case MS_NOT_REGISTERED:
            result = process_ms_not_registered_reply(referral_entry,pending_referral_entry);
            break;
        case DELEGATION_HOLE:
            result = process_delegation_hole_reply(referral_entry,pending_referral_entry);
            break;
        case NOT_AUTHORITATIVE:
            result = process_not_authoritative_reply(referral_entry,pending_referral_entry);
            break;
        default:
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_referral_record: Referral record %s/%d  with not supported action: %d",
                    get_char_from_lisp_addr_t(referral_mapping->eid_prefix),referral_mapping->eid_prefix_length,referral_entry->act_entry_type);
            result = BAD;
            break;
    }

    return (result);
}