Example #1
0
static void thread_nd_coap_notification_callback(int8_t interface_id, const uint8_t ip_addr[16], uint16_t loc_addr, const uint8_t ml_eid[8])
{
    protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
    if (!cur) {
        return;
    }

    /* First check to see if we have an existing entry with different RLOC - we need to unicast error
     * notification to that old entry if so. */
    ipv6_neighbour_t *entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, ip_addr);
    if (entry && entry->ll_type == ADDR_802_15_4_SHORT) {
        uint16_t old_entry_rloc = common_read_16_bit(entry->ll_address + 2);
        if (old_entry_rloc != loc_addr) {
            uint8_t old_entry_ip[16];
            thread_addr_write_mesh_local_16(old_entry_ip, common_read_16_bit(entry->ll_address + 2), cur->thread_info);
            tr_warn("Proactive address change %s %04x->%04x", trace_ipv6(ip_addr), old_entry_rloc, loc_addr);
            thread_resolution_client_address_error(interface_id, old_entry_ip, ip_addr, ml_eid);
        }
    }

    /* Now treat as an unsolicited update (by address, because entry may be NULL) */
    uint8_t ll_addr[4];
    common_write_16_bit(cur->mac_parameters->pan_id, ll_addr + 0);
    common_write_16_bit(loc_addr, ll_addr + 2);
    ipv6_neighbour_update_unsolicited(&cur->ipv6_neighbour_cache, ip_addr, ADDR_802_15_4_SHORT, ll_addr);

    if (nd_proxy_enabled_for_upstream(cur->id)) {
        ipv6_route_add(ip_addr, 128, cur->id, NULL, ROUTE_THREAD_PROXIED_HOST, 3600, 0);
    }
}
Example #2
0
uint8_t *eapol_write_pdu_frame(uint8_t *ptr, eapol_pdu_t *eapol_pdu)
{
    *ptr++ = EAPOL_PROTOCOL_VERSION;
    *ptr++ = eapol_pdu->packet_type;
    ptr = common_write_16_bit(eapol_pdu->packet_length, ptr);
    eapol_pdu->packet_body = ptr;

    if (eapol_pdu->packet_type == EAPOL_EAP_TYPE) {
        eap_header_t *eap_header = &eapol_pdu->msg.eap;
        ptr = eap_header_build(ptr, eap_header->length, eap_header->eap_code, eap_header->id_seq, eap_header->type);
        memcpy(ptr, eap_header->data_ptr, eap_header->length - (ptr - eapol_pdu->packet_body));
        ptr += eap_header->length - (ptr - eapol_pdu->packet_body);

    } else if (eapol_pdu->packet_type == EAPOL_KEY_TYPE) {
        eapol_key_frame_t *key_frame = &eapol_pdu->msg.key;
        *ptr++ = key_frame->key_description;
        ptr = eapol_key_information_write(&key_frame->key_information, ptr);
        ptr = common_write_16_bit(key_frame->key_length, ptr);
        ptr = common_write_64_bit(key_frame->replay_counter, ptr);

        if (key_frame->key_nonce) {
            memcpy(ptr, key_frame->key_nonce, 32);
        } else {
            memset(ptr, 0, 32);
        }
        ptr += 32;

        if (key_frame->key_iv) {
            memcpy(ptr, key_frame->key_iv, 16);
        } else {
            memset(ptr, 0, 16);
        }
        ptr += 16;

        if (key_frame->key_rsc) {
            memcpy(ptr, key_frame->key_rsc, 8);
        } else {
            memset(ptr, 0, 8);
        }
        ptr += 8;

        //Reserved 8bytes
        memset(ptr, 0, 8);
        ptr += 8;

        if (key_frame->key_mic && key_frame->key_information.key_mic) {
            memcpy(ptr, key_frame->key_mic, 16);
        } else {
            memset(ptr, 0, 16);
        }
        ptr += 16;
        ptr = common_write_16_bit(key_frame->key_data_length, ptr);
        if (key_frame->key_data_length && key_frame->key_data) {
            memcpy(ptr, key_frame->key_data, key_frame->key_data_length);
            ptr += key_frame->key_data_length;
        }
    }

    return ptr;
}
Example #3
0
buffer_t *udp_down(buffer_t *buf)
{
    if (buf->src_sa.addr_type != ADDR_IPV6) {
        //tr_debug("Create Address");
//      if(protocol_stack_interface_get_address_by_prefix(buf->if_index, buf->src_sa.address,buf->dst_sa.address, 0) != 0)
//      {
        tr_debug("InterFace Address Get Fail--> free Buffer");
        return buffer_free(buf);
//      }
//      else
//      {
//          buf->src_sa.addr_type = ADDR_IPV6;
//      }
    }

    buf = buffer_headroom(buf, 8);
    if (buf) {
        uint8_t *ptr;
        buf->buf_ptr -= 8;

        ptr = buffer_data_pointer(buf);
        ptr = common_write_16_bit(buf->src_sa.port, ptr);
        ptr = common_write_16_bit(buf->dst_sa.port, ptr);
        ptr = common_write_16_bit(buffer_data_length(buf), ptr);
        udp_checksum_write(buf);
        buf->IPHC_NH = 0;
        buf->info = (buffer_info_t)(B_FROM_UDP | B_TO_IPV6 | B_DIR_DOWN);
        buf->options.type = IPV6_NH_UDP;
        buf->options.code = 0;
    }
    return (buf);
}
Example #4
0
void nd_tasklet_trace_bootstrap_info()
{
    network_layer_address_s app_nd_address_info;
    link_layer_address_s app_link_address_info;
    uint8_t temp_ipv6[16];
    if (arm_nwk_nd_address_read(tasklet_data_ptr->network_interface_id,
                                &app_nd_address_info) != 0) {
        tr_error("ND Address read fail");
    } else {
        tr_debug("ND Access Point: %s", trace_ipv6(app_nd_address_info.border_router));
        tr_debug("ND Prefix 64: %s", trace_array(app_nd_address_info.prefix, 8));

        if (arm_net_address_get(tasklet_data_ptr->network_interface_id,
                                ADDR_IPV6_GP, temp_ipv6) == 0) {
            tr_debug("GP IPv6: %s", trace_ipv6(temp_ipv6));
        }
    }

    if (arm_nwk_mac_address_read(tasklet_data_ptr->network_interface_id,
                                 &app_link_address_info) != 0) {
        tr_error("MAC Address read fail\n");
    } else {
        uint8_t temp[2];
        common_write_16_bit(app_link_address_info.mac_short,temp);
        tr_debug("MAC 16-bit: %s", trace_array(temp, 2));
        common_write_16_bit(app_link_address_info.PANId, temp);
        tr_debug("PAN ID: %s", trace_array(temp, 2));
        tr_debug("MAC 64-bit: %s", trace_array(app_link_address_info.mac_long, 8));
        tr_debug("IID (Based on MAC 64-bit address): %s", trace_array(app_link_address_info.iid_eui64, 8));
    }

    tr_debug("Channel: %d", arm_net_get_current_channel(tasklet_data_ptr->network_interface_id));
}
Example #5
0
uint8_t *pana_header_write(uint8_t *ptr, const pana_header_t *header)
{
    ptr = common_write_16_bit(PANA_HEADER_START, ptr);
    ptr = common_write_16_bit(header->payload_len, ptr);
    ptr = common_write_16_bit(header->flags, ptr);
    ptr = common_write_16_bit(header->type, ptr);
    ptr = common_write_32_bit(header->session_id, ptr);
    return common_write_32_bit(header->seq, ptr);
}
Example #6
0
static void tls_set_adata(ccm_globals_t *ccm_ptr, uint8_t *a_data, const uint8_t *nonce, uint8_t type)
{
    ccm_ptr->adata_len = 13;
    ccm_ptr->adata_ptr = a_data;
    memcpy(a_data, nonce, 8);
    a_data += 8;
    *a_data++ = type;
    a_data = common_write_16_bit(TLS_1_2_VER, a_data);
    common_write_16_bit(ccm_ptr->data_len, a_data);
}
Example #7
0
buffer_t *pana_relay_avp_build(buffer_t *buf, sec_suite_t *suite)
{
    uint8_t *ptr, *adr_ptr;
    uint16_t relay_len, padding;
    relay_len = buffer_data_length(buf);
    padding = relay_len;
    buf->socket = socket_dereference(buf->socket);
    buf->session_ptr = NULL;
    if ((buf = buffer_headroom(buf, 36)) == 0) {
        return buf;
    } else {
        buffer_data_reserve_header(buf, 36);
        ptr = buffer_data_pointer(buf);
        ptr = pana_avp_base_write(AVP_PAC_INFO_CODE, 18, ptr, 0, 0);
        //SET Relay IPV6 address
        if (suite->pana_session.user_server) {
            memcpy(ptr, suite->session_address, 16);
            ptr += 16;
            ptr = common_write_16_bit(suite->session_port, ptr);

            adr_ptr = protocol_6lowpan_nd_border_router_address_get(buf->interface->nwk_id);
            if (adr_ptr) {
                memcpy(buf->src_sa.address, adr_ptr, 16);
                memcpy(buf->dst_sa.address, suite->pana_session.session_relay_address, 16);
                buf->dst_sa.port = suite->pana_session.relay_port;
            }
        } else {
            memcpy(ptr, buf->src_sa.address, 16);
            ptr += 16;
            ptr = common_write_16_bit(buf->src_sa.port, ptr);
        }
        //PADDING for PAC
        ptr = common_write_16_bit(0, ptr);
        //PANA Relay AVP header Write data is already there
        ptr = pana_avp_base_write(AVP_RELAY_MSG_CODE, relay_len, ptr, 0, 0);
    }
    //Enable security for relay allways by Default
    buf->options.ll_security_bypass_tx = false;
    padding %= 4;
    if (padding) {
        padding = 4 - padding;
        //tr_debug("Add Pad: %02x", padding);
        if ((buf = buffer_headroom(buf, padding)) != 0) {
            uint8_t *ptr2;
            buffer_data_reserve_header(buf, padding);
            ptr = buffer_data_pointer(buf);
            ptr2 = ptr;
            ptr += padding;
            memmove(ptr2, ptr, relay_len + 36);
        }
    }
    return buf;
}
Example #8
0
void udp_checksum_write(buffer_t *buf)
{
    uint8_t *ptr = buffer_data_pointer(buf) + 6;
    uint16_t check;

    common_write_16_bit(0, ptr);
    check = buffer_ipv6_fcf(buf, IPV6_NH_UDP);
    if (check == 0) {
        check = 0xffff;
    }
    common_write_16_bit(check, ptr);
}
int thread_management_get_commissioner_address(int8_t interface_id, uint8_t *address_ptr, uint16_t *port_ptr)
{
#ifdef HAVE_THREAD
    protocol_interface_info_entry_t *cur;
    cur = protocol_stack_interface_info_get_by_id(interface_id);

    if (!cur || !cur->thread_info || !address_ptr) {
        return -1;
    }

    if (!cur->thread_info->registered_commissioner.commissioner_valid) {
        return -2;
    }
    memcpy(address_ptr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
    memcpy(address_ptr + 8, ADDR_SHORT_ADR_SUFFIC, 6);
    common_write_16_bit(0xfc30 + (cur->thread_info->registered_commissioner.session_id % 8), address_ptr + 14);

    if (port_ptr) {
        *port_ptr = THREAD_MANAGEMENT_PORT;// Default commissioner port
    }

    return 0;
#else
    (void) interface_id;
    (void) address_ptr;
    (void) port_ptr;
    return -1;
#endif
}
Example #10
0
uint8_t *thread_meshcop_tlv_data_write_uint16(uint8_t *ptr, uint8_t type, uint16_t data)
{
    *ptr++ = type;
    *ptr++ = 2;
    ptr = common_write_16_bit(data, ptr);
    return ptr;
}
int thread_management_get_my_iid16(int8_t interface_id, uint8_t *iidPtr)
{
    protocol_interface_info_entry_t *cur;
    cur = protocol_stack_interface_info_get_by_id(interface_id);
    if (!cur) {
        return -1;
    }

    if (!cur->thread_info) {
        return -1;
    }

    if (thread_attach_ready(cur) != 0) {
        return -1;
    }

    if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) {
        return -1;
    }

    memcpy(iidPtr, ADDR_SHORT_ADR_SUFFIC, 6);
    common_write_16_bit(mac_helper_mac16_address_get(cur), (iidPtr + 6));

    return 0;
}
Example #12
0
uint8_t *mle_tlv_write_version(uint8_t *ptr, uint16_t version)
{
    *ptr++ = MLE_TYPE_VERSION;
    *ptr++ = 2;
    ptr = common_write_16_bit(version, ptr);
    return ptr;
}
Example #13
0
uint8_t *mle_tlv_write_link_quality(uint8_t *ptr, uint8_t incoming_idr, uint8_t *mac64, uint16_t short_address, uint8_t priority_flag)
{
    *ptr++ = MLE_TYPE_LINK_QUALITY;
    if (mac64) {
        *ptr++ = 11;
        *ptr++ = 0x07; /* 8 bytes long address */
    } else {
        *ptr++ = 5;
        *ptr++ = 0x01; /* 2 bytes long address */
    }

    if (priority_flag) {
        *ptr++ = MLE_NEIGHBOR_PRIORITY_LINK | MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
    } else {
        *ptr++ = MLE_NEIGHBOR_INCOMING_LINK | MLE_NEIGHBOR_OUTGOING_LINK;
    }

    *ptr++ = incoming_idr;

    if (mac64) {
        memcpy(ptr, mac64, 8);
        ptr += 8;
    } else {
        ptr = common_write_16_bit(short_address, ptr);
    }

    return ptr;
}
Example #14
0
uint8_t *mle_tlv_write_short_address(uint8_t *ptr, uint16_t shortAddress)
{
    *ptr++ = MLE_TYPE_ADDRESS16;
    *ptr++ = 2;
    ptr = common_write_16_bit(shortAddress, ptr);
    return ptr;
}
Example #15
0
uint8_t* fhss_beacon_encode_raw(uint8_t* buffer, const fhss_synchronization_beacon_payload_s* source)
{
    *buffer++ = FHSS_DATA_START_DELIMETER;
    *buffer++ = source->channel_index;
    *buffer++ = source->sender_unicast_channel;
    buffer = common_write_16_bit(source->current_superframe, buffer);
    buffer = common_write_16_bit(source->remaining_slots, buffer);
    buffer = common_write_16_bit(source->channel_list_counter, buffer);
    *buffer++ = source->hop_count;
    *buffer++ = source->number_of_broadcast_channels;
    *buffer++ = source->number_of_tx_slots;
    buffer = common_write_32_bit(source->time_since_last_beacon, buffer);
    buffer = common_write_16_bit(source->processing_delay, buffer);
    buffer = common_write_16_bit(source->superframe_length, buffer);
    *buffer++ = source->number_of_superframes_per_channel;

    return buffer;
}
Example #16
0
static void thread_nd_coap_response_callback(int8_t interface_id, int8_t status, const uint8_t ip_addr[16], uint16_t loc_addr, uint32_t last_transaction_time, uint8_t *mleid)
{
    protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
    if (!cur) {
        return;
    }
    (void) last_transaction_time;
    (void) mleid;

    ipv6_neighbour_t *neighbour_entry = ipv6_neighbour_lookup(&cur->ipv6_neighbour_cache, ip_addr);
    if (neighbour_entry) {
        if (status == 0) {
            uint8_t ll_addr[4];
            common_write_16_bit(cur->mac_parameters->pan_id, ll_addr + 0);
            common_write_16_bit(loc_addr, ll_addr + 2);
            ipv6_neighbour_update_from_na(&cur->ipv6_neighbour_cache, neighbour_entry, NA_S | NA_O | NA_R, ADDR_802_15_4_SHORT, ll_addr);
        } else {
            ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour_entry);
        }
    }
}
Example #17
0
void thread_tasklet_trace_bootstrap_info()
{
    link_layer_address_s app_link_address_info;
    uint8_t temp_ipv6[16];
    if (arm_net_address_get(thread_tasklet_data_ptr->nwk_if_id,
                            ADDR_IPV6_GP, temp_ipv6) == 0) {
        tr_debug("GP IPv6: %s", trace_ipv6(temp_ipv6));
    }

    if (arm_nwk_mac_address_read(thread_tasklet_data_ptr->nwk_if_id,
                                 &app_link_address_info) != 0) {
        tr_error("MAC Address read fail\n");
    } else {
        uint8_t temp[2];
        common_write_16_bit(app_link_address_info.mac_short,temp);
        tr_debug("MAC 16-bit: %s", trace_array(temp, 2));
        common_write_16_bit(app_link_address_info.PANId, temp);
        tr_debug("PAN ID: %s", trace_array(temp, 2));
        tr_debug("MAC 64-bit: %s", trace_array(app_link_address_info.mac_long, 8));
        tr_debug("IID (Based on MAC 64-bit address): %s", trace_array(app_link_address_info.iid_eui64, 8));
    }
}
Example #18
0
uint8_t *thread_meshcop_tlv_data_write_header(uint8_t *ptr, uint8_t type, uint16_t length)
{
    if (!ptr) {
        return ptr;    // Check parameters
    }
    *ptr++ = type;
    if (length > 254) {
        *ptr++ = 0Xff;
        ptr = common_write_16_bit(length, ptr);
    } else {
        *ptr++ = length;
    }
    return ptr;
}
Example #19
0
static uint8_t *eapol_key_information_write(eapol_key_information_t *key_information, uint8_t *ptr)
{
    uint16_t key_info = 0;
    key_info |= (key_information->description_version << KEY_INFO_VERSION_BIT_SHIFT);
    key_info |= (key_information->pairwise_key << KEY_INFO_KEY_TYPE_BIT_SHIFT);
    key_info |= (key_information->install << KEY_INFO_INSTALL_BIT_SHIFT);
    key_info |= (key_information->key_ack << KEY_INFO_ACK_BIT_SHIFT);
    key_info |= (key_information->key_mic << KEY_INFO_MIC_SHIFT);
    key_info |= (key_information->secured_key_frame << KEY_INFO_SECURE_SHIFT);
    key_info |= (key_information->error << KEY_INFO_ERROR_SHIFT);
    key_info |= (key_information->request << KEY_INFO_REQUEST_SHIFT);
    key_info |= (key_information->encrypted_key_data << KEY_INFO_ENC_KEY_DATA_SHIFT);
    key_info |= (key_information->smk_handshake << KEY_INFO_SMK_SHIFT);
    return common_write_16_bit(key_info, ptr);
}
Example #20
0
uint8_t *thread_meshcop_tlv_data_write(uint8_t *ptr, uint8_t type, uint16_t length, const uint8_t *data)
{
    if (!ptr) {
        return ptr;    // Check parameters
    }
    *ptr++ = type;
    if (length > 254) {
        *ptr++ = 0Xff;
        ptr = common_write_16_bit(length, ptr);
    } else {
        *ptr++ = length;
    }
    if ( length > 0  && data) {
        memcpy(ptr, data, length);
    }
    return ptr + length;
}
uint8_t *thread_nd_network_data_has_route_tlv_write(uint8_t *ptr, uint16_t routerId, uint8_t prf)
{
    ptr = common_write_16_bit(routerId, ptr);
    *ptr++ = prf;
    return ptr;
}
uint8_t *thread_nd_network_data_border_router_tlv_write(uint8_t *ptr, uint16_t routerId, uint16_t flags)
{
    ptr = common_write_16_bit(routerId, ptr);
    ptr = common_write_16_bit(flags, ptr);
    return ptr;
}
Example #23
0
/*
 *   0                   1                   2                   3
 *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *                                  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *                                  |  Option Type  |  Opt Data Len |
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  |O|R|F|0|0|0|0|0| RPLInstanceID |          SenderRank           |
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *  |                         (sub-TLVs)                            |
 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *                     Figure 1: RPL Option
 */
