Ejemplo n.º 1
0
 int process_map_request_record(
         uint8_t **cur_ptr,
         lisp_addr_t *local_rloc,
         lisp_addr_t *remote_rloc,
         uint16_t dst_port,
         uint8_t rloc_probe,
         uint64_t nonce)
 {
     lispd_pkt_map_request_eid_prefix_record_t  *record                 = NULL;
     lispd_mapping_elt                          *requested_mapping      = NULL;
     lispd_mapping_elt                          *mapping                = NULL;
     map_reply_opts                             opts;
     lisp_addr_t                                aux_eid_prefix;
     int                                        aux_eid_prefix_length   = 0;
     int                                        aux_iid                 = -1;

     /* Get the requested EID prefix */
     record = (lispd_pkt_map_request_eid_prefix_record_t *)*cur_ptr;
     /* Auxiliar lispd_mapping_elt created to be filled with pkt_process_eid_afi */
     requested_mapping = new_local_mapping(aux_eid_prefix, aux_eid_prefix_length, aux_iid);
     if (requested_mapping == NULL){
         return (BAD);
     }
     *cur_ptr = (uint8_t *)&(record->eid_prefix_afi);
     if ((err=pkt_process_eid_afi(cur_ptr, requested_mapping))!=GOOD){
         lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_request_record: Requested EID could not be processed");
         free_mapping_elt (requested_mapping, TRUE);
         return (err);
     }
     requested_mapping->eid_prefix_length = record->eid_prefix_length;

     /* Check the existence of the requested EID */
     /*  We don't use prefix mask and use by default 32 or 128*/
     mapping = lookup_eid_in_db(requested_mapping->eid_prefix);
     if (!mapping){
         lispd_log_msg(LISP_LOG_DEBUG_1,"The requested EID doesn't belong to this node: %s/%d",
                 get_char_from_lisp_addr_t(requested_mapping->eid_prefix),
                 requested_mapping->eid_prefix_length);
         free_mapping_elt (requested_mapping, TRUE);
         return (BAD);
     }
     free_mapping_elt (requested_mapping, TRUE);

     /* Set flags for Map-Reply */
     opts.send_rec   = 1;
     opts.echo_nonce = 0;
     opts.rloc_probe = rloc_probe;

     err = build_and_send_map_reply_msg(mapping, local_rloc, remote_rloc, dst_port, nonce, opts);

     return (err);
 }
Ejemplo n.º 2
0
void free_referral_cache_entry_recursive(lispd_referral_cache_entry *referral_cache_entry)
{
    free_mapping_elt (referral_cache_entry->mapping);
    if (referral_cache_entry->expiry_ddt_cache_timer != NULL){
        stop_timer(referral_cache_entry->expiry_ddt_cache_timer);
    }
    remove_referral_cache_entry_from_parent_node(referral_cache_entry);
    free_lispd_referral_cache_list(referral_cache_entry->children_nodes);
    free (referral_cache_entry);
}
Ejemplo n.º 3
0
/*
 * Generates a clone of a lispd_mapping_elt. Parameters like timers or nonces are not cloned
 */
lispd_mapping_elt *copy_mapping_elt(lispd_mapping_elt *elt)
{
    lispd_mapping_elt *mapping = NULL;
    mapping = new_mapping(elt->eid_prefix,elt->eid_prefix_length,elt->iid);
    if (mapping == NULL){
        return (NULL);
    }
    mapping->locator_count = elt->locator_count;
    if (elt->head_v4_locators_list != NULL){
        mapping->head_v4_locators_list = copy_locators_list(elt->head_v4_locators_list);
        if (mapping->head_v4_locators_list == NULL){
            free_mapping_elt(mapping);
            return (NULL);
        }
    }
    if(elt->head_v6_locators_list != NULL){
        mapping->head_v6_locators_list = copy_locators_list(elt->head_v6_locators_list);
        if (mapping->head_v6_locators_list == NULL){
            free_mapping_elt(mapping);
            return(NULL);
        }
    }
    if (elt->extended_info != NULL){
        if (mapping->mapping_type == LOCAL_MAPPING){
            mapping->extended_info = (void *)copy_lcl_mapping_extended_info((lcl_mapping_extended_info *)elt->extended_info);
            if (mapping->extended_info == NULL){
                free_mapping_elt(mapping);
                return(NULL);
            }
            calculate_balancing_vectors (mapping,&(((lcl_mapping_extended_info *)mapping->extended_info)->outgoing_balancing_locators_vecs));
        }else{
            mapping->extended_info = (void *)copy_rmt_mapping_extended_info((rmt_mapping_extended_info *)elt->extended_info);
            if (mapping->extended_info == NULL){
                free_mapping_elt(mapping);
                return(NULL);
            }
            calculate_balancing_vectors (mapping,&(((rmt_mapping_extended_info *)mapping->extended_info)->rmt_balancing_locators_vecs));
        }
    }

    return (mapping);
}
Ejemplo n.º 4
0
/*
 * Copy from the src referral cache to the dst referral cache the following data: mapping, act and ttl
 * @param dst_referral Destination of the data to be copied. The timer should be restarted outside this function
 * @param src_referral Source of the data to be copied
 * @return GOOD if finish correctly or an error code otherwise
 */
