uint32_t iot_context_manager_update(const iot_interface_t * p_interface, iot_context_t * p_context) { VERIFY_MODULE_IS_INITIALIZED(); NULL_PARAM_CHECK(p_context); VERIFY_CID_VALUE(p_context->context_id); VERIFY_PREFIX_LEN_VALUE(p_context->prefix_len); uint32_t retval = NRF_SUCCESS; uint32_t err_code = NRF_SUCCESS; iot_context_t * p_internal_context; CM_ENTRY(); CM_MUTEX_LOCK(); const uint32_t table_id = context_table_find(p_interface); if (table_id != IOT_CONTEXT_MANAGER_MAX_TABLES) { // Try to find context in context table. retval = context_find_by_cid(table_id, p_context->context_id, &p_internal_context); if (retval != NRF_SUCCESS) { err_code = context_find_free(table_id, &p_internal_context); // Increase context count. if (err_code == NRF_SUCCESS) { m_context_table[table_id].context_count++; } } if (err_code == NRF_SUCCESS) { // Update context table, with parameters from application. p_internal_context->context_id = p_context->context_id; p_internal_context->prefix_len = p_context->prefix_len; p_internal_context->compression_flag = p_context->compression_flag; memset(p_internal_context->prefix.u8, 0, IPV6_ADDR_SIZE); IPV6_ADDRESS_PREFIX_SET(p_internal_context->prefix.u8, p_context->prefix.u8, p_context->prefix_len); } else { CM_ERR("No place in context table."); } } else { // No free context table found. CM_ERR("No context table found."); err_code = (NRF_ERROR_NOT_FOUND | IOT_CONTEXT_MANAGER_ERR_BASE); } CM_MUTEX_UNLOCK(); CM_EXIT(); return err_code; }
/**@brief Function for parsing Router Advertisement message. * Because stack gives all control to application, internal RA parsing take care * only on Context Identifier. * * @param[in] p_interface Pointer to external interface from which packet come. * @param[in] p_ip_header Pointer to IPv6 Header. * @param[in] p_icmp_header Pointer to ICMPv6 header. * @param[in] p_packet Pointer to packet buffer. * * @return NRF_SUCCESS after successful processing, error otherwise. */ static uint32_t ra_input(iot_interface_t * p_interface, ipv6_header_t * p_ip_header, icmp6_header_t * p_icmp_header, iot_pbuffer_t * p_packet) { uint32_t err_code; iot_context_t context; iot_context_t * p_context; uint16_t curr_opt_offset = ND_RA_HEADER_SIZE; nd_option_t * p_opt = NULL; nd_option_6co_t * p_6co = NULL; nd_option_pio_t * p_pio = NULL; if(!IPV6_ADDRESS_IS_LINK_LOCAL(&p_ip_header->srcaddr)) { return ICMP6_INVALID_PACKET_DATA; } // Read all option we get. while(curr_opt_offset < p_packet->length) { p_opt = (nd_option_t *)(p_packet->p_payload + curr_opt_offset); if(p_opt->length == 0) { ICMP6_ERR("[ICMP6]: Option can't has 0 bytes!\r\n"); return ICMP6_INVALID_PACKET_DATA; } ICMP6_ERR("[ICMP6]: Option type = 0x%02x!\r\n", p_opt->type); // Searching for handling options. switch(p_opt->type) { case ND_OPT_TYPE_PIO: { p_pio = (nd_option_pio_t *)p_opt; if(p_pio->prefix_length != 0 && (p_pio->flags & ND_OPT_PIO_A_MASK) && !(p_pio->flags & ND_OPT_PIO_L_MASK)) { // Ignore Link-Local address if(IPV6_ADDRESS_IS_LINK_LOCAL(&p_pio->prefix)) { ICMP6_ERR("[ICMP6]: Ignore Link-Local prefix!\r\n"); break; } // For now address is automatically set as a preferred. ipv6_addr_conf_t temp_address; // Set IPv6 EUI-64 IPV6_CREATE_LINK_LOCAL_FROM_EUI64(&temp_address.addr, p_interface->local_addr.identifier); // Add prefix IPV6_ADDRESS_PREFIX_SET(temp_address.addr.u8, p_pio->prefix.u8, p_pio->prefix_length); if(p_pio->valid_lifetime != 0) { temp_address.state = IPV6_ADDR_STATE_PREFERRED; err_code = ipv6_address_set(p_interface, &temp_address); if(err_code != NRF_SUCCESS) { ICMP6_ERR("[ICMP6]: Cannot add new address! Address table is full!\r\n"); } } else { err_code = ipv6_address_remove(p_interface, &temp_address.addr); if(err_code != NRF_SUCCESS) { ICMP6_ERR("[ICMP6]: Cannot remove address!\r\n"); } } } else { ICMP6_ERR("[ICMP6]: Prefix option has incorrect parameters!\r\n"); return ICMP6_INVALID_PACKET_DATA; } break; } case ND_OPT_TYPE_6CO: { p_6co = (nd_option_6co_t *)p_opt; memset(context.prefix.u8, 0, IPV6_ADDR_SIZE); context.prefix = p_6co->context; context.prefix_len = p_6co->context_length; context.context_id = (p_6co->CID_C & ND_OPT_6CO_CID_MASK) >> ND_OPT_6CO_CID_POS; context.compression_flag = (p_6co->CID_C & ND_OPT_6CO_C_MASK) >> ND_OPT_6CO_C_POS; if(p_6co->valid_lifetime == 0) { err_code = iot_context_manager_get_by_cid(p_interface, context.context_id, &p_context); if(err_code == NRF_SUCCESS) { err_code = iot_context_manager_remove(p_interface, p_context); if(err_code == NRF_SUCCESS) { ICMP6_TRC("[ICMP6]: Removed context! CID = 0x%02x\r\n", context.context_id); } } } else { err_code = iot_context_manager_update(p_interface, &context); if(err_code == NRF_SUCCESS) { ICMP6_TRC("[ICMP6]: New context added! CID = 0x%02x\r\n", context.context_id); } } break; } } // Increment current offset option. curr_opt_offset += 8 * p_opt->length; } return NRF_SUCCESS; }