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
/*
 * send_map_reply()
 *
 * Send a map-reply to a querier.
 */
void send_map_reply(lispd_pkt_map_request_t *pkt,
                    struct sockaddr_in *source)
{
    lispd_pkt_map_request_eid_prefix_record_t *rec;
    lispd_pkt_map_request_itr_rloc_t *itr_rloc;
    lispd_locator_chain_t *loc_chain;
    lispd_pkt_map_reply_t *reply_pkt;
    struct ip *iphdr;
    struct udphdr *udphdr;
    lisp_addr_t eid_prefix;
    struct sockaddr_in dst;
    lispd_if_t *oif = get_primary_interface();
    char addr_buf[128];
    char *ptr;
    int offset, i, s, len, nbytes, udp_len;

    if (!oif) {
        log_msg(INFO, "No interfaces are available to source reply");
        return;
    }

    /*
     * Figure out what they are asking for, need to advance past
     * all the ITR-RLOCs in the packet. Sigh.
     */
    offset = sizeof(lispd_pkt_map_request_t);

    if (pkt->source_eid_afi != 0) {
        if (lisp2inetafi(ntohs(pkt->source_eid_afi)) == AF_INET) {
            offset += sizeof(struct in_addr);
        } else {
            offset += sizeof(struct in6_addr);
        }
    }

    itr_rloc = (lispd_pkt_map_request_itr_rloc_t *)CO(pkt, offset);
    for (i = 0; i < pkt->additional_itr_rloc_count + 1; i++) {
        offset += sizeof(lispd_pkt_map_request_itr_rloc_t);
        if (lisp2inetafi(ntohs(itr_rloc->afi)) == AF_INET) {
            offset += sizeof(struct in_addr);
        } else {
            offset += sizeof(struct in6_addr);
        }
        itr_rloc = (lispd_pkt_map_request_itr_rloc_t *)CO(pkt, offset);
    }

    rec = (lispd_pkt_map_request_eid_prefix_record_t *)CO(pkt, offset);
    ptr = CO(rec, sizeof(lispd_pkt_map_request_eid_prefix_record_t));
    memcpy(&eid_prefix.address.ip, ptr, sizeof(struct in_addr));

    if (lisp2inetafi(ntohs(rec->eid_prefix_afi)) != AF_INET) {
        log_msg(INFO, "     AF: %d unsupported currently.",
               lisp2inetafi(ntohs(rec->eid_prefix_afi)));
        return;
    }

    log_msg(INFO, " Request for EID: %s/%d", inet_ntop(AF_INET, &eid_prefix.address.ip.s_addr,
                                                          addr_buf, 128),
           rec->eid_prefix_mask_length);

    /*
     * Lookup in our local database
     */
    if (!lookup_eid_in_db(lisp2inetafi(ntohs(rec->eid_prefix_afi)),
                          eid_prefix.address.ip.s_addr, &loc_chain)) {
        log_msg(INFO, "   Unable to find entry in local database.");
        return;
    } else {
        log_msg(INFO, "   Found entry, building reply.");
    }

    reply_pkt = build_map_reply(source->sin_addr.s_addr, pkt->rloc_probe,
                                loc_chain, (char *)&pkt->nonce, &len);

    if (!reply_pkt) {
        log_msg(INFO,
               "Failed to build map reply");
        return;
    }

    /*
     * Build the outer IP header ourselves, this doesn't
     * go using LISP, so we don't want the EID used as the source.
     */
    iphdr = (struct ip *)malloc(len + sizeof(struct ip) + sizeof(struct udphdr));
    udphdr = (struct udphdr *)CO(iphdr, sizeof(struct ip));
    ptr = CO(udphdr, sizeof(struct udphdr));
    memcpy(ptr, (char *)reply_pkt, len);
    free(reply_pkt);

    udp_len = len + sizeof(struct udphdr);

    /*
     * AF_INET for now XXX
     */
    iphdr->ip_hl = 5;
    iphdr->ip_v = IPVERSION;
    iphdr->ip_tos        = 0;
    iphdr->ip_len        = htons(udp_len + sizeof(struct ip));
    iphdr->ip_id         = htons(54321);
    iphdr->ip_off        = 0;
    iphdr->ip_ttl        = 255;
    iphdr->ip_p          = IPPROTO_UDP;
    iphdr->ip_sum        = 0; // Raw socket handler does this for us.

    iphdr->ip_src.s_addr = oif->address.address.ip.s_addr; /// XXX Huh?
    iphdr->ip_dst.s_addr = source->sin_addr.s_addr;

    udphdr->source = htons(LISP_CONTROL_PORT);
    udphdr->dest = source->sin_port;
    udphdr->len = htons(udp_len);
    udphdr->check = 0;
    udphdr->check = udp_checksum(udphdr, udp_len, iphdr, AF_INET);