static buffer_t *rpl_data_exthdr_provider_hbh_2(buffer_t *buf, rpl_instance_t *instance, rpl_neighbour_t *neighbour, ipv6_exthdr_stage_t stage, int16_t *result)
{
    ipv6_route_info_t *route_info = &buf->route->route_info;

    /* This can be called both for routes which only use HbH headers (eg DIO)
     * as well as one-hop DAO_SR routes which would normally use source routing
     * headers, if there was more than one hop. For DAO_SR, neighbour will be
     * NULL.
     */

    rpl_dodag_t *dodag = rpl_instance_current_dodag(instance);
    if (!dodag) {
        *result = -1;
        return buf;
    }

    bool destination_in_instance = false;
    uint16_t ext_size = 0;
    if (addr_ipv6_equal(route_info->next_hop_addr, buf->dst_sa.address) ||
        addr_ipv6_equal(buf->dst_sa.address, dodag->id)) {
        destination_in_instance = true;

        if (buf->rpl_option) {
            /* Forwarding an existing option - preserve it */
            uint8_t opt_size = buf->rpl_option[0];
            ext_size = 2 + opt_size;
            ext_size = (ext_size + 7) &~ 7;
        } else {
            /* Generating our own option - fixed size, no TLVs */
            ext_size = 8;
        }
    }

    switch (stage) {
        case IPV6_EXTHDR_SIZE:
            *result = ext_size;
            return buf;

        case IPV6_EXTHDR_INSERT: {
            if (!destination_in_instance) {
                /* We don't add a header - we'll do it on the tunnel */
                *result = 0;
                return buf;
            }
            buf = buffer_headroom(buf, ext_size);
            if (!buf) {
                return NULL;
            }
            uint8_t *ext = buffer_data_reserve_header(buf, ext_size);
            ext[0] = buf->options.type;
            buf->options.type = IPV6_NH_HOP_BY_HOP;
            ext[1] = ext_size / 8 - 1;
            uint8_t *opt = ext + 2;
            opt[0] = IPV6_OPTION_RPL;
            if (buf->rpl_option) {
                /* Get back the RPL option we stripped off an outer IP header */
                memcpy(opt + 1, buf->rpl_option, 1 + buf->rpl_option[0]);
                ns_dyn_mem_free(buf->rpl_option);
                buf->rpl_option = NULL;
            } else {
                opt[1] = 4; // option length
                opt[2] = 0; // placeholder
                opt[3] = instance->id;
                /* For upwards routes we can deduce that DODAGID must be
                 * the destination, so set the D flag.
                 */
                if (rpl_instance_id_is_local(instance->id) && !rpl_data_is_rpl_downward_route(route_info->source)) {
                    opt[3] |= RPL_INSTANCE_DEST;
                }
                common_write_16_bit(RPL_RANK_INFINITE, opt + 4); // SenderRank (placeholder)
            }
            /* Pad HbH header if necessary. */
            uint8_t pad_len = ext + ext_size - (opt + 2 + opt[1]);
            if (pad_len == 1) {
                opt[0] = IPV6_OPTION_PAD1;
            } else if (pad_len > 1) {
                opt[0] = IPV6_OPTION_PADN;
                opt[1] = pad_len - 2;
                memset(opt + 2, 0, pad_len - 2);
            }
            // don't forget to set the "RPL option present" marker
            buf->options.ip_extflags |= IPEXT_HBH_RPL;
            *result = 0;
            return buf;
        }

        case IPV6_EXTHDR_MODIFY: {
            uint8_t *opt;
            uint16_t sender_rank;

            rpl_data_locate_info(buf, &opt, NULL);
            if (!opt) {
                *result = IPV6_EXTHDR_MODIFY_TUNNEL;
                // Tunnel to next hop in general case, but if going to DODAGID,
                // it can tunnel all the way (and it HAS to if it is a local
                // DODAG).
                if (!addr_ipv6_equal(buf->dst_sa.address, dodag->id)) {
                    memcpy(buf->dst_sa.address, route_info->next_hop_addr, 16);
                }
                buf->src_sa.addr_type = ADDR_NONE; // force auto-selection
                return buf;
            }

            if (buf->ip_routed_up) {
                /* Check for rank errors - RFC 6550 11.2.2.2. */
                /* Note that RPL spec does not say that packets from nodes of
                 * equal rank are errors, but we treat them as such to get
                 * reliable sibling loop detection - we require sender rank to be
                 * strictly less for Down packets and strictly greater for Up.
                 */
                sender_rank = common_read_16_bit(opt + 4);
                rpl_cmp_t cmp = rpl_rank_compare_dagrank_rank(dodag, sender_rank, instance->current_rank);
                rpl_cmp_t expected_cmp = (opt[2] & RPL_OPT_DOWN) ? RPL_CMP_LESS : RPL_CMP_GREATER;
                if (cmp != expected_cmp) {
                    /* Set the Rank-Error bit; if already set, drop */
                    if (opt[2] & RPL_OPT_RANK_ERROR) {
                        protocol_stats_update(STATS_RPL_ROUTELOOP, 1);
                        tr_info("Forwarding inconsistency R");
                        rpl_instance_inconsistency(instance);
                        *result = -1;
                        return buf;
                    } else {
                        opt[2] |= RPL_OPT_RANK_ERROR;
                    }
                }
            }

            if (buf->rpl_flag_error & RPL_OPT_FWD_ERROR) {
                opt[2] |= RPL_OPT_FWD_ERROR;
            } else if (rpl_data_is_rpl_downward_route(route_info->source)) {
                opt[2] |= RPL_OPT_DOWN;
            } else {
                opt[2] &= ~RPL_OPT_DOWN;
            }

            /* Set the D flag for local instances */
            if (rpl_instance_id_is_local(instance->id)) {
                if (addr_ipv6_equal(dodag->id, buf->dst_sa.address)) {
                    opt[3] |= RPL_INSTANCE_DEST;
                } else if (addr_ipv6_equal(dodag->id, buf->src_sa.address)) {
                    opt[3] &=~ RPL_INSTANCE_DEST;
                } else {
                    tr_error("Local instance invalid %s[%d]: %s -> %s", trace_ipv6(dodag->id), instance->id, trace_ipv6(buf->src_sa.address), trace_ipv6(buf->dst_sa.address));
                    *result = -1;
                    return buf;
                }
            }

            /* RPL 11.2.2.2. says we set SenderRank to infinite when forwarding
             * across a version discontinuity. (Must be up - we don't know versions
             * of downward routes).
             */
            if ((buf->rpl_flag_error & RPL_OPT_FWD_ERROR) || rpl_data_is_rpl_downward_route(route_info->source) || !neighbour || neighbour->dodag_version == instance->current_dodag_version) {
                sender_rank = nrpl_dag_rank(dodag, instance->current_rank);
            } else {
                sender_rank = RPL_RANK_INFINITE;
            }
            common_write_16_bit(sender_rank, opt + 4);
            *result = 0;
            return buf;
        }
        default:
            return buffer_free(buf);
    }
}
Example #24
0
/* Input: Final IP packet for transmission on link.
 *        Buffer destination = final destination
 *        Buffer source undefined.
 *        Route next hop address set.
 * Output: Buffer destination+source = link-layer addresses
 *         Sent to mesh, LowPAN fragmentation or MAC layers
 */
