/** * This function stores the LOCATOR parameter into the hadb entry * of a connection in question. The whole LOCATOR is stored and * handled later as the LOCATOR is received before the connection * state has reached ESTABLISHED (UPDATEs are not allowed before * the state is ESTABLISHED) and the address verification is * handled later during the BEX (after receiving the R2). * * @param packet_type The packet type of the control message (RFC 5201, 5.3.) * @param ha_state The host association state (RFC 5201, 4.4.1.) * @param ctx Pointer to the packet context, containing all information for * the packet handling (received message, source and destination * address, the ports and the corresponding entry from the host * association database). * * @return zero on success, or negative error value on error. */ int hip_handle_locator(UNUSED const uint8_t packet_type, UNUSED const uint32_t ha_state, struct hip_packet_context *ctx) { const struct hip_locator *locator = NULL; int n_addrs = 0, loc_size = 0, err = 0; locator = hip_get_param(ctx->input_msg, HIP_PARAM_LOCATOR); if (locator) { n_addrs = hip_get_locator_addr_item_count(locator); loc_size = sizeof(struct hip_locator) + (n_addrs * sizeof(struct hip_locator_info_addr_item)); /* this handle function is called during BEX, there should be no * locators yet. */ HIP_ASSERT(!ctx->hadb_entry->locator); HIP_IFEL(!(ctx->hadb_entry->locator = malloc(loc_size)), -1, "Malloc for entry->locators failed\n"); memcpy(ctx->hadb_entry->locator, locator, loc_size); } else { HIP_DEBUG("R1 did not have locator\n"); } out_err: return err; }
/** * Handle SEQ parameter in first and second update packet. * * @param packet_type The packet type of the control message (RFC 5201, 5.3.) * @param ha_state The host association state (RFC 5201, 4.4.1.) * @param ctx Pointer to the packet context, containing all information for * the packet handling (received message, source and destination * address, the ports and the corresponding entry from the host * association database). * * @return zero on success, or negative error value on error. */ int hip_handle_seq_param(UNUSED const uint8_t packet_type, UNUSED const uint32_t ha_state, struct hip_packet_context *ctx) { const struct hip_seq *seq = NULL; const enum update_types update_type = hip_classify_update_type(ctx->input_msg); struct update_state *localstate = NULL; int err = 0; if (update_type == FIRST_UPDATE_PACKET || update_type == SECOND_UPDATE_PACKET) { HIP_IFEL(!(seq = hip_get_param(ctx->input_msg, HIP_PARAM_SEQ)), -1, "SEQ parameter not found\n"); HIP_IFEL(!(localstate = lmod_get_state_item(ctx->hadb_entry->hip_modular_state, "update")), -1, "failed to look up update state\n"); // progress update sequence to currently processed update if (localstate->update_id_in < ntohl(seq->update_id)) { localstate->update_id_in = ntohl(seq->update_id); } HIP_IFEL(hip_build_param_ack(ctx->output_msg, ntohl(seq->update_id)), -1, "Building of ACK parameter failed\n"); } out_err: return err; }
/** * Handle ECHO_REQUEST_UNSIGNED parameter. * * @param packet_type The packet type of the control message (RFC 5201, 5.3.) * @param ha_state The host association state (RFC 5201, 4.4.1.) * @param ctx Pointer to the packet context, containing all information for * the packet handling (received message, source and destination * address, the ports and the corresponding entry from the host * association database). * * @return zero on success, or negative error value on error. */ int hip_handle_echo_request_param(UNUSED const uint8_t packet_type, UNUSED const uint32_t ha_state, struct hip_packet_context *ctx) { const struct hip_echo_request *echo_request = NULL; int err = 0; if (!(echo_request = hip_get_param(ctx->input_msg, HIP_PARAM_ECHO_REQUEST))) { HIP_DEBUG("no ECHO_REQUEST parameter in UPDATE packet, skipping\n"); /* This condition is no error! There simply was no request by the peer * to add a ECHO_RESPONSE parameter to the outbound message. */ return 0; } HIP_DEBUG("echo opaque data len=%d\n", hip_get_param_contents_len(echo_request)); HIP_HEXDUMP("ECHO_REQUEST ", (const uint8_t *) echo_request + sizeof(struct hip_tlv_common), hip_get_param_contents_len(echo_request)); HIP_IFEL(hip_build_param_echo(ctx->output_msg, (const uint8_t *) echo_request + sizeof(struct hip_tlv_common), hip_get_param_contents_len(echo_request), 0, 0), -1, "Building of ECHO_RESPONSE failed\n"); out_err: return err; }
/** * handle_locator_value - This function copies the 2nd address (ipv4) from * the locator from packet returned from lookup * * @param *packet response returned from the lookup service * @param *locator_ipv4 opaque pointer passed to point to the ipv4 address * @return status of the operation 0 on success, -1 on failure */ int handle_locator_value (unsigned char *packet, void *locator_ipv4) { struct hip_locator *locator; struct hip_locator_info_addr_item *locator_address_item = NULL; int locator_item_count = 0; struct in6_addr addr6; struct in_addr addr4; locator = hip_get_param((struct hip_common *)packet, HIP_PARAM_LOCATOR); if (locator) { locator_item_count = hip_get_locator_addr_item_count(locator); locator_item_count--; locator_address_item = hip_get_locator_first_addr_item(locator); memcpy(&addr6, (struct in6_addr*)&locator_address_item[locator_item_count].address, sizeof(struct in6_addr)); if (IN6_IS_ADDR_V4MAPPED(&addr6)) { IPV6_TO_IPV4_MAP(&addr6, &addr4); sprintf((char*)locator_ipv4, "%s", inet_ntoa(addr4)); } else { hip_in6_ntop(&addr6, (char*)locator_ipv4); _HIP_DEBUG("Value: %s\n", (char*)locator_ipv4); } return 0 ; } else return -1; }
/** * verify_hddr_lib - It sends the dht response to hipdaemon * first appending one more user param for holding a structure hdrr_info * hdrr_info is used by daemon to mark signature and host id verification results to flags * Then adding user header for recognizing the message at daemon side * * @param *hipcommonmsg packet returned from the lookup service * @param *addrkey key used for the lookup * @return OR of the signature and host id verification, 0 in case of success */ int verify_hddr_lib (struct hip_common *hipcommonmsg,struct in6_addr *addrkey) { struct hip_hdrr_info hdrr_info; struct hip_hdrr_info *hdrr_info_response; int err = 0 ; memcpy(&hdrr_info.dht_key, addrkey, sizeof(struct in6_addr)); hdrr_info.sig_verified = -1; hdrr_info.hit_verified = -1; hip_build_param_hip_hdrr_info(hipcommonmsg, &hdrr_info); _HIP_DUMP_MSG (hipcommonmsg); HIP_INFO("Asking signature verification info from daemon...\n"); HIP_IFEL(hip_build_user_hdr(hipcommonmsg, SO_HIP_VERIFY_DHT_HDRR_RESP,0),-1, "Building daemon header failed\n"); HIP_IFEL(hip_send_recv_daemon_info(hipcommonmsg, 0, 0), -1, "Send recv daemon info failed\n"); hdrr_info_response = hip_get_param (hipcommonmsg, HIP_PARAM_HDRR_INFO); _HIP_DUMP_MSG (hipcommonmsg); HIP_DEBUG ("Sig verified (0=true): %d\nHit Verified (0=true): %d \n" ,hdrr_info_response->sig_verified, hdrr_info_response->hit_verified); return (hdrr_info_response->sig_verified | hdrr_info_response->hit_verified); out_err: return err; }
/** * Change the state of hadb state cache in the firewall * * @param msg the message containing hadb cache information * * @return zero on success, non-zero on error */ static int hip_handle_bex_state_update(struct hip_common *msg) { const struct in6_addr *src_hit = NULL, *dst_hit = NULL; const struct hip_tlv_common *param = NULL; int err = 0, msg_type = 0; msg_type = hip_get_msg_type(msg); /* src_hit */ param = hip_get_param(msg, HIP_PARAM_HIT); src_hit = hip_get_param_contents_direct(param); HIP_DEBUG_HIT("Source HIT: ", src_hit); /* dst_hit */ param = hip_get_next_param(msg, param); dst_hit = hip_get_param_contents_direct(param); HIP_DEBUG_HIT("Destination HIT: ", dst_hit); /* update bex_state in firewalldb */ switch (msg_type) { case HIP_MSG_FW_BEX_DONE: err = hip_firewall_cache_set_bex_state(src_hit, dst_hit, HIP_STATE_ESTABLISHED); break; case HIP_MSG_FW_UPDATE_DB: err = hip_firewall_cache_set_bex_state(src_hit, dst_hit, HIP_STATE_NONE); break; default: break; } return err; }
/** * handle_locator_all_values - This function copies the locator from packet returned from lookup * @param *packet response returned from the lookup service * @param *locator_complete opaque pointer passed to point to the locator result * @return status of the operation 0 on success, -1 on failure */ int handle_locator_all_values (unsigned char *packet, void *locator_complete) { struct hip_locator *locator; locator = hip_get_param((struct hip_common *)packet, HIP_PARAM_LOCATOR); if (locator) { memcpy(locator_complete, locator, HIP_MAX_PACKET); return 0 ; } else return -1 ; }
/** * handle_hdrr_value - This function gets the HDRR from packet returned from lookup * @param *packet response returned from the lookup service * @param *hdrr opaque pointer passed to point to the hdrr result * @return status of the operation 0 on success, -1 on failure */ int handle_hdrr_value (unsigned char *packet, void *hdrr) { struct hip_locator *locator; locator = hip_get_param((struct hip_common *)packet, HIP_PARAM_LOCATOR); if (locator) { memcpy(hdrr, packet, HIP_MAX_PACKET); return 0 ; } else return -1 ; }
/** * Handle ESP_INFO parameter in first and second update packet. * * @param packet_type The packet type of the control message (RFC 5201, 5.3.) * @param ha_state The host association state (RFC 5201, 4.4.1.) * @param ctx Pointer to the packet context, containing all information for * the packet handling (received message, source and destination * address, the ports and the corresponding entry from the host * association database). * * @return zero on success, or negative error value on error. */ int hip_handle_esp_info_param(UNUSED const uint8_t packet_type, UNUSED const uint32_t ha_state, struct hip_packet_context *ctx) { const struct hip_esp_info *esp_info = NULL; const enum update_types update_type = hip_classify_update_type(ctx->input_msg); if (update_type == FIRST_UPDATE_PACKET || update_type == SECOND_UPDATE_PACKET) { if (!(esp_info = hip_get_param(ctx->input_msg, HIP_PARAM_ESP_INFO))) { HIP_ERROR("No ESP_INFO parameter found\n"); return -1; } // set the new spi value for the association // TODO add rekeying functionality here ctx->hadb_entry->spi_outbound_new = ntohl(esp_info->new_spi); } return 0; }
hip_lsi_t *hip_fw_get_default_lsi() { int err = 0; struct hip_common *msg = NULL; struct hip_tlv_common *param; /* Use cached LSI if possible */ if (local_lsi.s_addr != 0) { //memcpy(lsi, &local_lsi, sizeof(*lsi)); return &local_lsi; goto out_err; } /* Query hipd for the LSI */ HIP_IFE(!(msg = hip_msg_alloc()), -1); HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_DEFAULT_HIT, 0), -1, "build hdr failed\n"); /* send and receive msg to/from hipd */ HIP_IFEL(hip_send_recv_daemon_info(msg, 0, hip_fw_sock), -1, "send_recv msg failed\n"); HIP_DEBUG("send_recv msg succeed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n"); HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_LSI)), -1, "Did not find LSI\n"); memcpy(&local_lsi, hip_get_param_contents_direct(param), sizeof(local_lsi)); //memcpy(lsi, &local_lsi, sizeof(*lsi)); out_err: if(msg) HIP_FREE(msg); if (err) return NULL; else return &local_lsi; }
/** * display a LOCATOR parameter contents in a HIP control message * * @param in_msg the message where the LOCATOR parameter is located */ void hip_print_locator_addresses(const struct hip_common *in_msg) { const struct hip_locator *locator; const struct hip_locator_info_addr_item *ptr = NULL; const struct hip_locator_info_addr_item *item = NULL; const struct hip_locator_info_addr_item2 *item2 = NULL; const char *address_pointer; locator = hip_get_param(in_msg, HIP_PARAM_LOCATOR); if (locator) { address_pointer = (const char *) (locator + 1); for (; address_pointer < ((const char *) locator) + hip_get_param_contents_len(locator); ) { ptr = (const struct hip_locator_info_addr_item *) address_pointer; if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_UDP) { item2 = (const struct hip_locator_info_addr_item2 *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item2->address); HIP_DEBUG("Locator address offset is %d\n", address_pointer - (const char *) (locator + 1)); address_pointer += sizeof(struct hip_locator_info_addr_item2); } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_ESP_SPI) { item = (const struct hip_locator_info_addr_item *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item->address); address_pointer += sizeof(struct hip_locator_info_addr_item); } else if (ptr->locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) { item = (const struct hip_locator_info_addr_item *) address_pointer; HIP_DEBUG_HIT("LOCATOR", &item->address); address_pointer += sizeof(struct hip_locator_info_addr_item); } else { address_pointer += sizeof(struct hip_locator_info_addr_item); } } } }
/** handles the TPA specific parts in the setup of new IPsec SAs * * @param msg the HIP message * @param esp_prot_transform the TPA transform (return value) * @param num_anchors number of anchor in the array * @param esp_prot_anchors array storing the anchors * @param hash_item_length length of the employed hash structure at the peer (return value) * @return 0 on success, -1 on error */ int esp_prot_handle_sa_add_request(const struct hip_common *msg, uint8_t *esp_prot_transform, uint16_t *num_anchors, unsigned char (*esp_prot_anchors)[MAX_HASH_LENGTH], uint32_t *hash_item_length) { const struct hip_tlv_common *param = NULL; int hash_length = 0, err = 0; const unsigned char *anchor = NULL; uint16_t i; *num_anchors = 0; *esp_prot_transform = 0; HIP_ASSERT(msg != NULL); HIP_ASSERT(esp_prot_transform != NULL); HIP_ASSERT(num_anchors != NULL); HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_ESP_PROT_TFM)), -1, "esp prot transform missing\n"); *esp_prot_transform = *((const uint8_t *) hip_get_param_contents_direct(param)); HIP_DEBUG("esp protection transform is %u\n", *esp_prot_transform); // this parameter is only included, if the esp extension is used if (*esp_prot_transform > ESP_PROT_TFM_UNUSED) { // retrieve hash length for the received transform HIP_IFEL((hash_length = esp_prot_get_hash_length(*esp_prot_transform)) <= 0, -1, "error or tried to resolve UNUSED transform\n"); HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_ITEM_LENGTH)), -1, "transform suggests hash_item_length, but it is NOT included in msg\n"); *hash_item_length = *((const uint32_t *) hip_get_param_contents_direct(param)); HIP_DEBUG("esp protection item length: %u\n", *hash_item_length); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "transform suggests num_anchors, but it is NOT included in msg\n"); *num_anchors = *((const uint16_t *) hip_get_param_contents_direct(param)); HIP_DEBUG("esp protection number of transferred anchors: %u\n", *num_anchors); HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_HCHAIN_ANCHOR)), -1, "transform suggests anchor, but it is NOT included in msg\n"); if (*num_anchors <= num_parallel_hchains) { for (i = 0; i < *num_anchors; i++) { anchor = hip_get_param_contents_direct(param); // store the current anchor memcpy(&esp_prot_anchors[i][0], anchor, hash_length); HIP_HEXDUMP("esp protection anchor is ", &esp_prot_anchors[i][0], hash_length); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "awaiting further anchor, but it is NOT included in msg\n"); } } } out_err: if (err) { *esp_prot_transform = 0; *num_anchors = 0; } return err; }
/** handles a user-message sent by the firewall when the bex-store is updated * * @param msg the user-message sent by fw * @return 0 if ok, != 0 else */ int anchor_db_update(const struct hip_common *msg) { const struct hip_tlv_common *param = NULL; const unsigned char *anchor = NULL; int err = 0, i, j; uint8_t esp_transforms[MAX_NUM_TRANSFORMS]; HIP_ASSERT(msg != NULL); // if this function is called, the extension should be active if (esp_prot_active) { memset(esp_transforms, 0, MAX_NUM_TRANSFORMS * sizeof(uint8_t)); HIP_DEBUG("updating hchain anchorDB...\n"); /* XX TODO ineffcient -> only add non-existing elements instead of * uniniting and adding all elements again */ anchor_db_uninit(); /*** set up anchor_db.num_anchors and anchor_db.anchor_lengths ***/ // get first int value HIP_IFEL(!(param = hip_get_param(msg, HIP_PARAM_UINT)), -1, "parameter missing in user-message from fw\n"); // don't set up anything for UNUSED transform for (i = 0; i < esp_prot_num_transforms - 1; i++) { // needed for redirection to correct slot in anchor_db esp_transforms[i] = *(const uint8_t *) hip_get_param_contents_direct(param); HIP_DEBUG("esp_transform is %u\n", esp_transforms[i]); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "parameter missing in user-message from fw\n"); anchor_db.num_anchors[esp_transforms[i]] = *(const int *) hip_get_param_contents_direct(param); HIP_DEBUG("num_anchors is %i\n", anchor_db.num_anchors[esp_transforms[i]]); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "parameter missing in user-message from fw\n"); anchor_db.anchor_lengths[esp_transforms[i]] = *(const int *) hip_get_param_contents_direct(param); HIP_DEBUG("anchor_length is %i\n", anchor_db.anchor_lengths[esp_transforms[i]]); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "parameter missing in user-message from fw\n"); } for (i = 0; i < esp_prot_num_transforms - 1; i++) { HIP_DEBUG("transform %u:\n", esp_transforms[i]); for (j = 0; j < anchor_db.num_anchors[esp_transforms[i]]; j++) { HIP_IFEL(!(anchor_db.anchors[esp_transforms[i]][j] = malloc(anchor_db.anchor_lengths[esp_transforms[i]])), -1, "failed to allocate memory\n"); anchor = hip_get_param_contents_direct(param); memcpy(anchor_db.anchors[esp_transforms[i]][j], anchor, anchor_db.anchor_lengths[esp_transforms[i]]); HIP_HEXDUMP("adding anchor: ", anchor_db.anchors[esp_transforms[i]][j], anchor_db.anchor_lengths[esp_transforms[i]]); HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "parameter missing in user-message from fw\n"); anchor_db.hash_item_length[esp_transforms[i]] = *(const int *) hip_get_param_contents_direct(param); HIP_DEBUG("adding hash_item_length: %i\n", anchor_db.hash_item_length[esp_transforms[i]]); // exclude getting the next param for the very last loop if (!(i == esp_prot_num_transforms - 2 && j == anchor_db.num_anchors[esp_transforms[i]] - 1)) { HIP_IFEL(!(param = hip_get_next_param(msg, param)), -1, "parameter missing in user-message from fw\n"); } } } HIP_DEBUG("anchor_db successfully updated\n"); } else { HIP_ERROR("received anchor_db update, but esp protection extension disabled\n"); err = -1; goto out_err; } out_err: return err; }