    /* XXX: assumes v4 transport */
    if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
        log_msg(INFO, "socket (send_map_request): %s", strerror(errno));
        return;
    }

    memset((char *) &dst, 0, sizeof(dst));

    dst.sin_family      = AF_INET;	/* XXX: assume v4 transport */
    dst.sin_addr.s_addr = source->sin_addr.s_addr;

    if ((nbytes = sendto(s,
                         (const void *)iphdr,
                         len + sizeof(struct ip) + sizeof(struct udphdr),
                         0,
                         (struct sockaddr *)&dst,
                         sizeof(struct sockaddr))) < 0) {
        log_msg(INFO, "sendto (send_map_request): %s", strerror(errno));
        return;
    }

    if (nbytes != (int)(len + sizeof(struct udphdr) + sizeof(struct ip))) {
        log_msg(INFO,
               "send_map_request: nbytes (%d) != packet_len (%d)\n",
               nbytes, len);
        return;
    }

    close(s);
    free(iphdr);
    return;
}
Ejemplo n.º 3
0
uint8_t *build_map_request_pkt(
        lispd_mapping_elt       *requested_mapping,
        lisp_addr_t             *src_eid,
        uint8_t                 encap,
        uint8_t                 probe,
        uint8_t                 solicit_map_request,/* boolean really */
        uint8_t                 smr_invoked,
        int                     *len,               /* return length here */
        uint64_t                *nonce)             /* return nonce here */
{

    uint8_t                                     *packet                 = NULL;
    uint8_t                                     *mr_packet              = NULL;
    lispd_pkt_map_request_t                     *mrp                    = NULL;
    lispd_pkt_mapping_record_t                  *rec                    = NULL;
    lispd_pkt_map_request_itr_rloc_t            *itr_rloc               = NULL;
    lispd_pkt_map_request_eid_prefix_record_t   *request_eid_record     = NULL;
    uint8_t                                     *cur_ptr                = NULL;

    int                     map_request_msg_len = 0;
    int                     ctr                 = 0;
    int                     cpy_len             = 0;
    int                     locators_ctr        = 0;

    lispd_mapping_elt       *src_mapping        = NULL;
    lispd_locators_list     *locators_list[2]   = {NULL,NULL};
    lispd_locator_elt       *locator            = NULL;
    lisp_addr_t             *ih_src_ip          = NULL;

    /*
     * Lookup the local EID prefix from where we generate the message.
     * src_eid is null for RLOC probing and refreshing map_cache -> Source-EID AFI = 0
     */
    if (src_eid != NULL){
        src_mapping = lookup_eid_in_db(*src_eid);
        if (!src_mapping){
            lispd_log_msg(LISP_LOG_DEBUG_2,"build_map_request_pkt: Source EID address not found in local data base - %s -",
                    get_char_from_lisp_addr_t(*src_eid));
            return (NULL);
        }

    }

    /* Calculate the packet size and reserve memory */
    map_request_msg_len = get_map_request_length(requested_mapping,src_mapping);
    *len = map_request_msg_len;

    if ((packet = malloc(map_request_msg_len)) == NULL){
        lispd_log_msg(LISP_LOG_WARNING,"build_map_request_pkt: Unable to allocate memory for Map Request (packet_len): %s", strerror(errno));
        return (NULL);
    }
    memset(packet, 0, map_request_msg_len);


    cur_ptr = packet;

    mrp = (lispd_pkt_map_request_t *)cur_ptr;

    mrp->type                      = LISP_MAP_REQUEST;
    mrp->authoritative             = 0;
    if (src_eid != NULL)
        mrp->map_data_present      = 1;
    else
        mrp->map_data_present      = 0;

    if (probe)
        mrp->rloc_probe            = 1;
    else
        mrp->rloc_probe            = 0;

    if (solicit_map_request)
        mrp->solicit_map_request   = 1;
    else
        mrp->solicit_map_request   = 0;

    if (smr_invoked)
        mrp->smr_invoked           = 1;
    else
        mrp->smr_invoked           = 0;

    mrp->additional_itr_rloc_count = 0;     /* To be filled later  */
    mrp->record_count              = 1;     /* XXX: assume 1 record */
    mrp->nonce = build_nonce((unsigned int) time(NULL));
    *nonce                         = mrp->nonce;

    if (src_eid != NULL){
        cur_ptr = pkt_fill_eid(&(mrp->source_eid_afi),src_mapping);

        /* Add itr-rlocs */
        locators_list[0] = src_mapping->head_v4_locators_list;
        locators_list[1] = src_mapping->head_v6_locators_list;

        for (ctr=0 ; ctr < 2 ; ctr++){
            while (locators_list[ctr]){
                locator = locators_list[ctr]->locator;
                if (*(locator->state)==DOWN){
                    locators_list[ctr] = locators_list[ctr]->next;
                    continue;
                }
                /* Remove ITR locators behind NAT: No control message (4342) can be received in these interfaces */
                if (((lcl_locator_extended_info *)locator->extended_info)->rtr_locators_list != NULL){
                    locators_list[ctr] = locators_list[ctr]->next;
                    continue;
                }

                itr_rloc = (lispd_pkt_map_request_itr_rloc_t *)cur_ptr;
                itr_rloc->afi = htons(get_lisp_afi(locator->locator_addr->afi,NULL));
                /* Add rloc address */
                cur_ptr = CO(itr_rloc,sizeof(lispd_pkt_map_request_itr_rloc_t));
                cpy_len = copy_addr((void *) cur_ptr ,locator->locator_addr, 0);
                cur_ptr = CO(cur_ptr, cpy_len);
                locators_ctr ++;
                locators_list[ctr] = locators_list[ctr]->next;
            }
        }
    }else {
        // XXX If no source EID is used, then we only use one ITR-RLOC for IPv4 and one for IPv6-> Default control RLOC
        mrp->source_eid_afi = 0;
        cur_ptr = CO(mrp, sizeof(lispd_pkt_map_request_t));
        if (default_ctrl_iface_v4 != NULL){
            itr_rloc = (lispd_pkt_map_request_itr_rloc_t *)cur_ptr;
            itr_rloc->afi = htons((uint16_t)LISP_AFI_IP);
            cur_ptr = CO(itr_rloc,sizeof(lispd_pkt_map_request_itr_rloc_t));
            cpy_len = copy_addr((void *) cur_ptr ,default_ctrl_iface_v4->ipv4_address, 0);
            cur_ptr = CO(cur_ptr, cpy_len);
            locators_ctr ++;
        }
        if (default_ctrl_iface_v6 != NULL){
            itr_rloc = (lispd_pkt_map_request_itr_rloc_t *)cur_ptr;
            itr_rloc->afi = htons(get_lisp_afi(AF_INET6,NULL));
            cur_ptr = CO(itr_rloc,sizeof(lispd_pkt_map_request_itr_rloc_t));
            cpy_len = copy_addr((void *) cur_ptr ,default_ctrl_iface_v6->ipv6_address, 0);
            cur_ptr = CO(cur_ptr, cpy_len);
            locators_ctr ++;
        }
    }
    mrp->additional_itr_rloc_count = locators_ctr - 1; /* IRC = 0 --> 1 ITR-RLOC */
    if (locators_ctr == 0){
        lispd_log_msg(LISP_LOG_DEBUG_2,"build_map_request_pkt: No ITR RLOCs.");
        free(packet);
        return (NULL);
    }


    /* Requested EID record */
    request_eid_record = (lispd_pkt_map_request_eid_prefix_record_t *)cur_ptr;
    request_eid_record->eid_prefix_length = requested_mapping->eid_prefix_length;

    cur_ptr = pkt_fill_eid(&(request_eid_record->eid_prefix_afi),requested_mapping);

    if (mrp->map_data_present == 1){
        /* Map-Reply Record */
        rec = (lispd_pkt_mapping_record_t *)cur_ptr;
        if ((pkt_fill_mapping_record(rec, src_mapping, NULL))== NULL) {
            lispd_log_msg(LISP_LOG_DEBUG_2,"build_map_request_pkt: Couldn't buil map reply record for map request. "
                    "Map Request will not be send");
            free(packet);
            return(NULL);
        }
    }

    /* Add Encapsulated (Inner) control header*/
    if (encap){

        /*
         * If no source EID is included (Source-EID-AFI = 0), The default RLOC address is used for
         * the source address in the inner IP header
         */
        if (src_eid != NULL){
            ih_src_ip = &(src_mapping->eid_prefix);;
        }else{
            if (requested_mapping->eid_prefix.afi == AF_INET){
                ih_src_ip = get_main_eid (AF_INET);
            }else{
                ih_src_ip = get_main_eid (AF_INET6);
            }
        }

        mr_packet = packet;
        packet = build_control_encap_pkt(mr_packet, map_request_msg_len, ih_src_ip, &(requested_mapping->eid_prefix), LISP_CONTROL_PORT, LISP_CONTROL_PORT, len);

        if (packet == NULL){
            lispd_log_msg(LISP_LOG_DEBUG_1,"build_map_request_pkt: Couldn't encapsulate the map request");
            free (mr_packet);
            return (NULL);
        }
    }

    return (packet);
}