buffer_t *lowpan_down(buffer_t *buf)
{
    protocol_interface_info_entry_t *cur = buf->interface;

    buf->options.type = 0;

    if (!buf->route) {
        tr_debug("lowpan_down route");
        return buffer_free(buf);
    }

    const uint8_t *ip_src = buffer_data_pointer(buf) + 8;
    const uint8_t *next_hop = buf->route->route_info.next_hop_addr;
    bool link_local = addr_is_ipv6_link_local(next_hop);
    bool stable_only = false;

    /* We have IP next hop - figure out the MAC address */
    if (addr_is_ipv6_multicast(next_hop)) {
        buf->dst_sa.addr_type = ADDR_BROADCAST;
        common_write_16_bit(cur->mac_parameters->pan_id, buf->dst_sa.address);
        buf->dst_sa.address[2] = 0x80 | (next_hop[14] & 0x1f);
        buf->dst_sa.address[3] = next_hop[15];
        stable_only = true;
    } else { /* unicast */
        ipv6_neighbour_t *n = ipv6_interface_resolve_new(cur, buf);
        if (!n) {
            return NULL;
        }
        if (thread_info(cur)) {
            stable_only = thread_stable_context_check(cur, buf);
        }
    }

    if (!buf->link_specific.ieee802_15_4.useDefaultPanId) {
        /* Override dest PAN ID (from multicast map above, or neighbour cache) */
        common_write_16_bit(buf->link_specific.ieee802_15_4.dstPanId, buf->dst_sa.address);
    }

    /* Figure out which source MAC address to use. Usually try to match the
     * source, for best compression, and to ensure if the layer above uses LL64
     * (like MLE), it forces us to use our MAC64.
     */
    if (thread_info(cur) && !(link_local && thread_insist_that_mesh_isnt_a_link(cur)) && buf->dst_sa.addr_type == ADDR_802_15_4_SHORT) {
        /* For Thread, we want to always use short source address for unicast
         * to non-link-local 16-bit addresses, which is the case where we want
         * to use mesh headers.
         */
        buf->src_sa.addr_type = ADDR_802_15_4_SHORT;
    } else if (addr_iid_matches_eui64(ip_src + 8, cur->mac)) {
        buf->src_sa.addr_type = ADDR_802_15_4_LONG;
    } else if (cur->mac_parameters->mac_short_address < 0xfffe && addr_iid_matches_lowpan_short(ip_src + 8, cur->mac_parameters->mac_short_address)) {
        buf->src_sa.addr_type = ADDR_802_15_4_SHORT;
    } else {
        /* This lets mac_mlme_write_our_addr choose based on address mode */
        buf->src_sa.addr_type = ADDR_NONE;
    }

    if (!mac_helper_write_our_addr(cur, &buf->src_sa)) {
        return buffer_free(buf);
    }

    /* Clear Link Layer Re Transmission Counter */
    //buf->fhss_channel_retries_left = 1+ cur->mac_parameters->number_of_fhss_channel_retries;


    if (buf->dst_sa.addr_type != ADDR_802_15_4_LONG && buf->dst_sa.addr_type != ADDR_802_15_4_SHORT && buf->dst_sa.addr_type != ADDR_BROADCAST) {
        tr_debug("IP:Dest Pro. addr_type: %02x", buf->dst_sa.addr_type);
        return buffer_free(buf);
    }

    uint_fast8_t mesh_size;
    if (link_local && thread_insist_that_mesh_isnt_a_link(cur)) {
        mesh_size = 0;
    } else {
        /* Allow the link-layer destination addresses passed from upper layers
         * to be remapped - used to implement Thread anycast.
         *
         * Mapping function can change address and type - if it returns false,
         * packet is dropped.
         *
         * Note that this mapping has to be done before IPHC compression, which
         * is why it moved from mesh.c.
         */
        if (!mesh_address_map(cur, &buf->dst_sa.addr_type, buf->dst_sa.address)) {
            tr_debug("mesh_address_map fail");
            return buffer_free(buf);
        }

        /* After mapping, compute final mesh header size (which depends on
         * the final address).
         */
        mesh_size = mesh_header_size(buf);
    }

    if (mesh_size == 0) {
        if (buf->dst_sa.addr_type == ADDR_BROADCAST) {
            /* Thread says multicasts other than MLE are sent to our parent, if we're an end device */
            if (cur->ip_multicast_as_mac_unicast_to_parent && !buf->options.ll_broadcast_tx) {
                if (protocol_6lowpan_interface_get_mac_coordinator_address(cur, &buf->dst_sa) < 0) {
                    tr_warn("IP: No parent for multicast as unicast");
                    return buffer_free(buf);
                }
            } else {
                /*
                 * Not using a mesh header, so have to "purify" RFC 4944 multicast - we
                 * set a 100xxxxxxxxxxxxx RFC 4944 multicast address above, but
                 * IEEE 802.15.4 only supports broadcast in the real MAC header.
                 */
                common_write_16_bit(0xFFFF, buf->dst_sa.address + 2);
            }
        }
    }

    /* RFC 6282+4944 require that we limit compression to the first fragment.
     * This check is slightly conservative - always allow 4 for first-fragment header
     */
    uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf);
    uint_fast16_t max_iphc_size = mac_helper_max_payload_size(cur, overhead) - mesh_size - 4;

    buf = iphc_compress(&cur->lowpan_contexts, buf, max_iphc_size, stable_only);
    if (!buf) {
        return NULL;
    }

    if (mesh_size != 0) {
        buf->info = (buffer_info_t)(B_FROM_IPV6_TXRX | B_TO_MESH_ROUTING | B_DIR_DOWN);
        return buf;
    }

    buf->info = (buffer_info_t)(B_FROM_IPV6_TXRX | B_TO_MAC | B_DIR_DOWN);

    return buf;
}
/**
  * \brief Network state event handler.
  * \param event show network start response or current network state.
  *
  * - ARM_NWK_BOOTSTRAP_READY: Save NVK peristant data to NVM and Net role
  * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state
  * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state
  * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result
  * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels
  * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state
  */