int update_referral_cache_data(
        lispd_referral_cache_entry *dst_referral,
        lispd_referral_cache_entry *src_referral)
{
    free_mapping_elt (dst_referral->mapping);
    dst_referral->mapping = copy_mapping_elt(src_referral->mapping);
    if (dst_referral->mapping == NULL){
        return (BAD);
    }
    dst_referral->act_entry_type = src_referral->act_entry_type;
    dst_referral->ttl = src_referral->ttl;
    return (GOOD);
}
Ejemplo n.º 5
0
void free_referral_cache_entry(lispd_referral_cache_entry *referral_cache_entry)
{
    lispd_referral_cache_list *list_elt          = referral_cache_entry->children_nodes;
    lispd_referral_cache_list *aux_list_elt      = NULL;
    free_mapping_elt (referral_cache_entry->mapping);
    /* We remove the list of childs (lispd_referral_cache_list) but not the childs  (lispd_referral_cache_entry)*/
    while (list_elt != NULL){
        aux_list_elt = list_elt->next;
        free(aux_list_elt);
        list_elt = aux_list_elt;
    }
    if (referral_cache_entry->expiry_ddt_cache_timer != NULL){
        stop_timer(referral_cache_entry->expiry_ddt_cache_timer);
    }
    free (referral_cache_entry);
}
Ejemplo n.º 6
0
/*
 * Generates a mapping with the local extended info
 */
