void *pkt_fill_eid( void *offset, lispd_mapping_elt *mapping) { uint16_t *afi_ptr; lispd_pkt_lcaf_t *lcaf_ptr; lispd_pkt_lcaf_iid_t *iid_ptr; void *eid_ptr; int eid_addr_len; afi_ptr = (uint16_t *)offset; eid_addr_len = get_addr_len(mapping->eid_prefix.afi); /* For negative IID values, we skip LCAF/IID field */ if (mapping->iid < 0) { *afi_ptr = htons(get_lisp_afi(mapping->eid_prefix.afi, NULL)); eid_ptr = CO(offset, sizeof(uint16_t)); } else { *afi_ptr = htons(LISP_AFI_LCAF); lcaf_ptr = (lispd_pkt_lcaf_t *) CO(offset, sizeof(uint16_t)); iid_ptr = (lispd_pkt_lcaf_iid_t *) CO(lcaf_ptr, sizeof(lispd_pkt_lcaf_t)); eid_ptr = (void *) CO(iid_ptr, sizeof(lispd_pkt_lcaf_iid_t)); lcaf_ptr->rsvd1 = 0; lcaf_ptr->flags = 0; lcaf_ptr->type = 2; lcaf_ptr->rsvd2 = 0; /* This can be IID mask-len, not yet supported */ lcaf_ptr->len = htons(sizeof(lispd_pkt_lcaf_iid_t) + eid_addr_len); iid_ptr->iid = htonl(mapping->iid); iid_ptr->afi = htons(mapping->eid_prefix.afi); } if ((copy_addr(eid_ptr,&(mapping->eid_prefix), 0)) == 0) { LISPD_LOG(LISP_LOG_DEBUG_3, "copy_addr failed"); return NULL; } return CO(eid_ptr, eid_addr_len); }
int get_prefix_len(int afi) { return(get_addr_len(afi) * 8); }
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); }
int extract_nat_lcaf_data(uint8_t *offset, uint16_t *ms_udp_port, uint16_t *etr_udp_port, lisp_addr_t *global_etr_rloc, lisp_addr_t *ms_rloc, lisp_addr_t *private_etr_rloc, rtr_locators_list_t **rtr_list, uint32_t *length) { lcaf_hdr_t *pkt_lcaf; lispd_pkt_nat_lcaf_t *pkt_nat_lcaf; rtr_locators_list_t *rtr_locator_list = NULL; rtr_locator_t *rtr_locator; lisp_addr_t rtr_address = {.afi=LM_AFI_NO_ADDR}; uint8_t *ptr = offset; uint32_t lcaf_length; uint32_t cumulative_add_length; pkt_lcaf = (lcaf_hdr_t *)ptr; if (pkt_lcaf->type != LCAF_NATT){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Packet doesn't have NAT LCAF address"); return (BAD); } lcaf_length = ntohs(pkt_lcaf->len); ptr = CO(ptr,sizeof(lcaf_hdr_t)); pkt_nat_lcaf = (lispd_pkt_nat_lcaf_t *)ptr; *ms_udp_port = ntohs(pkt_nat_lcaf->ms_udp_port); *etr_udp_port = ntohs(pkt_nat_lcaf->etr_udp_port); cumulative_add_length = FIELD_PORT_LEN * 2; /* 2 UDP ports */ ptr = CO(ptr,sizeof(lispd_pkt_nat_lcaf_t)); /* Extract the Global ETR RLOC */ if ((extract_lisp_address(ptr, global_etr_rloc)) != GOOD){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Couldn't process Global ETR RLOC"); return (BAD); } cumulative_add_length += get_addr_len(global_etr_rloc->afi) + FIELD_AFI_LEN; ptr = CO(ptr, get_addr_len(global_etr_rloc->afi) + FIELD_AFI_LEN); /* Extract the MS RLOC */ if ((extract_lisp_address(ptr, ms_rloc)) != GOOD){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Couldn't process MS RLOC"); return (BAD); } cumulative_add_length += get_addr_len(ms_rloc->afi) + FIELD_AFI_LEN; ptr = CO(ptr, get_addr_len(ms_rloc->afi) + FIELD_AFI_LEN); /* Extract the Private ETR RLOC */ if (extract_lisp_address(ptr, private_etr_rloc) != GOOD){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Couldn't process private ETR RLOC"); return (BAD); } cumulative_add_length += get_addr_len(private_etr_rloc->afi) + FIELD_AFI_LEN; ptr = CO(ptr, get_addr_len(private_etr_rloc->afi) + FIELD_AFI_LEN); /* Extract the list of RTR RLOCs */ while (cumulative_add_length < lcaf_length) { if ((extract_lisp_address(ptr, &rtr_address))!= GOOD){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Coudln't process rtr address"); return (BAD); } rtr_locator = rtr_locator_new (rtr_address); if (rtr_locator == NULL){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Error malloc lispd_rtr_locator"); return (BAD); } if ((rtr_list_add(&rtr_locator_list,rtr_locator))!=GOOD){ LMLOG(LDBG_2, "extract_nat_lcaf_data: Error adding rtr_locator"); return (BAD); } // Return the first element of the list if (*rtr_list == NULL){ *rtr_list = rtr_locator_list; } LMLOG(LDBG_3, "Added RTR with RLOC %s to the list of RTRs", get_char_from_lisp_addr_t(rtr_locator->address)); cumulative_add_length += get_addr_len(rtr_locator->address.afi) + FIELD_AFI_LEN; ptr = CO(ptr, get_addr_len(rtr_locator->address.afi) + FIELD_AFI_LEN); } *length = sizeof(lcaf_hdr_t) + lcaf_length; return (GOOD); }