void app_parse_network_event(arm_event_s *event )
{
	arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
	switch (status)
	{
		  case ARM_NWK_BOOTSTRAP_READY:
			  /* Network is ready and node is connect to Access Point */
			  if(access_point_status==0)
			  {
				  uint8_t temp_ipv6[16];
				  tr_debug("Network Connection Ready");
				  access_point_status=1;

				  if( arm_nwk_nd_address_read(net_rf_id,&app_nd_address_info) != 0)
				  {
					  tr_debug("ND Address read fail");
				  }
				  else
				  {
					  debug("ND Access Point:");
						printf_ipv6_address(app_nd_address_info.border_router);

						debug("ND Prefix 64:");
						printf_array(app_nd_address_info.prefix, 8);

						if(arm_net_address_get(net_rf_id,ADDR_IPV6_GP,temp_ipv6) == 0)
						{
							debug("GP IPv6:");
							printf_ipv6_address(temp_ipv6);
						}
					}

				  if( arm_nwk_mac_address_read(net_rf_id,&app_link_address_info) != 0)
					{
						tr_debug("MAC Address read fail\n");
					}
					else
					{
						uint8_t temp[2];
						debug("MAC 16-bit:");
						common_write_16_bit(app_link_address_info.PANId,temp);
						debug("PAN ID:");
						printf_array(temp, 2);
						debug("MAC 64-bit:");
						printf_array(app_link_address_info.mac_long, 8);
						debug("IID (Based on MAC 64-bit address):");
						printf_array(app_link_address_info.iid_eui64, 8);
					}

			  }

			  break;
		  case ARM_NWK_NWK_SCAN_FAIL:
			  /* Link Layer Active Scan Fail, Stack is Already at Idle state */
			  tr_debug("Link Layer Scan Fail: No Beacons");
			  access_point_status=0;
			  break;
		  case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
			  /* No ND Router at current Channel Stack is Already at Idle state */
			  tr_debug("ND Scan/ GP REG fail");
			  access_point_status=0;
			  break;
		  case ARM_NWK_NWK_CONNECTION_DOWN:
			  /* Connection to Access point is lost wait for Scan Result */
			  tr_debug("ND/RPL scan new network");
			  access_point_status=0;
			  break;
		  case ARM_NWK_NWK_PARENT_POLL_FAIL:
			  access_point_status=0;
			  break;
		  case ARM_NWK_AUHTENTICATION_FAIL:
			  tr_debug("Network authentication fail");
			  access_point_status=0;
			  break;
		  default:
			  debug_hex(status);
			  debug("Unknow event");
			  break;
	 }

	if(access_point_status == 0)
	{
		//Set Timer for new network scan
		eventOS_event_timer_request(1, ARM_LIB_SYSTEM_TIMER_EVENT,node_main_tasklet_id,5000); // 5 sec timer started
	}
}
Example #26
0
static bool mac_helper_write_16bit(uint16_t temp16, uint8_t *addrPtr)
{
    common_write_16_bit(temp16, addrPtr);
    return temp16 != 0xffff;
}