lispd_mapping_elt *new_local_mapping(
        lisp_addr_t     eid_prefix,
        uint8_t         eid_prefix_length,
        int             iid)
{
    lispd_mapping_elt           *mapping        = NULL;

    if ((mapping = new_mapping (eid_prefix, eid_prefix_length, iid)) == NULL){
        return (NULL);
    }

    mapping->mapping_type = LOCAL_MAPPING;
    mapping->extended_info = (void *)new_lcl_mapping_extended_info();
    if (mapping->extended_info == NULL){
        free_mapping_elt(mapping);
        return (NULL);
    }
    return (mapping);
}
Ejemplo n.º 7
0
int process_map_reply_probe_record(
        uint8_t     **cur_ptr,
        uint64_t    nonce)
{
    lispd_pkt_mapping_record_t              *record                 = NULL;
    lispd_mapping_elt                       *mapping                = NULL;
    lispd_map_cache_entry                   *cache_entry            = NULL;
    lispd_locator_elt                       *aux_locator            = NULL;
    lispd_locator_elt                       *locator                = NULL;
    rmt_locator_extended_info               *rmt_locator_ext_inf    = NULL;
    lispd_locators_list                     *locators_list[2]       = {NULL,NULL};
    lisp_addr_t                             aux_eid_prefix;
    int                                     aux_eid_prefix_length   = 0;
    int                                     aux_iid                 = 0;
    int                                     ctr                     = 0;
    int                                     locators_probed         = 0;

    record = (lispd_pkt_mapping_record_t *)(*cur_ptr);
    mapping = new_map_cache_mapping(aux_eid_prefix,aux_eid_prefix_length,aux_iid);
    if (mapping == NULL){
        return (BAD);
    }
    *cur_ptr = (uint8_t *)&(record->eid_prefix_afi);
    if (!pkt_process_eid_afi(cur_ptr,mapping)){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_probe_record:  Error processing the EID of the map reply record");
        free_mapping_elt(mapping);
        return (BAD);
    }
    mapping->eid_prefix_length = record->eid_prefix_length;

    if (record->locator_count != 0 ){
        /* Serch map cache entry exist*/
        cache_entry = lookup_map_cache_exact(mapping->eid_prefix,mapping->eid_prefix_length);
        if (cache_entry == NULL){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_probe_record:  No map cache entry found for %s/%d",
                    get_char_from_lisp_addr_t(mapping->eid_prefix),mapping->eid_prefix_length);
            free_mapping_elt(mapping);
            return (BAD);
        }

        /* Check instane id.*/
        if (cache_entry->mapping->iid != mapping->iid){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_probe_record:  Instance ID of the map reply doesn't match with the map cache entry");
            free_mapping_elt(mapping);
            return (BAD);
        }


        /* Free auxiliar mapping used to search the map cache entry*/
        free_mapping_elt(mapping);

        /*
         * Check probed locators of the list. Only one locator can be probed per message
         */
        for (ctr=0 ; ctr < record->locator_count ; ctr++){
            err = process_map_reply_probe_locator (cur_ptr, cache_entry->mapping, nonce, &locator);
            if (err == ERR_MALLOC){
                return (BAD);
            }
            if (locator == NULL){ // The current locator is not probed
                continue;
            }
            rmt_locator_ext_inf = (rmt_locator_extended_info *)(locator->extended_info);
            /* Check the nonce of the message match with the one stored in the structure of the locator */
            if ((check_nonce(rmt_locator_ext_inf->rloc_probing_nonces,nonce)) == GOOD){
                free(rmt_locator_ext_inf->rloc_probing_nonces);
                rmt_locator_ext_inf->rloc_probing_nonces = NULL;
                if (locators_probed == 0){
                    aux_locator = locator;
                    locators_probed ++;
                }else{
                    lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_reply_probe_record: Invalid Map-Reply Probe. Only one locator can be probed per message");
                    return (BAD);
                }
            }else{
                lispd_log_msg(LISP_LOG_DEBUG_1,"The nonce of the Map-Reply Probe doesn't match the nonce of the generated Map-Request Probe. Discarding message ...");
                return (BAD);
            }
        }
        locator = aux_locator;
        if (locator ==  NULL){
            lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_reply_probe_record: Invalid Map-Reply Probe. No probed locator of the received message matches with the "
                    "locators of the mapping  stored in the map cahce database.");
            return (BAD);
        }
        lispd_log_msg(LISP_LOG_DEBUG_1,"Map-Reply probe reachability to RLOC %s of the EID cache entry %s/%d",
                    get_char_from_lisp_addr_t(*(locator->locator_addr)),
                    get_char_from_lisp_addr_t(cache_entry->mapping->eid_prefix),
                    cache_entry->mapping->eid_prefix_length);

    }else{ // Probe of a negative map cache -> proxy-etr
        if(proxy_etrs != NULL && compare_lisp_addr_t(&(mapping->eid_prefix),&(proxy_etrs->mapping->eid_prefix)) == 0){
            cache_entry = proxy_etrs;
            locators_list[0] = proxy_etrs->mapping->head_v4_locators_list;
            locators_list[1] = proxy_etrs->mapping->head_v6_locators_list;

            for (ctr=0 ; ctr < 2 ; ctr++){
                while (locators_list[ctr]!=NULL){
                    aux_locator = locators_list[ctr]->locator;
                    rmt_locator_ext_inf = (rmt_locator_extended_info *)(aux_locator->extended_info);
                    if ((check_nonce(rmt_locator_ext_inf->rloc_probing_nonces,nonce)) == GOOD){
                        free (rmt_locator_ext_inf->rloc_probing_nonces);
                        rmt_locator_ext_inf->rloc_probing_nonces = NULL;
                        locator = aux_locator;
                        break;
                    }
                    locators_list[ctr] = locators_list[ctr]->next;
                }
                if (locator != NULL){
                    break;
                }
            }
            if (locator == NULL){
                lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_reply_probe_record: The nonce of the Negative Map-Reply Probe don't match any nonce of Proxy-ETR locators");
                free_mapping_elt(mapping);
                return (BAD);
            }
            free_mapping_elt(mapping);
        }else{
            lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_reply_probe_record: The received negative Map-Reply Probe has not been requested: %s/%d",
                    get_char_from_lisp_addr_t(mapping->eid_prefix),mapping->eid_prefix_length);
            free_mapping_elt(mapping);
            return (BAD);
        }

        lispd_log_msg(LISP_LOG_DEBUG_1,"Map-Reply probe reachability to the PETR with RLOC %s",
                    get_char_from_lisp_addr_t(*(locator->locator_addr)));
    }



    if (*(locator->state) == DOWN){
        *(locator->state) = UP;

        lispd_log_msg(LISP_LOG_DEBUG_1,"Map-Reply Probe received for locator %s -> Locator state changes to UP",
                           get_char_from_lisp_addr_t(*(locator->locator_addr)));

        /* [re]Calculate balancing locator vectors  if it has been a change of status*/
        calculate_balancing_vectors (
                cache_entry->mapping,
                &(((rmt_mapping_extended_info *)cache_entry->mapping->extended_info)->rmt_balancing_locators_vecs));
    }
    /*
     * Reprogramming timers of rloc probing
     */
    rmt_locator_ext_inf = (rmt_locator_extended_info *)(locator->extended_info);
    if (rmt_locator_ext_inf->probe_timer == NULL){
       lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_reply_probe_record: The received Map-Reply Probe was not requested");
       return (BAD);
    }

    start_timer(rmt_locator_ext_inf->probe_timer, rloc_probe_interval, (timer_callback)rloc_probing,rmt_locator_ext_inf->probe_timer->cb_argument);
    if (record->locator_count != 0 ){
        lispd_log_msg(LISP_LOG_DEBUG_2,"Reprogramed RLOC probing of the locator %s of the EID %s/%d in %d seconds",
                get_char_from_lisp_addr_t(*(locator->locator_addr)),
                get_char_from_lisp_addr_t(cache_entry->mapping->eid_prefix),
                cache_entry->mapping->eid_prefix_length, rloc_probe_interval);
    }else{
        lispd_log_msg(LISP_LOG_DEBUG_2,"Reprogramed RLOC probing of the locator %s (PETR) in %d seconds",
                get_char_from_lisp_addr_t(*(locator->locator_addr)), rloc_probe_interval);
    }

    return (GOOD);
}
Ejemplo n.º 8
0
int process_map_reply_record(uint8_t **cur_ptr, uint64_t nonce)
{
    lispd_pkt_mapping_record_t              *record                 = NULL;
    lispd_mapping_elt                       *mapping                = NULL;
    lispd_map_cache_entry                   *cache_entry            = NULL;
    lisp_addr_t                             aux_eid_prefix;
    int                                     aux_eid_prefix_length   = 0;
    int                                     aux_iid                 = 0;
    int                                     ctr                     = 0;
    uint8_t                                 is_new_mapping          = FALSE;

    record = (lispd_pkt_mapping_record_t *)(*cur_ptr);
    mapping = new_map_cache_mapping(aux_eid_prefix,aux_eid_prefix_length,aux_iid);
    if (mapping == NULL){
        return (BAD);
    }
    *cur_ptr = (uint8_t *)&(record->eid_prefix_afi);
    if (!pkt_process_eid_afi(cur_ptr,mapping)){
        lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_record:  Error processing the EID of the map reply record");
        free_mapping_elt(mapping);
        return (BAD);
    }
    mapping->eid_prefix_length = record->eid_prefix_length;


    /*
     * Check if the map replay corresponds to a not active map cache
     */

    cache_entry = lookup_nonce_in_no_active_map_caches(mapping->eid_prefix.afi, nonce);


    if (cache_entry != NULL){
        if (cache_entry->mapping->iid != mapping->iid){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_record:  Instance ID of the map reply doesn't match with the inactive map cache entry");
            free_mapping_elt(mapping);
            return (BAD);
        }
        /*
         * If the eid prefix of the received map reply doesn't match the inactive map cache entry (x.x.x.x/32 or x:x:x:x:x:x:x:x/128),then
         * we remove the inactie entry from the database and store it again with the correct eix prefix (for instance /24).
         */
        if (cache_entry->mapping->eid_prefix_length != mapping->eid_prefix_length){
            if (change_map_cache_prefix_in_db(mapping->eid_prefix, mapping->eid_prefix_length, cache_entry) != GOOD){
                free_mapping_elt(mapping);
                return (BAD);
            }
        }
        cache_entry->active = 1;
        stop_timer(cache_entry->request_retry_timer);
        cache_entry->request_retry_timer = NULL;
        lispd_log_msg(LISP_LOG_DEBUG_2,"  Activating map cache entry %s/%d",
                            get_char_from_lisp_addr_t(mapping->eid_prefix),mapping->eid_prefix_length);
        free_mapping_elt(mapping);
        is_new_mapping = TRUE;
    }
    /* If the nonce is not found in the no active cache enties, then it should be an active cache entry */
    else {
        /* Serch map cache entry exist*/
        cache_entry = lookup_map_cache_exact(mapping->eid_prefix,mapping->eid_prefix_length);
        if (cache_entry == NULL){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_record:  No map cache entry found for %s/%d",
                    get_char_from_lisp_addr_t(mapping->eid_prefix),mapping->eid_prefix_length);
            free_mapping_elt(mapping);
            return (BAD);
        }
        /* Check the found map cache entry contain the nonce of the map reply*/
        if (check_nonce(cache_entry->nonces,nonce)==BAD){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_record:  The nonce of the Map-Reply doesn't match the nonce of the generated Map-Request. Discarding message ...");
            free_mapping_elt(mapping);
            return (BAD);
        }else {
            free(cache_entry->nonces);
            cache_entry->nonces = NULL;
        }
        /* Stop timer of Map Requests retransmits */
        if (cache_entry->smr_inv_timer != NULL){
            stop_timer(cache_entry->smr_inv_timer);
            cache_entry->smr_inv_timer = NULL;
        }
        /* Check instane id.*/
        if (cache_entry->mapping->iid != mapping->iid){
            lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_reply_record:  Instance ID of the map reply doesn't match with the map cache entry");
            free_mapping_elt(mapping);
            return (BAD);
        }
        lispd_log_msg(LISP_LOG_DEBUG_2,"  A map cache entry already exists for %s/%d, replacing locators list of this entry",
                get_char_from_lisp_addr_t(cache_entry->mapping->eid_prefix),
                cache_entry->mapping->eid_prefix_length);
        free_locator_list(cache_entry->mapping->head_v4_locators_list);
        free_locator_list(cache_entry->mapping->head_v6_locators_list);
        cache_entry->mapping->head_v4_locators_list = NULL;
        cache_entry->mapping->head_v6_locators_list = NULL;
        free_mapping_elt(mapping);
    }
    cache_entry->actions = record->action;
    cache_entry->ttl = ntohl(record->ttl);
    cache_entry->active_witin_period = 1;
    cache_entry->timestamp = time(NULL);
    //locator_count updated when adding the processed locators

    /* Generate the locators */
    for (ctr=0 ; ctr < record->locator_count ; ctr++){
        if ((process_map_reply_locator (cur_ptr, cache_entry->mapping)) != GOOD){
            return(BAD);
        }
    }

    if (is_loggable(LISP_LOG_DEBUG_2)){
        dump_map_cache_entry(cache_entry, LISP_LOG_DEBUG_2);
    }

    /* [re]Calculate balancing locator vectors  if it is not a negative map reply*/
    if (cache_entry->mapping->locator_count != 0){
        calculate_balancing_vectors (
                cache_entry->mapping,
                &(((rmt_mapping_extended_info *)cache_entry->mapping->extended_info)->rmt_balancing_locators_vecs));
    }
    /*
     * Reprogramming timers
     */
    /* Expiration cache timer */
    if (!cache_entry->expiry_cache_timer){
        cache_entry->expiry_cache_timer = create_timer (EXPIRE_MAP_CACHE_TIMER);
    }
    start_timer(cache_entry->expiry_cache_timer, cache_entry->ttl*60, (timer_callback)map_cache_entry_expiration,
                     (void *)cache_entry);
    lispd_log_msg(LISP_LOG_DEBUG_1,"The map cache entry %s/%d will expire in %d minutes.",
            get_char_from_lisp_addr_t(cache_entry->mapping->eid_prefix),
            cache_entry->mapping->eid_prefix_length, cache_entry->ttl);

    /* RLOC probing timer */
    if (is_new_mapping == TRUE && rloc_probe_interval != 0){
        programming_rloc_probing(cache_entry);
    }
    return (TRUE);
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
 int process_map_request_msg(
         uint8_t        *packet,
         lisp_addr_t    *local_rloc,
         uint16_t       dst_port) {

     lispd_mapping_elt          *source_mapping          = NULL;
     lispd_map_cache_entry      *map_cache_entry        = NULL;
     lisp_addr_t                itr_rloc[32];
     lisp_addr_t                *remote_rloc            = NULL;
     int                        itr_rloc_count          = 0;
     int                        itr_rloc_afi            = 0;
     uint8_t                    *cur_ptr                = NULL;
     int                        len                     = 0;
     lispd_pkt_map_request_t    *msg                    = NULL;
     lisp_addr_t                aux_eid_prefix;
     int                        aux_eid_prefix_length   = 0;
     int                        aux_iid                 = -1;
     int                        i                       = 0;

     /* If the packet is an Encapsulated Map Request, verify checksum and remove the inner IP header */

     if (((lisp_encap_control_hdr_t *) packet)->type == LISP_ENCAP_CONTROL_TYPE) {
         if ((err = process_encapsulated_map_request_headers(packet,&len,&dst_port)) != GOOD){
             return (BAD);
         }
         msg = (lispd_pkt_map_request_t *) CO(packet, len);
     } else if (((lispd_pkt_map_request_t *) packet)->type == LISP_MAP_REQUEST) {
         msg = (lispd_pkt_map_request_t *) packet;
     } else
         return(BAD); //we should never reach this return()

     /*
      * Source EID is optional in general, but required for SMRs
      */

     /* Auxiliar lispd_mapping_elt created to be filled with pkt_process_eid_afi */
     source_mapping = new_local_mapping(aux_eid_prefix,aux_eid_prefix_length,aux_iid);
     if (source_mapping == NULL){
         return (BAD);
     }
     cur_ptr = (uint8_t *)&(msg->source_eid_afi);
     if (pkt_process_eid_afi(&cur_ptr, source_mapping) != GOOD){
         free_mapping_elt(source_mapping, FALSE);
         return (BAD);
     }
     /* If packet is a Solicit Map Request, process it */

     if (source_mapping->eid_prefix.afi != 0 && msg->solicit_map_request) {
         /*
          * Lookup the map cache entry that match with the source EID prefix of the message
          */
         map_cache_entry = lookup_map_cache(source_mapping->eid_prefix);
         if (map_cache_entry == NULL){
             free_mapping_elt(source_mapping, FALSE);
             return (BAD);
         }

         /*
          * Check IID of the received Solicit Map Request match the IID of the map cache
          */
         if (map_cache_entry->mapping->iid != source_mapping->iid){
             lispd_log_msg(LISP_LOG_DEBUG_2,"process_map_request_msg: The IID of the received Solicit Map Request doesn't match the IID of "
                     "the entry in the map cache");
             free_mapping_elt(source_mapping, FALSE);
             return (BAD);
         }
         /* Free source_mapping once we have a valid map cache entry */
         free_mapping_elt(source_mapping, FALSE);

         /*
          * Only accept a solicit map request for an EID prefix ->If node which generates the message
          * has more than one locator, it probably will generate a solicit map request for each one.
          * Only the first one is considered.
          * If map_cache_entry->nonces is different of null, we have already received a solicit map request
          */
         if (map_cache_entry->nonces == NULL){
             solicit_map_request_reply(NULL,(void *)map_cache_entry);
         }
         /* Return here only if RLOC probe bit is not set */
         if (!msg->rloc_probe){
             return(GOOD);
         }
     }

     /* Get the array of ITR-RLOCs */
     itr_rloc_count = msg->additional_itr_rloc_count + 1;
     for (i = 0; i < itr_rloc_count; i++) {
         itr_rloc_afi = lisp2inetafi(ntohs(*(uint16_t *)cur_ptr));
         cur_ptr = CO(cur_ptr, sizeof(uint16_t));
         memcpy(&(itr_rloc[i].address), cur_ptr, get_addr_len(itr_rloc_afi));
         itr_rloc[i].afi = itr_rloc_afi;
         cur_ptr = CO(cur_ptr, get_addr_len(itr_rloc_afi));
         // Select the first accessible rloc from the ITR-RLOC list
         if (remote_rloc == NULL){
             if (local_rloc != NULL && itr_rloc[i].afi ==  local_rloc->afi){
                 remote_rloc = &itr_rloc[i];
             }
         }
     }
     if (remote_rloc == NULL){
         lispd_log_msg(LISP_LOG_DEBUG_1,"process_map_request_msg: Couldn't generate map replay - "
                 "No supported afi in the list of ITR-RLOCS");
         return (BAD);
     }

     /* Process record and send Map Reply for each one */
     for (i = 0; i < msg->record_count; i++) {
         process_map_request_record(&cur_ptr, local_rloc, remote_rloc, dst_port, msg->rloc_probe, msg->nonce);
     }
     return(GOOD);
 }