Пример #1
0
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;
}
Пример #2
0
/**@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;
}