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); } }
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; }
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); }
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)); }
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); }
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); }
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; }
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 }
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; }
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; }
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; }
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; }
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; }
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); } } }
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)); } }
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; }
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); }
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; }
/* * 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); } }
/* 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 } }
static bool mac_helper_write_16bit(uint16_t temp16, uint8_t *addrPtr) { common_write_16_bit(temp16, addrPtr); return temp16 != 0xffff; }