BA / Mbed OS BaBoRo1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_bootstrap.c Source File

thread_bootstrap.c

00001 /*
00002  * Copyright (c) 2014-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * \file thread_bootstrap.c
00032  * \brief Add short description about this file!!!
00033  *
00034  */
00035 #include "nsconfig.h"
00036 #ifdef HAVE_THREAD
00037 #include <string.h>
00038 #include <ns_types.h>
00039 #include <nsdynmemLIB.h>
00040 #include "eventOS_event.h"
00041 #include "eventOS_event_timer.h"
00042 #include "randLIB.h"
00043 #include "ns_sha256.h"
00044 #include "common_functions.h"
00045 #include "NWK_INTERFACE/Include/protocol.h"
00046 #include "net_thread_test.h"
00047 #include "ipv6_stack/protocol_ipv6.h"
00048 #include "libDHCPv6/libDHCPv6.h"
00049 #include "libDHCPv6/libDHCPv6_server.h"
00050 #include "ns_trace.h"
00051 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00052 #include "6LoWPAN/Thread/thread_common.h"
00053 #include "6LoWPAN/Thread/thread_routing.h"
00054 #include "6LoWPAN/Thread/thread_nd.h"
00055 #include "6LoWPAN/Thread/thread_bootstrap.h"
00056 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00057 #include "6LoWPAN/Thread/thread_discovery.h"
00058 #include "6LoWPAN/Thread/thread_leader_service.h"
00059 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00060 #include "6LoWPAN/Thread/thread_management_internal.h"
00061 #include "6LoWPAN/Thread/thread_management_server.h"
00062 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00063 #include "6LoWPAN/Thread/thread_network_synch.h"
00064 #include "6LoWPAN/Thread/thread_joiner_application.h"
00065 #include "6LoWPAN/Thread/thread_extension.h"
00066 #include "6LoWPAN/Thread/thread_management_client.h"
00067 #include "6LoWPAN/Thread/thread_address_registration_client.h"
00068 #include "6LoWPAN/Thread/thread_joiner_application.h"
00069 #include "6LoWPAN/Thread/thread_bbr_api_internal.h"
00070 #include "6LoWPAN/Thread/thread_border_router_api_internal.h"
00071 #include "6LoWPAN/Thread/thread_beacon.h"
00072 #include "6LoWPAN/Thread/thread_nvm_store.h"
00073 #include "6LoWPAN/Thread/thread_extension_bootstrap.h"
00074 #include "6LoWPAN/MAC/mac_helper.h"
00075 #include "6LoWPAN/Thread/thread_mle_message_handler.h"
00076 #include "mac_api.h"
00077 #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up
00078 #include "thread_management_if.h"
00079 #include "thread_border_router_api.h"
00080 #include "thread_tmfcop_lib.h"
00081 #include "Common_Protocols/ipv6.h"
00082 #include "Common_Protocols/icmpv6.h"
00083 #include "Common_Protocols/icmpv6_radv.h"
00084 #include "MPL/mpl.h"
00085 #include "MLE/mle.h"
00086 #include "MLE/mle_tlv.h"
00087 #include "thread_dhcpv6_client.h"
00088 #include "thread_config.h"
00089 #include "thread_meshcop_lib.h"
00090 #include "multicast_api.h"
00091 #include "mlme.h"
00092 #include "Service_Libs/nd_proxy/nd_proxy.h"
00093 #include "Service_Libs/blacklist/blacklist.h"
00094 #include "6LoWPAN/MAC/mac_data_poll.h"
00095 
00096 #define TRACE_GROUP "thbs"
00097 
00098 //#define EXTRA_DEBUG_INFO
00099 #ifdef EXTRA_DEBUG_INFO
00100 #define tr_debug_extra(...) tr_debug(__VA_ARGS__)
00101 #else
00102 #define tr_debug_extra(...)
00103 #endif
00104 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur);
00105 
00106 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur_interface);
00107 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration);
00108 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur);
00109 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur);
00110 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state);
00111 static void thread_bootsrap_network_discovery_failure(int8_t interface_id);
00112 
00113 static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur);
00114 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info);
00115 static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64);
00116 
00117 
00118 
00119 static bool thread_interface_is_active(int8_t interface_id) {
00120     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00121     if (!cur || !(cur->lowpan_info & INTERFACE_NWK_ACTIVE)) {
00122         return false;
00123     }
00124 
00125     return true;
00126 }
00127 
00128 static void thread_neighbor_remove(int8_t interface_id, mle_neigh_table_entry_t *cur)
00129 {
00130     protocol_interface_info_entry_t *cur_interface = protocol_stack_interface_info_get_by_id(interface_id);
00131     if (!cur_interface) {
00132         return;
00133     }
00134     thread_reset_neighbour_info(cur_interface, cur);
00135 }
00136 
00137 
00138 static bool thread_child_keep_alive_callback(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00139 {
00140     uint8_t mac64[8];
00141     uint8_t *ll64_ptr = mle_service_get_msg_destination_address_pointer(msgId);
00142 
00143     memcpy(mac64, ll64_ptr + 8, 8);
00144     mac64[0] ^= 2;
00145 
00146     mle_neigh_table_entry_t *neig_info = mle_class_get_by_link_address(interface_id, mac64, ADDR_802_15_4_LONG );
00147 
00148     if (!neig_info) {
00149         return false;//Why entry is removed before timeout??
00150     }
00151 
00152 
00153     if (neig_info->ttl > MLE_TABLE_CHALLENGE_TIMER) {
00154         return false;
00155     }
00156 
00157 
00158     if (usedAllRetries) {
00159 
00160         //GET entry
00161         mle_class_remove_entry(interface_id, neig_info);
00162         return false;
00163     }
00164 
00165     return true;
00166 }
00167 
00168 int8_t thread_mle_class_init(int8_t interface_id)
00169 {
00170     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00171     if (!cur) {
00172         return -1;
00173     }
00174 
00175     mac_description_storage_size_t buffer;
00176     //Read MAC device table sizes
00177     if (cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
00178         return -1;
00179     }
00180 
00181     if (buffer.key_description_table_size < 4) {
00182         return -1;
00183     }
00184 
00185     if (mle_class_init(interface_id, buffer.device_decription_table_size - 1, &thread_neighbor_remove, &thread_child_keep_alive, &thread_interface_is_active) != 0) {
00186         return -1;
00187     }
00188 
00189     mle_class_router_challenge(interface_id, NULL);
00190 
00191     //Defined well know neighbour for discovery
00192 
00193     return 0;
00194 }
00195 
00196 
00197 
00198 uint8_t thread_mode_get_by_interface_ptr(protocol_interface_info_entry_t *cur)
00199 {
00200     uint8_t mle_mode = 0;
00201     if (!thread_info(cur)) {
00202         return 0;
00203     }
00204     if (cur->mac_parameters->RxOnWhenIdle) {
00205         mle_mode |= MLE_RX_ON_IDLE;
00206     }
00207 
00208     if (thread_info(cur)->requestFullNetworkData) {
00209         mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET);
00210     }
00211     if (thread_joiner_application_provisioning_get(cur->id) == PROVISIONING_STATUS_NOT_DONE) {
00212         // if provisioning is not done Sleepy devices need to temporarily request full network data
00213         // To receive commissioner information
00214         mle_mode |= (MLE_THREAD_REQ_FULL_DATA_SET);
00215     }
00216 
00217     /* We always send secured data requests */
00218     mle_mode |= MLE_THREAD_SECURED_DATA_REQUEST;
00219 
00220     switch (thread_info(cur)->thread_device_mode) {
00221         case THREAD_DEVICE_MODE_ROUTER:
00222         case THREAD_DEVICE_MODE_FULL_END_DEVICE:
00223             mle_mode |= MLE_FFD_DEV;
00224             break;
00225 
00226         default:
00227             break;
00228     }
00229 
00230 
00231     return mle_mode;
00232 }
00233 
00234 static int8_t thread_child_keep_alive(int8_t interface_id, const uint8_t *mac64)
00235 {
00236     mle_message_timeout_params_t timeout;
00237     uint8_t ll64[16];
00238     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00239     uint32_t keySequence;
00240     uint16_t bufId;
00241     uint8_t mode;
00242     if (!cur) {
00243         return -1;
00244     }
00245 
00246     if (!thread_info(cur)) {
00247         return -1;
00248     }
00249 
00250     //routers do not send keep alive
00251     if (thread_i_am_router(cur)){
00252         return -1;
00253     }
00254 
00255     tr_debug("Child Keep Alive");
00256     bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false,MLE_COMMAND_CHILD_UPDATE_REQUEST);
00257     if (bufId == 0) {
00258         return -1;
00259     }
00260 
00261     thread_management_get_current_keysequence(cur->id, &keySequence);
00262     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00263     mode = thread_mode_get_by_interface_ptr(cur);
00264 
00265     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00266     ptr = mle_general_write_source_address(ptr, cur);
00267     ptr = mle_tlv_write_mode(ptr, mode);
00268 
00269     ptr = thread_leader_data_tlv_write(ptr, cur);
00270 
00271     //Set Addresss TLV
00272     if ((mode & MLE_FFD_DEV) == 0) {
00273         ptr = thread_address_registration_tlv_write(ptr, cur);
00274     }
00275 
00276     memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
00277     memcpy(&ll64[8], mac64, 8);
00278     ll64[8] ^= 2;
00279     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
00280         tr_debug("Buffer overflow at message write");
00281     }
00282     timeout.retrans_max = 3;
00283     timeout.timeout_init = 1;
00284     timeout.timeout_max = 4;
00285     timeout.delay = MLE_NO_DELAY;
00286 
00287     //SET Destination address
00288     mle_service_set_msg_destination_address(bufId, ll64);
00289     //Set Callback
00290     mle_service_set_packet_callback(bufId, thread_child_keep_alive_callback);
00291     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00292     mle_service_send_message(bufId);
00293     return 0;
00294 }
00295 
00296 /**
00297  * Return lower (worse) of the two margins.
00298  */
00299 uint8_t thread_parent_margin_calc(uint8_t marginFromParent, uint8_t marginToParent)
00300 {
00301     if (marginFromParent > marginToParent) {
00302         return marginToParent;
00303     } else {
00304         return marginFromParent;
00305     }
00306 }
00307 
00308 uint8_t thread_compute_link_margin(int8_t rssi)
00309 {
00310     if (rssi < -94) {
00311         return 0;
00312     }
00313 
00314     return (rssi + 94);
00315 }
00316 
00317 uint8_t thread_calculate_link_margin(int8_t dbm, uint8_t compLinkMarginFromParent)
00318 {
00319     uint8_t compLinkMarginToParent;
00320     uint8_t newLqi;
00321 
00322     compLinkMarginToParent = thread_compute_link_margin(dbm);
00323     //Calculate New Combined LQI
00324     newLqi = thread_parent_margin_calc(compLinkMarginFromParent, compLinkMarginToParent);
00325     return newLqi;
00326 }
00327 
00328 bool thread_check_is_this_my_parent(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp)
00329 {
00330     if (entry_temp && thread_info(cur)->thread_endnode_parent) {
00331         if(memcmp(entry_temp->mac64, thread_info(cur)->thread_endnode_parent->mac64, 8) == 0) {
00332          return true;
00333         }
00334     }
00335     return false;
00336 }
00337 
00338 bool thread_bootstrap_request_network_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, uint16_t short_address)
00339 {
00340     bool requestNetworkdata = false;
00341     thread_leader_data_t *leadeInfo = thread_info(cur)->thread_leader_data;
00342 
00343     if (thread_info(cur)->thread_endnode_parent->shortAddress != short_address) {
00344         return false;
00345     }
00346 
00347     if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) {
00348         tr_debug("Learn new Network Data");
00349         requestNetworkdata = true;
00350         thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1;
00351         thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1;
00352     }
00353     else if (common_serial_number_greater_8(leaderData->dataVersion, leadeInfo->dataVersion)) {
00354         requestNetworkdata = true;
00355 
00356     } else if (common_serial_number_greater_8(leaderData->stableDataVersion, leadeInfo->stableDataVersion)) {
00357         requestNetworkdata = true;
00358 
00359     }
00360 
00361     // Version number is updated when new network data is learned to avoid synchronization problems
00362     thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId;
00363     thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId;
00364     if (requestNetworkdata) {
00365         thread_bootstrap_parent_network_data_request(cur, true);
00366     }
00367     return true;
00368 }
00369 
00370 bool thread_instance_id_matches(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
00371 {
00372     if (thread_info(cur)->thread_leader_data) {
00373         if (thread_info(cur)->thread_leader_data->partitionId == leaderData->partitionId) {
00374             return true;
00375         }
00376     }
00377     return false;
00378 }
00379 
00380 static int thread_router_check_previous_partition_info(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv)
00381 {
00382     if (!routeTlv || !routeTlv->dataPtr || !routeTlv->tlvLen || !leaderData) {
00383         //check for parameters
00384         return -1;
00385     }
00386     if ((leaderData->partitionId == cur->thread_info->previous_partition_info.partitionId) &&
00387         (leaderData->weighting == cur->thread_info->previous_partition_info.weighting) &&
00388         (routeTlv->dataPtr[0] == cur->thread_info->previous_partition_info.idSequence)) {
00389         //drop the advertisement from previuos partition
00390         return 1;
00391     }
00392     else {
00393         //do not drop the advertisement
00394         return 0;
00395     }
00396 }
00397 int thread_bootstrap_partition_process(protocol_interface_info_entry_t *cur, uint8_t heard_partition_routers, thread_leader_data_t *heard_partition_leader_data, mle_tlv_info_t *routeTlv)
00398 {
00399     uint8_t active_routers = 0;
00400     thread_leader_data_t *current_leader_data = NULL;
00401 
00402     /* if there scanned parent, then the comparison is between parent responses so retrieve the previously scanned parent info
00403      * else comparison is between existing leader data and heard advertisement leader data so retrieve existing leader data
00404      */
00405     if (thread_info(cur)->thread_attach_scanned_parent) {
00406         current_leader_data = &thread_info(cur)->thread_attach_scanned_parent->leader_data;
00407         active_routers = thread_info(cur)->thread_attach_scanned_parent->activeRouters;
00408     } else {
00409         current_leader_data = thread_info(cur)->thread_leader_data;
00410         active_routers = thread_routing_count_active_routers(&thread_info(cur)->routing);
00411     }
00412 
00413     if (!current_leader_data)  {
00414         tr_warn("There is no leader data present");
00415         return -2;
00416     }
00417 
00418     if (1 == thread_router_check_previous_partition_info(cur, heard_partition_leader_data, routeTlv)) {
00419         tr_debug("Dropping advertisement from old partition without sequence number increase");
00420         return -2;
00421     }
00422     if (heard_partition_routers == 0 && active_routers == 1) {
00423         //heard a REED and I am in a singleton partition so merge
00424         tr_debug("Heard a REED and I am a singleton - merge");
00425         return 2;
00426     }
00427     /*Rule 0: If we are going to form Higher partition than heard we dont try to attach to lower ones
00428      */
00429     if (thread_extension_enabled(cur) &&
00430         thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER &&
00431         heard_partition_leader_data->weighting < thread_info(cur)->partition_weighting) {
00432         return -2;
00433     }
00434 
00435     //Rule 1: A non-singleton Thread Network Partition always has higher priority than a singleton Thread Network Partition
00436     if (heard_partition_routers > 1 && active_routers == 1) {
00437         tr_debug("Heard a nonsingleton and i am a singleton");
00438         return 2;
00439     }
00440     if (active_routers > 1 && heard_partition_routers == 1) {
00441         return -2;
00442     }
00443 
00444     /*Rule 2: When comparing two singleton or two non-singleton Thread Network Partitions,
00445     the one with the higher 8-bit weight value has higher priority. */
00446     if (heard_partition_leader_data->weighting > current_leader_data->weighting) {
00447         tr_debug("Heard a greater weighting");
00448         return 2;
00449     }
00450 
00451     if (heard_partition_leader_data->weighting < current_leader_data->weighting) {
00452         return -2;
00453     }
00454 
00455     /*Rule 3: When comparing two singleton or two non-singleton Thread Network Partitions that have the same 8-bit weight value,
00456      * the one with the higher Partition ID, considered as unsigned 32-bit numbers, has higher priority.
00457      */
00458     if (heard_partition_leader_data->partitionId > current_leader_data->partitionId){
00459         tr_debug("Heard a greater partition id");
00460         return 2;
00461     }
00462 
00463     if (heard_partition_leader_data->partitionId < current_leader_data->partitionId) {
00464         return -2;
00465     }
00466 
00467     return -2;
00468 }
00469 
00470 int thread_leader_data_validation(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv)
00471 {
00472     if (!thread_info(cur)->thread_leader_data) {
00473         return -1;
00474     }
00475     if ((thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) ||
00476         (thread_info(cur)->thread_leader_data->weighting != leaderData->weighting)) {
00477         uint8_t routers_in_route_tlv = thread_get_router_count_from_route_tlv(routeTlv);
00478         //partition checks
00479         return thread_bootstrap_partition_process(cur,routers_in_route_tlv,leaderData, routeTlv);
00480     }
00481 
00482     //Should check is there new version numbers
00483     if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion) ||
00484         common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) {
00485         // Version number increased by some-one else -> there is leader in the network
00486         if (thread_info(cur)->leader_private_data) {
00487             tr_error("Another leader detected -> bootstrap");
00488             thread_bootstrap_reset_restart(cur->id);
00489             return -1;
00490             }
00491         tr_debug("NEW Network Data available");
00492         return 1;
00493     }
00494 
00495     return 0;
00496 }
00497 
00498 void thread_bootstrap_all_nodes_address_generate(uint8_t multicast_address[16],uint8_t prefix[8], uint8_t scope)
00499 {
00500     memset(multicast_address, 0, 16);
00501     multicast_address[0] = 0xff;
00502     multicast_address[1] = 0x30 | scope; //Thread specification says p and t bits are 1
00503     multicast_address[2] = 0x00; //Reserved
00504     multicast_address[3] = 0x40; //Prefix length 64 bits
00505     memcpy(&multicast_address[4], prefix,8);
00506     multicast_address[15] = 1;
00507 }
00508 
00509 void thread_bootstrap_all_nodes_multicast_register(protocol_interface_info_entry_t *cur)
00510 {
00511     uint8_t multicast_address[16];
00512 
00513     switch (cur->thread_info->thread_device_mode) {
00514 #ifdef HAVE_THREAD_ROUTER
00515         case THREAD_DEVICE_MODE_ROUTER:
00516             cur->if_special_multicast_forwarding = thread_router_bootstrap_multicast_forwarder_enable;
00517             break;
00518 #endif
00519 
00520         default:
00521             cur->if_special_multicast_forwarding = NULL;
00522             break;
00523     }
00524 
00525     // Register to link local all thread nodes multicast
00526     thread_bootstrap_all_nodes_address_generate(multicast_address,cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
00527     tr_debug("Register multicast address: %s",trace_ipv6(multicast_address));
00528     addr_add_group(cur, multicast_address);
00529 
00530     // Register to mesh local all thread nodes multicast
00531     thread_bootstrap_all_nodes_address_generate(multicast_address,cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
00532     tr_debug("Register multicast address: %s",trace_ipv6(multicast_address));
00533     addr_add_group(cur, multicast_address);
00534 }
00535 
00536 void thread_bootstrap_all_nodes_multicast_unregister(protocol_interface_info_entry_t *cur)
00537 {
00538     uint8_t multicast_address[16];
00539 
00540     if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) {
00541         //Prefix not valid do not delete
00542         return;
00543     }
00544     // Unregister to link local all thread nodes multicast
00545     thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 2);
00546     tr_debug("Free multicast address: %s",trace_ipv6(multicast_address));
00547     //multicast_free_address(multicast_address);
00548     addr_remove_group(cur, multicast_address);
00549 
00550     // Unregister to mesh local all thread nodes multicast
00551     thread_bootstrap_all_nodes_address_generate(multicast_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 3);
00552     tr_debug("Free multicast address: %s",trace_ipv6(multicast_address));
00553     //multicast_free_address(multicast_address);
00554     addr_remove_group(cur, multicast_address);
00555 }
00556 
00557 void thread_end_device_mode_set(protocol_interface_info_entry_t *cur, bool sleepy)
00558 {
00559     if (sleepy) {
00560         cur->lowpan_info |= INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
00561         mle_class_mode_set(cur->id, MLE_CLASS_SLEEPY_END_DEVICE);
00562         mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false);
00563     } else {
00564         cur->lowpan_info &= ~INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE;
00565         mle_class_mode_set(cur->id, MLE_CLASS_END_DEVICE);
00566         mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true);
00567     }
00568 }
00569 
00570 
00571 int8_t nwk_thread_host_control(protocol_interface_info_entry_t *cur, net_host_mode_t mode, uint32_t delay)
00572 {
00573     int8_t ret_val = 0;
00574     //Check IF Bootsrap Ready and type is Host
00575 
00576     if (cur == NULL || cur->rfd_poll_info == NULL) {
00577         return -1;
00578     }
00579 
00580     nwk_rfd_poll_setups_s *rf_ptr = cur->rfd_poll_info;
00581     switch (mode) {
00582         case NET_HOST_FAST_POLL_MODE:
00583             //fast mode
00584             //Check Host current sleep state
00585             if (rf_ptr->host_mode == NET_HOST_RX_ON_IDLE) {
00586                 tr_debug("Enable Fast poll mode. Init Poll timer and period");
00587                 thread_end_device_mode_set(cur, true);
00588                 mac_poll_timer_trig(delay, cur);
00589                 rf_ptr->nwk_app_poll_time = 300;
00590                 rf_ptr->host_mode = NET_HOST_FAST_POLL_MODE;
00591             }
00592             break;
00593 
00594         case NET_HOST_RX_ON_IDLE:
00595             // Non-sleep mode
00596             thread_end_device_mode_set(cur, false);
00597             rf_ptr->host_mode = NET_HOST_RX_ON_IDLE;
00598             break;
00599 
00600         default:
00601             ret_val = -1;
00602             break;
00603     }
00604 
00605     return ret_val;
00606 }
00607 
00608 void thread_set_link_local_address(protocol_interface_info_entry_t *cur)
00609 {
00610     ns_list_foreach_safe(if_address_entry_t, addr, &cur->ip_addresses) {
00611         if(memcmp(addr->address, ADDR_LINK_LOCAL_PREFIX,8) == 0) {
00612             tr_debug("deleting address %s", trace_ipv6(addr->address));
00613             ns_list_remove(&cur->ip_addresses, addr);
00614             ns_dyn_mem_free(addr);
00615         }
00616     }
00617 
00618     /* Fix EUId64 also  to start use 0*/
00619     memcpy(cur->iid_eui64, cur->mac, 8);
00620     cur->iid_eui64[0] ^= 2;
00621     addr_interface_set_ll64(cur, NULL);
00622 }
00623 
00624 static int thread_configuration_security_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration)
00625 {
00626     uint8_t key_material[32];
00627     uint8_t key_index;
00628 
00629     tr_debug("MAC SET Security Mode");
00630 
00631     if (!(cur->lowpan_info & INTERFACE_NWK_ACTIVE) || !(cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED)) {
00632         return -1;
00633     }
00634     mac_helper_security_key_clean(cur);
00635     mac_helper_default_security_level_set(cur, 5);
00636     mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX);
00637 
00638     cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_PSK_LINK_SECURITY;
00639     cur->mac_parameters->mac_configured_sec_level = 5;
00640     cur->thread_info->masterSecretMaterial.historyKeyValid = false;
00641     cur->thread_info->masterSecretMaterial.valid_Info = true;
00642     // Update the guard timer value
00643     thread_calculate_key_guard_timer(cur, linkConfiguration, true);
00644     //Define KEY's
00645     thread_key_get(linkConfiguration->master_key, key_material, linkConfiguration->key_sequence);
00646     key_index = THREAD_KEY_INDEX(linkConfiguration->key_sequence);
00647     //Set Keys
00648     mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
00649     //Add Security to MLE service
00650     mle_service_security_set_security_key(cur->id, key_material, key_index, true);
00651     //Gen also Next Key
00652     thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
00653     return 0;
00654 }
00655 
00656 void thread_bootstrap_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid, bool coordinator)
00657 {
00658     mlme_start_t start_req;
00659     memset(&start_req, 0, sizeof(mlme_start_t));
00660 
00661     cur->mac_parameters->pan_id = panid;
00662     cur->mac_parameters->mac_channel = channel;
00663 
00664     start_req.PANId = panid;
00665     start_req.LogicalChannel = channel;
00666     start_req.BeaconOrder = 0x0f;
00667     start_req.SuperframeOrder = 0x0f;
00668     start_req.PANCoordinator = coordinator;
00669 
00670     thread_discovery_responser_enable(cur->id, coordinator);
00671 
00672     if (cur->mac_api) {
00673         cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void*)&start_req);
00674     }
00675 }
00676 
00677 int thread_configuration_mac_activate(protocol_interface_info_entry_t *cur, uint16_t channel, uint16_t panid,uint8_t *extended_random_mac)
00678 {
00679     ipv6_neighbour_cache_flush(&cur->ipv6_neighbour_cache);
00680     mac_helper_mac64_set(cur, extended_random_mac);
00681     thread_set_link_local_address(cur);
00682 
00683     //SET Thread default here
00684     mac_helper_mac_mlme_max_retry_set(cur->id, THREAD_MAX_FRAME_RETRIES);
00685 
00686     bool coordinator = (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER);
00687     thread_bootstrap_mac_activate(cur, channel, panid, coordinator);
00688 
00689     mac_data_poll_init(cur);
00690 
00691     return 0;
00692 }
00693 
00694 int thread_configuration_6lowpan_activate(protocol_interface_info_entry_t *cur )
00695 {
00696     tr_debug("6lowpan configure");
00697     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
00698     cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
00699     return 0;
00700 }
00701 
00702 static void thread_bootstrap_ml_address_update(protocol_interface_info_entry_t *cur, const link_configuration_s *conf)
00703 {
00704     tr_debug("Updating ML addresses and prefix information.");
00705     uint8_t address[16];
00706 
00707     if (cur->thread_info->threadPrivatePrefixInfo.ulaValid &&
00708         memcmp(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix,
00709                conf->mesh_local_ula_prefix, 8) != 0) {
00710         // Current prefix is valid and old vs. new different: update old addresses
00711         // Update the addresses in the neighbor cache (replace the old ULA prefix part)
00712         ns_list_foreach(ipv6_neighbour_t, entry, &cur->ipv6_neighbour_cache.list) {
00713             tr_debug("Neighbor cache address: %s", trace_ipv6(entry->ip_address));
00714             if (bitsequal(entry->ip_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) {
00715                 memcpy(entry->ip_address, conf->mesh_local_ula_prefix, 8);
00716                 tr_debug("Updated to %s.", trace_ipv6(entry->ip_address));
00717             }
00718         }
00719 
00720         // Delete the ML64 address
00721         thread_delete_ml64_address(cur);
00722 
00723         // Free previously registered multicast addresses
00724         thread_bootstrap_all_nodes_multicast_unregister(cur);
00725 
00726         // In-place replace all other mesh local addresses...
00727         ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
00728             tr_debug("IP address: %s", trace_ipv6(e->address));
00729             if (bitsequal(e->address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64)) {
00730                 memcpy(address, conf->mesh_local_ula_prefix, 8);
00731                 memcpy(address+8, e->address+8, 8);
00732                 tr_debug("Updated to: %s", trace_ipv6(address));
00733                 addr_add(cur, address, e->prefix_len, e->source, e->valid_lifetime, e->preferred_lifetime, true);
00734                 addr_delete_entry(cur, e);
00735             }
00736         }
00737     }
00738 
00739     // Set new ML-EID and ULA prefix
00740     uint8_t *ml_eid = thread_joiner_application_ml_eid_get(cur->id);
00741     memcpy(cur->iid_slaac, ml_eid, 8);
00742 
00743     arm_thread_private_ula_prefix_set(cur, conf->mesh_local_ula_prefix);
00744 
00745     // Generate new ML64 address
00746     thread_generate_ml64_address(cur);
00747     // Generate new domain address
00748     thread_extension_address_generate(cur);
00749 
00750     // Register multicast addresses
00751     thread_bootstrap_all_nodes_multicast_register(cur);
00752 
00753     // Register leader anycast address (if we are the leader)
00754     thread_router_bootstrap_anycast_address_register(cur);
00755 
00756     thread_bootstrap_routing_activate(cur);
00757 }
00758 
00759 int thread_configuration_thread_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration)
00760 {
00761     tr_debug("thread configure");
00762 
00763     // Update existing mesh-local addresses and the ML prefix
00764     thread_bootstrap_ml_address_update(cur, linkConfiguration);
00765 
00766     //Define Default Contexts
00767     lowpan_context_update(&cur->lowpan_contexts, LOWPAN_CONTEXT_C, 0xFFFF, linkConfiguration->mesh_local_ula_prefix, 64, true);
00768 
00769     thread_extension_activate(cur);
00770 
00771     blacklist_clear();
00772 
00773     blacklist_params_set(
00774         THREAD_BLACKLIST_ENTRY_LIFETIME,
00775         THREAD_BLACKLIST_TIMER_MAX_TIMEOUT,
00776         THREAD_BLACKLIST_TIMER_TIMEOUT,
00777         THREAD_BLACKLIST_ENTRY_MAX_NBR,
00778         THREAD_BLACKLIST_PURGE_NBR,
00779         THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT);
00780 
00781     return 0;
00782 }
00783 
00784 int thread_configuration_mle_activate(protocol_interface_info_entry_t *cur)
00785 {
00786     tr_debug("thread MLE configure");
00787     mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
00788     return 0;
00789 }
00790 
00791 int thread_configuration_mle_disable(protocol_interface_info_entry_t *cur)
00792 {
00793     tr_debug("thread MLE disable");
00794     mle_service_interface_receiver_handler_update(cur->id, NULL);
00795     return 0;
00796 }
00797 
00798 int thread_mle_service_register(int8_t interface_id, uint8_t *mac64 )
00799 {
00800     if (mle_service_interface_register(interface_id,thread_mle_parent_discover_receive_cb, mac64,8) != 0) {
00801             tr_error("Mle Service init Fail");
00802             return -1;
00803     }
00804     mle_service_set_frame_counter_check(true);
00805     mle_service_set_fragmented_msg_ll_security(true);
00806     return 0;
00807 }
00808 
00809 int thread_link_configuration_activate(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration)
00810 {
00811     //Generate Beacon Payload from active configuration
00812     if (thread_beacon_create_payload(cur) != 0) {
00813         return -1;
00814     }
00815 
00816     if (thread_configuration_mac_activate(cur, linkConfiguration->rfChannel, linkConfiguration->panId,thread_joiner_application_random_mac_get(cur->id))) {
00817         return -1;
00818     }
00819 
00820     thread_configuration_thread_activate(cur, linkConfiguration);
00821     thread_configuration_security_activate(cur, linkConfiguration);
00822     thread_configuration_6lowpan_activate(cur);
00823     return 0;
00824 }
00825 
00826 int thread_bootstrap_announce_send(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp, uint16_t selected_channel)
00827 {
00828     uint8_t *ptr;
00829     uint8_t channel_tlv[3];
00830     mle_message_timeout_params_t timeout;
00831     uint32_t keySequence;
00832     uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_DATASET_ANNOUNCE);
00833     if (buf_id == 0) {
00834         return -1;
00835     }
00836 
00837     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_NODES);
00838 
00839     thread_management_get_current_keysequence(cur->id, &keySequence);
00840     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
00841     mle_service_set_msg_link_layer_security_mode(buf_id, true);
00842 
00843     ptr = mle_service_get_data_pointer(buf_id);
00844 
00845     ptr = thread_meshcop_tlv_data_write_uint64(ptr,MLE_TYPE_ACTIVE_TIMESTAMP, timestamp);
00846     ptr = thread_meshcop_tlv_data_write_uint16(ptr,MLE_TYPE_PANID, panid);
00847     channel_tlv[0] = channel_page;
00848     common_write_16_bit(channel, &channel_tlv[1]);
00849     ptr = thread_meshcop_tlv_data_write(ptr,MLE_TYPE_CHANNEL, 3, channel_tlv);
00850 
00851     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
00852         tr_debug("Buffer overflow at message write");
00853     }
00854     //SET packet channel
00855     mle_service_set_msg_rf_channel(buf_id, selected_channel);
00856 
00857     timeout.retrans_max = 0;
00858     timeout.timeout_init = 0;
00859     timeout.timeout_max = 0;
00860     timeout.delay = MLE_NO_DELAY;
00861 
00862     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
00863     mle_service_set_msg_panid(buf_id, 0xffff);
00864     mle_service_send_message(buf_id);
00865     return 0;
00866 }
00867 static void thread_announce_ntf_cb(void* arg)
00868 {
00869     if(!arg)
00870         return;
00871     protocol_interface_info_entry_t *cur = arg;
00872     cur->thread_info->announcement_info->timer = NULL;
00873     thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
00874 }
00875 
00876 static void thread_announce_success_cb(void* arg)
00877 {
00878     // We come here when we have succesfully attached to announced channel and then we announce this back
00879     protocol_interface_info_entry_t *cur = arg;
00880 
00881     if (!cur || !cur->thread_info->announcement_info) {
00882         return;
00883     }
00884 
00885     cur->thread_info->announcement_info->timer = NULL;
00886     cur->thread_info->announcement_info->announce_success = false;
00887     thread_bootstrap_announcement_start(cur, cur->thread_info->announcement_info->channel_page, cur->thread_info->announcement_info->channel, 3, cur->thread_info->announcement_info->period);
00888 }
00889 
00890 void thread_bootstrap_announcement_start(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint8_t count, uint16_t period)
00891 {
00892     if (!cur->thread_info->announcement_info ) {
00893         cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t));
00894     }
00895     if (!cur->thread_info->announcement_info ) {
00896         return;
00897     }
00898     tr_info("Start announcement ch: %d",channel);
00899     cur->thread_info->announcement_info->channel = channel;
00900     cur->thread_info->announcement_info->period = period;
00901     cur->thread_info->announcement_info->channel_page = channel_page;
00902     cur->thread_info->announcement_info->count = count;
00903     cur->thread_info->announcement_info->timer = NULL;
00904     cur->thread_info->announcement_info->announce_success = false;
00905     cur->thread_info->announcement_info->timestamp = 0;
00906     thread_bootsrap_event_trig(THREAD_ANNOUNCE_ACTIVE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
00907 }
00908 void thread_bootstrap_temporary_attach(protocol_interface_info_entry_t *cur, uint8_t channel_page, uint16_t channel, uint16_t panid, uint64_t timestamp)
00909 {
00910     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00911 
00912     if (!linkConfiguration) {
00913         tr_error("No link configuration!");
00914         return;
00915     }
00916 
00917     tr_debug("Attach to new channel %u", channel);
00918 
00919     /*
00920      * Save the old info and make a timer to announce it to old channels once if attachment is succesfull
00921      * When we receive attach fail
00922      */
00923     if (!cur->thread_info->announcement_info ) {
00924         cur->thread_info->announcement_info = ns_dyn_mem_alloc(sizeof(thread_announcement_t));
00925     }
00926     if (!cur->thread_info->announcement_info ) {
00927         return;
00928     }
00929     cur->thread_info->announcement_info->channel = linkConfiguration->rfChannel;
00930     cur->thread_info->announcement_info->channel_page = linkConfiguration->channel_page;
00931     cur->thread_info->announcement_info->panid = linkConfiguration->panId;
00932     cur->thread_info->announcement_info->count = 1;
00933     cur->thread_info->announcement_info->period = 1000;
00934     cur->thread_info->announcement_info->timestamp = timestamp;
00935     cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb,20000, cur);
00936     // TODO check timer value
00937     cur->thread_info->announcement_info->announce_success = true;
00938     linkConfiguration->channel_page = channel_page;
00939     linkConfiguration->rfChannel = channel;
00940     linkConfiguration->panId = panid;
00941     thread_joiner_application_link_configuration_store(cur->id, linkConfiguration);
00942     thread_bootstrap_reset_restart(cur->id);
00943 }
00944 
00945 static const trickle_params_t thread_mpl_data_trickle_params =
00946 {
00947     .Imin = 1, /* 50ms */
00948     .Imax = 2, /* 100ms */
00949     .k = 0,
00950     .TimerExpirations = 2 /* MPL core knows to suppress to 0 for non-routers */
00951 };
00952 
00953 static const trickle_params_t thread_mpl_control_trickle_params =
00954 {
00955     .Imin = 11,
00956     .Imax = 5 * 60 * 20,
00957     .k = 0,
00958     .TimerExpirations = 0
00959 };
00960 
00961 void thread_interface_init(protocol_interface_info_entry_t *cur)
00962 {
00963     thread_discovery_reset(cur->id);
00964     thread_routing_set_mesh_callbacks(cur);
00965     thread_dhcp_client_init(cur->id);
00966     thread_management_client_init(cur->id);
00967     thread_address_registration_init();
00968     cur->mpl_seed_id_mode = MULTICAST_MPL_SEED_ID_MAC_SHORT;
00969     cur->mpl_seed_set_entry_lifetime = 90;
00970     cur->mpl_proactive_forwarding = true;
00971     cur->mpl_control_trickle_params = thread_mpl_control_trickle_params;
00972     cur->mpl_data_trickle_params = thread_mpl_data_trickle_params;
00973     cur->mpl_seed = true;
00974     cur->mpl_treat_realm_domains_as_one = true;
00975     cur->if_ns_transmit = thread_nd_ns_transmit;
00976     cur->if_special_forwarding = thread_nd_special_forwarding;
00977     cur->if_snoop = thread_nd_snoop;
00978     cur->if_icmp_handler = thread_nd_icmp_handler;
00979     cur->ipv6_neighbour_cache.send_nud_probes = false;
00980     cur->ipv6_neighbour_cache.recv_addr_reg = true;
00981     cur->send_mld = false;
00982     cur->ip_multicast_as_mac_unicast_to_parent = true;
00983     if (!cur->thread_info->routerShortAddress) {
00984         cur->thread_info->routerShortAddress = 0xfffe;
00985     }
00986     if (cur->thread_info->thread_attach_scanned_parent) {
00987         mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id);
00988         ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent);
00989         cur->thread_info->thread_attach_scanned_parent = NULL;
00990     }
00991     //Disable Always RPL
00992     rpl_control_remove_domain_from_interface(cur);
00993     mpl_domain_create(cur, ADDR_ALL_MPL_FORWARDERS, NULL, MULTICAST_MPL_SEED_ID_DEFAULT, -1, 0, NULL, NULL);
00994     addr_add_group(cur, ADDR_REALM_LOCAL_ALL_NODES);
00995     cur->nwk_nd_re_scan_count = 5;
00996 
00997 }
00998 
00999 static void thread_interface_bootsrap_mode_init(protocol_interface_info_entry_t *cur)
01000 {
01001     thread_routing_reset(&cur->thread_info->routing);
01002     mac_helper_mac16_address_set(cur, 0xffff);
01003 
01004     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER) {
01005         tr_debug("Set ASPIRING Router Mode");
01006         cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_ROUTER;
01007         cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
01008     } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST &&
01009             cur->thread_info->end_device_link_synch ) {
01010         tr_debug("Set FED Mode");
01011         cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_FULL_END_DEVICE;
01012     } else if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) {
01013         tr_debug("Set ASPIRING Sleepy Host Mode");
01014         cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_SLEEPY_END_DEVICE;
01015         //SET Sleepy Host To RX on Idle mode for bootsrap
01016         nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
01017     } else {
01018         tr_debug("Set End node Mode");
01019         cur->thread_info->thread_device_mode = THREAD_DEVICE_MODE_END_DEVICE;
01020     }
01021     cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
01022 }
01023 
01024 int8_t thread_bootsrap_event_trig(thread_bootsrap_event_type_e event_type, int8_t Id, arm_library_event_priority_e priority)
01025 {
01026     arm_event_s event = {
01027         .receiver = Id,
01028         .sender = 0,
01029         .event_type = event_type,
01030         .priority = priority,
01031     };
01032     return eventOS_event_send(&event);
01033 }
01034 
01035 void thread_bootstrap_reset_restart(int8_t interface)
01036 {
01037     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
01038     if (!cur) {
01039         return;
01040     }
01041 
01042     if (cur->nwk_bootstrap_state == ER_MLE_SYNCH) {
01043         thread_network_synch_data_free(cur->id);
01044     }
01045     thread_nd_service_disable(interface);
01046     thread_routing_deactivate(&cur->thread_info->routing);
01047     //TODO: clear CoAP resending queue
01048     thread_bootsrap_event_trig(THREAD_BOOTSTRAP_RESET, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01049 }
01050 
01051 void thread_tasklet(arm_event_s *event)
01052 {
01053 
01054     protocol_interface_info_entry_t *cur = 0;
01055     thread_bootsrap_event_type_e event_type;
01056     event_type = (thread_bootsrap_event_type_e)event->event_type;
01057     cur = protocol_stack_interface_info_get_by_bootstrap_id(event->receiver);
01058     if (!cur) {
01059         tr_debug("Thread task unknown");
01060         return;
01061     }
01062 
01063     switch (event_type) {
01064         case THREAD_INIT_EVENT:
01065             tr_debug_extra("Thread SM THREAD_INIT_EVENT");
01066             tr_debug("Thread task Init");
01067             break;
01068 
01069         case THREAD_BOOTSTRAP_RESET:
01070             //Reset Current Thread state
01071             tr_debug_extra("Thread SM THREAD_BOOTSTRAP_RESET");
01072             if (thread_bootstrap_reset(cur) == 0) {
01073                 tr_debug("Thread Attached");
01074             } else {
01075                 tr_debug("Stop Bootsrap and send event");
01076             }
01077             break;
01078 
01079         case THREAD_ATTACH_READY:
01080             tr_debug_extra("Thread SM THREAD_ATTACH_READY");
01081             thread_bootstrap_attached_finish(cur);
01082             break;
01083         case THREAD_ATTACH_UPGRADE_REED:
01084             tr_debug_extra("Thread SM THREAD_ATTACH_UPGRADE_REED");
01085             if (thread_router_bootstrap_child_count_get(cur) > 0) {
01086                 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_PARENT_PARTITION_CHANGE);
01087             } else {
01088                 thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_TOO_FEW_ROUTERS);
01089             }
01090 
01091             break;
01092 
01093         case THREAD_ATTACH_DOWNGRADE_ROUTER:
01094             tr_debug_extra("Thread SM THREAD_ATTACH_DOWNGRADE_ROUTER");
01095             thread_bootstrap_attach_start(cur->id, THREAD_REATTACH_REED);
01096             break;
01097 
01098         case THREAD_ATTACH_ACTIVE_ROUTER:
01099             tr_debug_extra("Thread SM THREAD_ATTACH_ACTIVE_ROUTER");
01100             thread_bootstrap_all_nodes_multicast_register(cur);
01101             thread_router_bootstrap_anycast_address_register(cur);
01102             thread_router_bootstrap_active_router_attach(cur);
01103             thread_bootstrap_child_id_request(cur);
01104             if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) {
01105                 // publish our services to allow leader to remove old ones
01106                 thread_border_router_publish(cur->id);
01107             }
01108             thread_router_bootstrap_address_change_notify_send(cur);
01109             // Validate network data after a short period
01110             thread_border_router_resubmit_timer_set(cur->id, 5);
01111             break;
01112         case THREAD_ATTACH_ROUTER_ID_GET_FAIL:
01113             tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_GET_FAIL");
01114             tr_debug("Thread Router Id request Fail");
01115             cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01116             cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED;
01117             thread_router_bootstrap_child_information_clear(cur);
01118             thread_router_bootstrap_reed_advertisements_start(cur);
01119             thread_router_bootstrap_child_id_reject(cur);
01120             break;
01121 
01122         case THREAD_ATTACH_ROUTER_ID_RELEASED:
01123             tr_debug_extra("Thread SM THREAD_ATTACH_ROUTER_ID_RELEASED");
01124             if (thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase)) {
01125                 // publish our services to allow leader to remove old ones
01126                 thread_border_router_publish(cur->id);
01127             }
01128             break;
01129 
01130         case THREAD_CHILD_ID_REQUEST:
01131             tr_debug_extra("Thread SM THREAD_CHILD_ID_REQUEST");
01132             thread_router_bootstrap_child_id_handler(cur);
01133             break;
01134 
01135         case THREAD_CHILD_UPDATE:
01136             tr_debug_extra("Thread SM THREAD_CHILD_UPDATE");
01137             thread_bootstrap_child_update(cur);
01138             break;
01139         case THREAD_ANNOUNCE_ACTIVE: {
01140             tr_debug_extra("Thread SM THREAD_ANNOUNCE_ACTIVE");
01141 
01142             if (cur->thread_info->announcement_info->count > 0) {
01143                 cur->thread_info->announcement_info->count--;
01144 
01145                 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
01146                 if (!linkConfiguration) {
01147                     tr_error("No link configuration!");
01148                     break;
01149                 }
01150 
01151                 // New timeout needed
01152                 cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_ntf_cb,cur->thread_info->announcement_info->period, cur);
01153 
01154                 // Send announce_ntf
01155                 thread_bootstrap_announce_send(cur,linkConfiguration->channel_page,linkConfiguration->rfChannel,linkConfiguration->panId,linkConfiguration->timestamp, cur->thread_info->announcement_info->channel);
01156             } else {
01157                 // Last call, delete announcement info
01158                 ns_dyn_mem_free(cur->thread_info->announcement_info);
01159                 cur->thread_info->announcement_info = NULL;
01160             }
01161 
01162             break;
01163         }
01164 
01165         default:
01166             break;
01167     }
01168 }
01169 
01170 
01171 int thread_bootstrap_tasklet_init(protocol_interface_info_entry_t *cur)
01172 {
01173     if (cur->bootStrapId < 0) {
01174         cur->bootStrapId = eventOS_event_handler_create(&thread_tasklet, THREAD_INIT_EVENT);
01175         tr_debug("Allocate Thread Tasklet");
01176     }
01177     if (cur->bootStrapId >= 0) {
01178         return 0;
01179     }
01180     return -1;
01181 }
01182 
01183 int thread_proxy_validate(int8_t interface_id, uint8_t *addrerss)
01184 {
01185     ipv6_route_t *route;
01186     route = ipv6_route_choose_next_hop(addrerss, interface_id, NULL);
01187     if (!route) {
01188         return -1;
01189     }
01190 
01191     if (route->prefix_len < 128 || !route->on_link) {
01192         return -1;
01193     }
01194 
01195     return 0;
01196 }
01197 
01198 void thread_bootstrap_ready(protocol_interface_info_entry_t *cur)
01199 {
01200     cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01201     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE;
01202 
01203     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
01204         cur->ip_multicast_as_mac_unicast_to_parent = false;
01205         cur->ip_forwarding = true;
01206     } else {
01207         cur->ip_multicast_as_mac_unicast_to_parent = true;
01208         cur->ip_forwarding = false;
01209         if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
01210             /* REED should be able to IP forward */
01211             cur->ip_forwarding = true;
01212         } else {
01213             cur->ip_forwarding = false;
01214         }
01215     }
01216 
01217     tr_info("Set forwarding: ip=%d, multicast=%d", cur->ip_forwarding, thread_i_am_router(cur));
01218 
01219     if (cur->ip_forwarding) {
01220         addr_add_router_groups(cur);
01221     }
01222     // Bizarrely, Thread needs Realm-All-Routers active in FEDs for address resolution
01223     if (cur->ip_forwarding || cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
01224         addr_add_group(cur, ADDR_REALM_LOCAL_ALL_ROUTERS);
01225     }
01226 
01227     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
01228         if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
01229             thread_router_bootstrap_reed_advertisements_start(cur);
01230         }
01231 
01232         thread_bootstrap_mac_activate(cur, cur->mac_parameters->mac_channel, cur->mac_parameters->pan_id, true);
01233 
01234         if (nd_proxy_downstream_interface_register(cur->id,thread_proxy_validate , thread_bbr_proxy_state_update) != 0) {
01235             tr_debug("mesh proxy register fail");
01236         }
01237     }
01238 
01239     if (cur->thread_info->leader_private_data) {
01240         // Generate network data from network data structures
01241         thread_leader_service_generate_network_data(cur);
01242     }
01243 
01244     cur->bootsrap_state_machine_cnt = 0;
01245     mac_data_poll_protocol_poll_mode_decrement(cur);
01246 }
01247 
01248 void thread_clean_all_routers_from_neighbor_list(int8_t interface_id)
01249 {
01250     mle_neigh_table_list_t *neig_list = mle_class_active_list_get(interface_id);
01251     /* Init Double linked Routing Table */
01252     ns_list_foreach_safe(mle_neigh_table_entry_t, cur, neig_list) {
01253         if (thread_is_router_addr(cur->short_adr)) {
01254             tr_debug("Free Router %x", cur->short_adr);
01255             mle_class_remove_entry(interface_id, cur);
01256         }
01257     }
01258 }
01259 
01260 void thread_clean_old_16_bit_address_based_addresses(protocol_interface_info_entry_t *cur)
01261 {
01262     uint8_t static_address[16];
01263     //Delete old ULA16
01264     memcpy(static_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01265     memcpy(&static_address[8], ADDR_SHORT_ADR_SUFFIC, 6);
01266     common_write_16_bit(mac_helper_mac16_address_get(cur), &static_address[14]);
01267     addr_delete(cur, static_address);
01268     mac_helper_mac16_address_set(cur, 0xffff);
01269 
01270 }
01271 
01272 static int thread_bootstrap_attach_start(int8_t interface_id, thread_bootsrap_state_type_e state)
01273 {
01274 
01275     protocol_interface_info_entry_t *cur;
01276 
01277     cur = protocol_stack_interface_info_get_by_id(interface_id);
01278     if (!cur || !cur->thread_info) {
01279         return -1;
01280     }
01281     //Trigger the bootstrap
01282 
01283     nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
01284 
01285     switch (state) {
01286         case THREAD_NORMAL_ATTACH:
01287             cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
01288             mac_helper_default_security_level_set(cur, cur->mac_parameters->mac_configured_sec_level);
01289             mac_helper_default_security_key_id_mode_set(cur,MAC_KEY_ID_MODE_IDX);
01290             break;
01291 
01292         case THREAD_REATTACH:
01293             tr_debug("Thread ReAttach");
01294             //save the current partition id and sequence number before trying reattach
01295             cur->thread_info->previous_partition_info.partitionId = cur->thread_info->thread_leader_data->partitionId;
01296             cur->thread_info->previous_partition_info.weighting = cur->thread_info->thread_leader_data->weighting;
01297             cur->thread_info->previous_partition_info.idSequence = cur->thread_info->routing.router_id_sequence;
01298             cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur);
01299             if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY){
01300                 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH;
01301             }
01302             break;
01303         case THREAD_PARTITION_MERGE:
01304             cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur);
01305             break;
01306         case THREAD_ANY_ATTACH:
01307             cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur);
01308             cur->thread_info->thread_attached_state = THREAD_STATE_ATTACH_ANY;
01309             break;
01310 
01311         case THREAD_REATTACH_REED:
01312             cur->thread_info->releaseRouterId = true;
01313             cur->thread_info->routerShortAddress = mac_helper_mac16_address_get(cur);
01314 
01315             if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY){
01316                 cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH;
01317             }
01318             break;
01319     }
01320 
01321     // Set RX on idle
01322     thread_end_device_mode_set(cur, false);
01323     cur->nwk_nd_re_scan_count = 0;
01324     cur->nwk_bootstrap_state = ER_SCAN;
01325     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 10);
01326     return 0;
01327 }
01328 
01329 static void thread_bootsrap_network_discovery_failure(int8_t interface_id)
01330 {
01331     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01332     if (!cur || !cur->thread_info) {
01333         return;
01334     }
01335 //TODO we should send 3 in burst of 0.1 - 0.6 seconds and then do the exponential backup of 5s -- 80s
01336     uint32_t backof_delay = cur->nwk_nd_re_scan_count*2;
01337     if (backof_delay > 600) backof_delay = 600; //TODO test this and check guess this is 100ms ticks
01338 
01339     tr_debug("Continue network scan");
01340     cur->nwk_bootstrap_state = ER_ACTIVE_SCAN;
01341     cur->bootsrap_state_machine_cnt = backof_delay + randLIB_get_random_in_range(1, 6);
01342 }
01343 
01344 static void thread_bootstrap_generate_leader_and_link(protocol_interface_info_entry_t *cur)
01345 {
01346     if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH) {
01347         tr_debug("ReAttach Fail - retry");
01348         thread_bootstrap_attach_start(cur->id, THREAD_REATTACH);
01349         cur->thread_info->thread_attached_state = THREAD_STATE_REATTACH_RETRY;
01350     }
01351     else if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY) {
01352         tr_warn("ReAttach Fail");
01353         thread_bootstrap_attach_start(cur->id, THREAD_ANY_ATTACH);
01354     } else {
01355         if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) {
01356             bootsrap_next_state_kick(ER_BOOTSTRAP_LEADER_UP, cur);
01357         } else {
01358             bootsrap_next_state_kick(ER_BOOTSTRAP_NEW_FRAGMENT_START, cur);
01359         }
01360     }
01361 }
01362 static int8_t thread_bootstrap_attempt_attach_with_pending_set(protocol_interface_info_entry_t *cur)
01363 {
01364     tr_debug("Attempting to attach with pending set");
01365     uint32_t pending_delay_timer = thread_joiner_application_pending_config_timeout_get(cur->id);
01366     if (pending_delay_timer > 0 && thread_joiner_application_pending_delay_timer_in_sync(cur->id)) {
01367         tr_debug("We have a pending delay timer running");
01368         //we already have a pending set that can be activated so return
01369         return -1;
01370     }
01371 
01372     if (!thread_joiner_application_pending_config_exists(cur->id)) {
01373         tr_debug("no pending configuration found after reset");
01374         return -1;
01375     }
01376 
01377     if (thread_joiner_application_old_config_exists(cur->id)){
01378         //there is an existing old configuration so attempt to attach with it and set the pending timer to expire
01379         thread_joiner_application_old_config_activate(cur->id);
01380         thread_joiner_application_old_config_delete(cur->id);
01381         thread_joiner_application_pending_config_enable(cur->id,20000);
01382     }
01383     else {
01384         thread_joiner_pending_config_activate(cur->id);
01385     }
01386 
01387     return 0;
01388 }
01389 
01390 static void thread_bootstrap_orphan_scan_ready_cb(struct protocol_interface_info_entry *cur_interface, announce_discovery_response_t *discover_response) {
01391 
01392     if (!discover_response) {
01393         thread_bootstrap_orphan_scan_start(cur_interface);
01394         return;
01395     }
01396 
01397     link_configuration_s *link_configuration = thread_joiner_application_get_config(cur_interface->id);
01398 
01399     if (!link_configuration) {
01400         tr_debug("no link configuration found after reset");
01401         return;
01402     }
01403 
01404     tr_debug("New configuration received channel %u, %x", discover_response->channel, discover_response->pan_id);
01405     link_configuration->panId = discover_response->pan_id;
01406     link_configuration->rfChannel = discover_response->channel;
01407     link_configuration->channel_page = 0;
01408     cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN;
01409     cur_interface->bootsrap_state_machine_cnt = 1;
01410     ns_dyn_mem_free(discover_response);
01411 }
01412 
01413 static void thread_bootstrap_orphan_scan_start(struct protocol_interface_info_entry *cur)
01414 {
01415     thread_announce_discover_reques_t scan_req;
01416     //default channel mask for channels 11 to 26
01417     scan_req.channel_mask = 0x001fffe0;
01418 #ifdef THREAD_THCI_SUPPORT
01419     //use active operational dataset's channel mask if available
01420     link_configuration_s *link_configuration = thread_joiner_application_get_config(cur->id);
01421     if (!link_configuration) {
01422         return;
01423     }
01424     scan_req.channel_mask = common_read_32_bit(link_configuration->channel_mask);
01425     //the current channel is added to the mask.
01426     scan_req.channel_mask |= (0x80000000 >> link_configuration->rfChannel);
01427 #endif
01428     scan_req.pan_id = cur->mac_parameters->pan_id;
01429     scan_req.active_timestamp = 0;
01430     scan_req.active_timestamp |= MESHCOP_TLV_ACTIVE_TIME_STAMP_U_BIT;
01431 
01432     if (thread_discovery_announce_network_scan(cur->id, &scan_req, thread_bootstrap_orphan_scan_ready_cb) != 0) {
01433 
01434         tr_debug("announce discover start fail");
01435         thread_bootstrap_attach_start(cur->id, THREAD_NORMAL_ATTACH);
01436     } else {
01437         tr_debug("Orphan Host start announce scan");
01438     }
01439     return;
01440 }
01441 
01442 void thread_bootstrap_connection_error(int8_t interface_id, nwk_connect_error_types errorType, uint8_t *LinkId)
01443 {
01444     (void)LinkId;
01445     protocol_interface_info_entry_t *cur;
01446 
01447     switch (errorType) {
01448         case CON_ERROR_POLL:
01449         case CON_PARENT_CONNECT_DOWN:
01450             thread_bootstrap_reset_restart(interface_id);
01451             break;
01452 
01453         case CON_ERROR_LINK_TX_FAIL:
01454             //thread_mle_challenge_trig(interface_id,LinkId);
01455             break;
01456 
01457         case CON_ERROR_NETWORK_ATTACH_FAIL:
01458             cur = protocol_stack_interface_info_get_by_id(interface_id);
01459             if (!cur || !cur->thread_info) {
01460                 break;
01461             }
01462             if (thread_bootstrap_attempt_attach_with_pending_set(cur) == 0) {
01463                 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH);
01464                 break;
01465             }
01466 
01467             if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timer &&
01468                 cur->thread_info->announcement_info->announce_success) {
01469                 // Attachment to announce failed we return to previous channel
01470                 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
01471 
01472                 if (linkConfiguration) {
01473                     linkConfiguration->rfChannel = cur->thread_info->announcement_info->channel;
01474                     linkConfiguration->channel_page = cur->thread_info->announcement_info->channel_page;
01475                     linkConfiguration->panId = cur->thread_info->announcement_info->panid;
01476                     thread_joiner_application_link_configuration_store(cur->id, linkConfiguration);
01477                 } else {
01478                     tr_error("No link configuration!");
01479                 }
01480                 //set announce success flag to false because attach to new channel failed
01481                 cur->thread_info->announcement_info->announce_success = false;
01482                 thread_bootstrap_attach_start(interface_id, THREAD_NORMAL_ATTACH);
01483 
01484                 break;
01485             }
01486 
01487             if (cur->thread_info->thread_device_mode  == THREAD_DEVICE_MODE_ROUTER){
01488                 if (!thread_router_bootstrap_routing_allowed(cur)) {
01489                     thread_discovery_responser_enable(cur->id, false);
01490                     thread_bootstrap_orphan_scan_start(cur);
01491                 } else {
01492                     thread_bootstrap_generate_leader_and_link(cur);
01493                 }
01494             }
01495             else {
01496                 thread_bootstrap_orphan_scan_start(cur);
01497             }
01498             break;
01499 
01500         case CON_ERROR_NO_THREAD_NETWORK_AVAILABLE:
01501             thread_bootsrap_network_discovery_failure(interface_id);
01502             break;
01503         case CON_ERROR_PARTITION_MERGE:
01504             thread_bootstrap_attach_start(interface_id, THREAD_PARTITION_MERGE);
01505             break;
01506         case CON_ERROR_NETWORK_REATTACH:
01507             thread_bootstrap_attach_start(interface_id, THREAD_REATTACH);
01508             break;
01509         case CON_ERROR_NEIGHBOR_UNREACHABLE:
01510 
01511             break;
01512         case CON_ERROR_NETWORK_KICK:
01513             thread_bootstrap_reset_restart(interface_id);
01514             break;
01515     }
01516 }
01517 
01518 void thread_interface_up(protocol_interface_info_entry_t *cur)
01519 {
01520     thread_interface_init(cur);
01521     thread_interface_bootsrap_mode_init(cur);
01522     cur->nwk_nd_re_scan_count = 0;
01523 }
01524 
01525 int thread_bootstrap_reset(protocol_interface_info_entry_t *cur)
01526 {
01527     if (!cur || !cur->thread_info || (cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
01528         return -1;
01529     }
01530 
01531     if (cur->thread_info->thread_endnode_parent) {
01532         ns_dyn_mem_free(cur->thread_info->thread_endnode_parent);
01533         cur->thread_info->thread_endnode_parent = NULL;
01534     }
01535 
01536     neighbor_cache_flush(&cur->neigh_cache);
01537     thread_bootstrap_stop(cur);
01538 #ifndef NO_MLE
01539     mle_class_list_clean(cur->id);
01540 #endif
01541     cur->bootsrap_state_machine_cnt = 0;
01542     mac_helper_free_scan_confirm(&cur->mac_parameters->nwk_scan_params);
01543     //tr_debug( "--> idle");
01544     cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
01545     rpl_control_remove_domain_from_interface(cur);
01546     protocol_core_interface_info_reset(cur);
01547     mac_data_poll_disable(cur);
01548 
01549     //Prepare start Again
01550 
01551     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ACTIVE; //Set Active Bootsrap
01552     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY; //Clear Bind
01553     protocol_6lowpan_interface_common_init(cur);
01554     addr_interface_set_ll64(cur, NULL);
01555     thread_interface_up(cur);
01556 
01557     cur->nwk_mode = ARM_NWK_GP_IP_MODE;
01558     cur->nwk_bootstrap_state = ER_ACTIVE_SCAN;
01559     cur->nwk_nd_re_scan_count = 0;
01560     if(cur->thread_info->thread_attached_state != THREAD_STATE_REATTACH_RETRY) {
01561         cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
01562     }
01563     cur->ipv6_neighbour_cache.send_nud_probes = false; //Disable NUD probing
01564     cur->ip_multicast_as_mac_unicast_to_parent = true;
01565     //Define Default Contexts
01566     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
01567         nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
01568     }
01569     thread_anycast_address_policy_update(cur->thread_info, true);
01570     thread_bootstrap_state_machine(cur);
01571     return 0;
01572 }
01573 
01574 void thread_generate_ml64_address(protocol_interface_info_entry_t *cur)
01575 {
01576     if_address_entry_t *def_address = NULL;
01577     uint8_t ula[16];
01578     memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01579     //GENERATE ML-EID64
01580     memcpy(&ula[8], cur->iid_slaac , 8);
01581     def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true);
01582     if (def_address) {
01583         tr_debug("Generated UL64: %s", trace_ipv6(ula));
01584     }
01585 }
01586 
01587 void thread_delete_ml64_address(protocol_interface_info_entry_t *cur)
01588 {
01589     uint8_t ula[16];
01590     memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01591     memcpy(&ula[8], cur->iid_slaac, 8);
01592     addr_delete(cur, ula);
01593 
01594 }
01595 
01596 void thread_generate_ml16_address(protocol_interface_info_entry_t *cur)
01597 {
01598     if_address_entry_t *def_address = NULL;
01599     uint8_t ula[16];
01600     uint16_t euid16 = mac_helper_mac16_address_get(cur);
01601     if (euid16 == 0xffff) { // Safe guard
01602         tr_debug("Do NOT generate ML16, mac16=%u", euid16);
01603         return;
01604     }
01605     //GENERATE ML-16
01606     memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01607     memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6);
01608     common_write_16_bit(euid16, &ula[14]);
01609 
01610     def_address = addr_add(cur, ula, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true);
01611     if (def_address) {
01612         tr_debug("Generated ML16: %s", trace_ipv6(ula));
01613         cur->global_address_available = true;
01614     }
01615 }
01616 
01617 void thread_delete_ml16_addresses(protocol_interface_info_entry_t *cur)
01618 {
01619     uint8_t ula[16] = {0};
01620     memcpy(ula, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01621     memcpy(&ula[8], ADDR_SHORT_ADR_SUFFIC, 6);
01622     addr_delete_matching(cur, ula, 112, ADDR_SOURCE_UNKNOWN);
01623 }
01624 
01625 void thread_bootstrap_update_ml16_address(protocol_interface_info_entry_t *cur, uint16_t mac16)
01626 {
01627     thread_delete_ml16_addresses(cur);
01628     mac_helper_mac16_address_set(cur, mac16);
01629     thread_generate_ml16_address(cur);
01630     thread_router_bootstrap_anycast_address_register(cur);
01631 }
01632 static void thread_meshlocal_route_set(protocol_interface_info_entry_t *cur)
01633 {
01634     cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
01635     if (ipv6_route_add(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 64, cur->id, NULL, ROUTE_THREAD, 0xffffffff, 0) == NULL) {
01636         tr_error("fail to add route");
01637     }
01638 }
01639 
01640 void thread_bootstrap_attached_ready(protocol_interface_info_entry_t *cur)
01641 {
01642     thread_bootsrap_event_trig(THREAD_ATTACH_READY, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01643 }
01644 
01645 void thread_bootstrap_attached_downgrade_router(protocol_interface_info_entry_t *cur)
01646 {
01647     thread_bootsrap_event_trig(THREAD_ATTACH_DOWNGRADE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01648 }
01649 
01650 void thread_bootstrap_attched_upgrade_reed(protocol_interface_info_entry_t *cur)
01651 {
01652     thread_bootsrap_event_trig(THREAD_ATTACH_UPGRADE_REED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01653 }
01654 
01655 void thread_bootstrap_attached_active_router(protocol_interface_info_entry_t *cur)
01656 {
01657     thread_bootsrap_event_trig(THREAD_ATTACH_ACTIVE_ROUTER, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01658 }
01659 
01660 void thread_bootstrap_router_id_release_ready(protocol_interface_info_entry_t *cur)
01661 {
01662     thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_RELEASED, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01663 }
01664 
01665 void thread_bootstrap_router_id_get_fail(protocol_interface_info_entry_t *cur)
01666 {
01667     thread_bootsrap_event_trig(THREAD_ATTACH_ROUTER_ID_GET_FAIL, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01668 }
01669 
01670 int8_t thread_bootstrap_child_id_request(protocol_interface_info_entry_t *cur)
01671 {
01672     return thread_bootsrap_event_trig(THREAD_CHILD_ID_REQUEST, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
01673 }
01674 
01675 void thread_bootstrap_routing_activate(protocol_interface_info_entry_t *cur)
01676 {
01677     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE ||
01678             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
01679         thread_meshlocal_route_set(cur);
01680         thread_extension_route_set(cur);
01681         // FEDs and routers (REEDs) perform their own address resolution
01682         thread_nd_service_activate(cur->id);
01683     } else {
01684         thread_child_set_default_route(cur);
01685     }
01686 }
01687 
01688 void thread_bootstrap_attached_finish(protocol_interface_info_entry_t *cur)
01689 {
01690     cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY;
01691     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
01692     cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
01693     cur->bootsrap_state_machine_cnt = 10;
01694     cur->thread_info->routerIdReqCoapID = 0;
01695     cur->thread_info->networkDataRequested = false;
01696     clear_power_state(ICMP_ACTIVE);
01697 
01698     //Free scanned Result
01699     if (cur->thread_info->thread_attach_scanned_parent) {
01700         mle_service_msg_free(cur->thread_info->thread_attach_scanned_parent->child_id_request_id);
01701         ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent);
01702         cur->thread_info->thread_attach_scanned_parent = NULL;
01703     }
01704 
01705     // Make local/nwk data check after 5s
01706     thread_border_router_resubmit_timer_set(cur->id, 5);
01707     //Generate UL16
01708     thread_generate_ml16_address(cur);
01709     //GENERATE ML-EID64
01710     thread_generate_ml64_address(cur);
01711     // Generate new domain address
01712     thread_extension_address_generate(cur);
01713     thread_bootstrap_routing_activate(cur);
01714     thread_bootstrap_network_data_update(cur);
01715     // After successful attach if there is announcement info present, send announcement back to previous channel
01716     if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->announce_success == false) {
01717         cur->thread_info->announcement_info->timer = eventOS_timeout_ms(thread_announce_success_cb,20000, cur);
01718     }
01719     thread_configuration_mle_activate(cur);
01720 
01721     if (cur->thread_info->releaseRouterId) {
01722         thread_router_bootstrap_router_id_release(cur);
01723     }
01724     uint8_t *parent_mac_addr = NULL;
01725     if (cur->thread_info->thread_endnode_parent) {
01726         parent_mac_addr = cur->thread_info->thread_endnode_parent->mac64;
01727     }
01728     thread_nvm_store_link_info_write(parent_mac_addr, mac_helper_mac16_address_get(cur));
01729     thread_bootstrap_ready(cur);
01730 
01731     if(thread_is_router_addr(mac_helper_mac16_address_get(cur))) {
01732         // Attached as router Trigger routter attach
01733         tr_info("Attaching directly to router");
01734         thread_bootstrap_attached_active_router(cur);
01735     }
01736 }
01737 
01738 //This function is for Thread Parent scan callback
01739 bool thread_network_data_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
01740 {
01741     protocol_interface_info_entry_t *cur;
01742     (void)msgId;
01743 
01744     cur = protocol_stack_interface_info_get_by_id(interface_id);
01745     if (!cur || !cur->thread_info) {
01746         return false;
01747     }
01748 
01749     /* If network data is not received, send again */
01750     if(thread_info(cur)->networkDataRequested && !usedAllRetries){
01751         return true;
01752     }
01753 
01754     thread_info(cur)->networkDataRequested = false;
01755     mac_data_poll_protocol_poll_mode_decrement(cur);
01756     return false;
01757 }
01758 
01759 
01760 bool thread_tlv_request(int8_t interface_id, uint8_t *address, bool delayed_message, uint8_t *req_tlv, uint8_t req_len)
01761 {
01762     mle_message_timeout_params_t timeout;
01763     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01764     uint16_t buf_id;
01765 
01766     buf_id = mle_service_msg_allocate(interface_id, 32 + 20 + thread_leader_data_tlv_size(cur), false,MLE_COMMAND_DATA_REQUEST);
01767 
01768     if (!cur || buf_id == 0) {
01769         return false;
01770     }
01771 
01772     uint8_t *ptr = mle_service_get_data_pointer(buf_id);
01773     ptr = mle_tlv_req_tlv(ptr, req_tlv, req_len);
01774 
01775     //SET Leader Data
01776     ptr = thread_leader_data_tlv_write(ptr, cur);
01777 
01778     ptr = thread_active_timestamp_write(cur, ptr);
01779 
01780     ptr = thread_pending_timestamp_write(cur, ptr);
01781 
01782     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
01783         tr_debug("Buffer overflow at message write");
01784     }
01785     timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT;
01786     timeout.timeout_init = 1;
01787     timeout.timeout_max = 3;
01788     if (delayed_message) {
01789         timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
01790     } else {
01791         timeout.delay = MLE_NO_DELAY;
01792     }
01793     mac_data_poll_init_protocol_poll(cur);
01794     mle_service_set_packet_callback(buf_id, thread_network_data_timeout);
01795     mle_service_set_msg_destination_address(buf_id, address);
01796     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
01797     //Set Security
01798     uint32_t keySequence;
01799     thread_management_get_current_keysequence(cur->id, &keySequence);
01800     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
01801     mle_service_send_message(buf_id);
01802     return true;
01803 }
01804 
01805 void thread_bootstrap_parent_network_data_request(protocol_interface_info_entry_t *cur, bool delay_request)
01806 {
01807     uint8_t dst_address[16];
01808     memcpy(dst_address, ADDR_LINK_LOCAL_PREFIX, 8);
01809     memcpy(&dst_address[8], thread_info(cur)->thread_endnode_parent->mac64, 8);
01810     dst_address[8] ^= 2;
01811     thread_network_data_request_send(cur, dst_address, delay_request);
01812 }
01813 
01814 void thread_parent_scan(protocol_interface_info_entry_t *cur)
01815 {
01816     cur->thread_info->thread_attached_state = THREAD_STATE_NETWORK_DISCOVER;
01817     cur->nwk_nd_re_scan_count = 0;
01818     cur->nwk_bootstrap_state = ER_SCAN;
01819     cur->bootsrap_state_machine_cnt = randLIB_get_random_in_range(5, 15);
01820     nwk_thread_host_control(cur, NET_HOST_RX_ON_IDLE, 0);
01821 }
01822 
01823 void thread_bootstrap_joiner_application_commission_done_cb(int8_t interface_id)
01824 {
01825     protocol_interface_info_entry_t *interface;
01826     interface = protocol_stack_interface_info_get_by_id(interface_id);
01827     if (!interface) {
01828         return;
01829     }
01830     tr_debug("Commission Ready trig bootsrap to starting from init again");
01831     interface->nwk_bootstrap_state = ER_ACTIVE_SCAN;
01832     interface->bootsrap_state_machine_cnt = randLIB_get_random_in_range(1, 4);
01833 }
01834 
01835 static int compare_steering_and_joiner_bloom(uint8_t *steering_bloom, uint8_t *joiner_bloom, uint8_t steering_tlv_length)
01836 {
01837     //make sure s bit is not checked
01838     int loop_iterator;
01839     tr_debug("joiner bloom : %s", trace_array(joiner_bloom, steering_tlv_length));
01840     tr_debug("steering bloom : %s", trace_array(steering_bloom, steering_tlv_length));
01841     for (loop_iterator = 0; loop_iterator < steering_tlv_length; loop_iterator++)
01842     {
01843         if ((joiner_bloom[loop_iterator] != (joiner_bloom[loop_iterator] & steering_bloom[loop_iterator])))
01844         {
01845             thci_trace("joinerDiscoveryFailedFiltered");
01846             return 0;
01847         }
01848     }
01849     return 1;
01850 }
01851 
01852 static bool thread_route_possible_add(thread_attach_device_mode_e threadMode)
01853 {
01854     bool addRoute;
01855     if (threadMode == THREAD_DEVICE_MODE_ROUTER ||
01856         threadMode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
01857         addRoute = true;
01858     } else {
01859         addRoute = false;
01860     }
01861 
01862     return addRoute;
01863 }
01864 
01865 static void thread_dhcp_client_gua_error_cb(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status)
01866 {
01867     if (register_status) {
01868         tr_debug("Get Address %s From %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr));
01869     } else {
01870         tr_warn("Address Get fail: %s from: %s", trace_ipv6(prefix), trace_ipv6(dhcp_addr));
01871         if (prefix && dhcp_addr) {
01872             tr_debug("Delete Current Server data");
01873             thread_dhcp_client_global_address_delete(interface, dhcp_addr, prefix);
01874             //TODO shuold we try again or select new Server
01875         }
01876     }
01877 }
01878 
01879 static bool thread_dhcpv6_address_valid(uint8_t *prefixPtr, if_address_list_t *list)
01880 {
01881     bool addressReady = false;
01882     ns_list_foreach(if_address_entry_t, entry, list) {
01883         if (memcmp(entry->address, prefixPtr, 8) == 0) {
01884             addressReady = true;
01885             break;
01886         }
01887     }
01888     return addressReady;
01889 }
01890 
01891 static int thread_bloom_and_compare(uint8_t *steering_data_ptr,uint8_t steering_data_length,uint8_t *eui64, uint8_t eui64_length)
01892 {
01893     if (steering_data_length == 0 || steering_data_length > 16) {
01894         return 0;
01895     }
01896 
01897     uint8_t joiner_bloom_calculated[16] = {0};
01898     uint8_t mac_extended_address[8];
01899 
01900     ns_sha256_nbits(eui64, eui64_length, mac_extended_address, 64);
01901     mac_extended_address[0] |= 2; //local administered bit is set
01902 
01903     thread_beacon_calculate_bloom_filter(joiner_bloom_calculated,steering_data_length,mac_extended_address,8);
01904 
01905     return compare_steering_and_joiner_bloom(steering_data_ptr, joiner_bloom_calculated,steering_data_length);
01906 }
01907 
01908 static void thread_network_select_by_steering_data(device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response)
01909 {
01910     ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) {
01911 
01912         if (!thread_bloom_and_compare(cur_class->steering_data, cur_class->steering_data_valid, device_configuration_ptr->eui64,8) ) {
01913             ns_list_remove(discover_response, cur_class);
01914             ns_dyn_mem_free(cur_class);
01915         }
01916 
01917     }
01918 }
01919 
01920 static void thread_network_select(struct protocol_interface_info_entry *interface_ptr, device_configuration_s *device_configuration_ptr, thread_nwk_discovery_response_list_t *discover_response)
01921 {
01922     (void) interface_ptr;
01923 
01924     discovery_response_list_t *discovered_network_ptr = thread_extension_bootstrap_network_select(interface_ptr, discover_response);
01925 
01926     /* If network found */
01927     if (discovered_network_ptr) {
01928         /* Clear other networks from list */
01929         ns_list_foreach_safe(discovery_response_list_t, cur_class, discover_response) {
01930             if (cur_class != discovered_network_ptr) {
01931                 ns_list_remove(discover_response, cur_class);
01932                 ns_dyn_mem_free(cur_class);
01933             }
01934         }
01935     } else {
01936         thread_network_select_by_steering_data(device_configuration_ptr, discover_response);
01937     }
01938 }
01939 
01940 void thread_bootsrap_discovery_ready_cb(struct protocol_interface_info_entry *cur_interface, thread_nwk_discovery_response_list_t *discover_response)
01941 {
01942     device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id);
01943     if (!device_configuration_ptr) {
01944         tr_error("Mac scan confirm:Unknow Interface");
01945         thci_trace("joinerDiscoveryFailedNoBeacon");
01946         return;
01947     }
01948 
01949     thread_network_select(cur_interface, device_configuration_ptr, discover_response);
01950 
01951     if (!ns_list_count(discover_response)) {
01952         tr_debug("NO network available for scan");
01953         thci_trace("joinerDiscoveryFailedNoBeacon");
01954         goto exit_failure;
01955     }
01956 
01957     cur_interface->nwk_bootstrap_state = ER_ACTIVE_SCAN;
01958     cur_interface->bootsrap_state_machine_cnt = 1;
01959     return;
01960 
01961 
01962 
01963 exit_failure:
01964 
01965      thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL);
01966 }
01967 
01968 static void thread_bootstrap_create_unsecure_link_to_parent(protocol_interface_info_entry_t *interface, discovery_response_list_t *nwk_info)
01969 {
01970     mlme_start_t start_req;
01971     memset(&start_req, 0, sizeof(mlme_start_t));
01972 
01973     mac_helper_coordinator_address_set(interface, ADDR_802_15_4_LONG , nwk_info->extented_mac);
01974 
01975     interface->mac_parameters->pan_id = nwk_info->pan_id;
01976     interface->mac_parameters->mac_channel = nwk_info->channel;
01977 
01978     start_req.PANId = nwk_info->pan_id;
01979     start_req.LogicalChannel = nwk_info->channel;
01980     start_req.ChannelPage = 0;
01981     start_req.BeaconOrder = 0x0f;
01982     start_req.SuperframeOrder = 0x0f;
01983     //SET Beacon Payload
01984     mac_helper_beacon_payload_reallocate(interface, 0);
01985     interface->mac_api->mlme_req(interface->mac_api, MLME_START, (void*)&start_req);
01986     mac_data_poll_init(interface);
01987     mac_helper_mac16_address_set(interface, 0xffff);
01988     tr_debug("Mac Ready");
01989 }
01990 
01991 void thread_discover_native_commissioner_response(protocol_interface_info_entry_t *interface, thread_nwk_discovery_response_list_t *nwk_info)
01992 {
01993     thread_commissioning_link_configuration_s *config_ptr;
01994     int n = 0;
01995     if (ns_list_count(nwk_info) == 0) {
01996         tr_debug("Thread discover:No nwk");
01997         goto exit_failure;
01998     }
01999 
02000     // create list of available networks for native commissioner interface
02001     config_ptr = ns_dyn_mem_alloc(sizeof(thread_commissioning_link_configuration_s) * ns_list_count(nwk_info));
02002     if(!config_ptr) {
02003         tr_debug("Mac scan confirm:out of resources");
02004         goto exit_failure;
02005     }
02006 
02007     ns_list_foreach(discovery_response_list_t, cur_class, nwk_info) {
02008         config_ptr[n].panId = cur_class->pan_id;
02009         config_ptr[n].Protocol_id = THREAD_PROTOCOL_ID;
02010         config_ptr[n].version = THREAD_PROTOCOL_VERSION;
02011         config_ptr[n].rfChannel = cur_class->channel;
02012         memcpy(config_ptr[n].name, cur_class->network_name, 16);
02013         memcpy(config_ptr[n].extented_pan_id, cur_class->extented_pan_id, 8);
02014         n++;
02015     }
02016 
02017     if(interface->thread_info->native_commissioner_cb) {
02018         interface->thread_info->native_commissioner_cb(interface->id,n,config_ptr);
02019     }
02020     ns_dyn_mem_free(config_ptr);
02021 
02022     if(!interface->thread_info->native_commissioner_link) {
02023         tr_debug("Mac scan confirm:continue scanning");
02024         goto exit_failure;
02025     }
02026     //Free if not matching network found
02027     ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) {
02028         if(cur_class->version != THREAD_PROTOCOL_VERSION ||
02029                 cur_class->pan_id != interface->thread_info->native_commissioner_link->panId ||
02030                 memcmp(interface->thread_info->native_commissioner_link->name,cur_class->network_name,16) != 0  ||
02031                 memcmp(interface->thread_info->native_commissioner_link->extented_pan_id,cur_class->extented_pan_id,8) != 0 ) {
02032 
02033             ns_list_remove(nwk_info, cur_class);
02034             ns_dyn_mem_free(cur_class);
02035 
02036         }
02037     }
02038 
02039     if(ns_list_is_empty(nwk_info)) {
02040         tr_debug("Mac scan confirm:no networks available");
02041         goto exit_failure;
02042     }
02043     //select best parent link
02044     discovery_response_list_t *best = NULL;
02045 
02046     ns_list_foreach_safe(discovery_response_list_t, cur_class, nwk_info) {
02047         ns_list_remove(nwk_info, cur_class);
02048         if (!best || (best && best->dbm < cur_class->dbm)) {
02049             if (best) {
02050                 ns_dyn_mem_free(cur_class);
02051             }
02052             best = cur_class;
02053         } else {
02054             ns_dyn_mem_free(cur_class);
02055         }
02056     }
02057 
02058     // best is always not null, because the not empty check above
02059     /* coverity[FORWARD_NULL] */
02060     interface->thread_info->native_commissioner_port = best->commissioner_port;
02061     thread_bootstrap_create_unsecure_link_to_parent(interface, best);
02062     ns_dyn_mem_free(best);
02063 
02064     /**
02065      *  we should stop scanning and saying that the interface is up
02066      */
02067     tr_debug("Native commissioning interface ready");
02068     interface->thread_info->thread_attached_state = THREAD_STATE_CONNECTED;
02069     interface->nwk_bootstrap_state = ER_MLE_ATTACH_READY;
02070     interface->lowpan_info |= INTERFACE_NWK_BOOTSRAP_ADDRESS_REGISTER_READY;
02071     interface->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
02072 
02073     interface->thread_info->routerIdReqCoapID = 0;
02074     interface->thread_info->networkDataRequested = false;
02075 
02076     interface->bootsrap_state_machine_cnt = 10;
02077 
02078     clear_power_state(ICMP_ACTIVE);
02079     thread_bootstrap_ready(interface);
02080     return;
02081 
02082 
02083 
02084 exit_failure:
02085 
02086     thread_bootstrap_connection_error(interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL);
02087 }
02088 
02089 
02090 
02091 static void thread_bootsrap_network_join_start(struct protocol_interface_info_entry *cur_interface, discovery_response_list_t *nwk_info)
02092 {
02093     device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(cur_interface->id);
02094 
02095     uint8_t parent_ll_addr[16];
02096     memcpy(parent_ll_addr, ADDR_LINK_LOCAL_PREFIX, 8);
02097     memcpy(parent_ll_addr + 8, nwk_info->extented_mac, 8);
02098     parent_ll_addr[8] ^= 2;
02099 
02100     if (!device_configuration_ptr || blacklist_reject(parent_ll_addr)) {
02101         ns_dyn_mem_free(nwk_info);
02102         thci_trace("joinerDiscoveryFailedNoBeacon");
02103         thread_bootstrap_connection_error(cur_interface->id, CON_ERROR_NO_THREAD_NETWORK_AVAILABLE, NULL);
02104         return;
02105     }
02106 
02107     uint8_t private_mac[8];
02108     ns_sha256_nbits(device_configuration_ptr->eui64, 8, private_mac, 64);
02109     private_mac[0] |= 2; //local administered bit is set
02110 
02111     tr_debug("joiner mac id : %s", trace_array(private_mac, 8));
02112     mac_helper_mac64_set(cur_interface, private_mac);
02113 
02114     thread_set_link_local_address(cur_interface); // only to generate IID
02115 
02116     thread_bootstrap_create_unsecure_link_to_parent(cur_interface, nwk_info);
02117 
02118     thci_trace("joinerDiscoverySuccess");
02119     uint8_t parentLLAddress[16];
02120     protocol_6lowpan_interface_get_link_local_cordinator_address(cur_interface, parentLLAddress);
02121     tr_debug("Start commission with %s", trace_ipv6(parentLLAddress));
02122     cur_interface->bootsrap_state_machine_cnt = 0;
02123 
02124     if (0 > thread_extension_bootstrap_commission_start(cur_interface, parentLLAddress, nwk_info, thread_bootstrap_joiner_application_commission_done_cb)) {
02125         thread_joiner_application_pskd_commission_start(cur_interface->id, parentLLAddress, nwk_info->joiner_port, nwk_info->pan_id, nwk_info->extented_pan_id, nwk_info->channel, thread_bootstrap_joiner_application_commission_done_cb);
02126     }
02127     ns_dyn_mem_free(nwk_info);
02128 
02129 }
02130 
02131 void thread_bootsrap_device_synch_fail(protocol_interface_info_entry_t *cur)
02132 {
02133     tr_debug("Link Synch Fail -->Parent Scan Start");
02134     thread_bootstrap_clear_neighbor_entries(cur);
02135     thread_network_synch_data_free(cur->id);
02136     thread_delete_ml64_address(cur);
02137     thread_parent_scan(cur);
02138 }
02139 
02140 bool thread_device_synch_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
02141 {
02142     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
02143     (void)msgId;
02144     if (!interface) {
02145         return false;
02146     }
02147 
02148     if (usedAllRetries) {
02149         thread_bootsrap_device_synch_fail(interface);
02150         return false;
02151     }
02152 
02153     return true;
02154 }
02155 
02156 bool thread_link_request_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
02157 {
02158     protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(interface_id);
02159 
02160     if (!interface) {
02161         return false;
02162     }
02163 
02164     if (usedAllRetries) {
02165         uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId);
02166         tr_debug("Link Request timed out, address: %s", trace_ipv6(addr));
02167         blacklist_update(addr, false);
02168         return false;
02169     }
02170 
02171     return true;
02172 }
02173 static bool thread_bootstrap_sync_after_reset_start(protocol_interface_info_entry_t *cur)
02174 {
02175     uint16_t my_short_address;
02176     uint8_t parent_mac64[8];
02177 
02178     int link_info_err = thread_nvm_store_link_info_get(parent_mac64, &my_short_address);
02179     if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) {
02180         tr_warning("thread_nvm_store_link_info_get returned %d", link_info_err);
02181         return false;
02182     }
02183     link_info_err = thread_nvm_store_link_info_clear();
02184     if ( link_info_err!= THREAD_NVM_FILE_SUCCESS) {
02185         tr_warning("thread_nvm_store_link_info_clear returned %d", link_info_err);
02186         }
02187     if (thread_is_router_addr(my_short_address)) {
02188         thread_info(cur)->routerShortAddress = my_short_address;
02189         thread_dynamic_storage_build_mle_table(cur->id);
02190         thread_router_bootstrap_link_synch_start(cur);
02191         return true;
02192     }
02193     if (!thread_parent_data_allocate(cur->thread_info)) {
02194         tr_info("parent alloc failed");
02195         return false;
02196     }
02197 
02198     cur->thread_info->thread_endnode_parent->shortAddress = 0xfffe;
02199     memcpy(cur->thread_info->thread_endnode_parent->mac64,parent_mac64,8);
02200     thread_endevice_synch_start(cur);
02201     return true;
02202 }
02203 void thread_bootstrap_start_network_discovery(protocol_interface_info_entry_t *cur)
02204 {
02205     thread_discover_reques_t scan_request;
02206     thread_discovery_ready_cb *discover_ready;
02207     cur->nwk_nd_re_scan_count++;
02208     cur->mac_parameters->nwk_scan_params.stack_chan_list = cur->mac_parameters->mac_channel_list;
02209 
02210 
02211     if(cur->thread_info->native_commissioner_cb) {
02212         tr_debug("native commissioner network scan start");
02213 
02214         discover_ready = thread_discover_native_commissioner_response;
02215         scan_request.joiner_flag = false;
02216         scan_request.native_commisioner = true;
02217     } else {
02218         discovery_response_list_t *thread_network = thread_discovery_network_description_get(cur->id);
02219         if (thread_network) {
02220             thread_bootsrap_network_join_start(cur, thread_network);
02221             return;
02222         }
02223 
02224         tr_debug("scan networks for joining application");
02225         thci_trace("joinerDiscoveryStarted");
02226 
02227         blacklist_params_set(
02228                 THREAD_COMM_BLACKLIST_ENTRY_LIFETIME,
02229                 THREAD_COMM_BLACKLIST_TIMER_MAX_TIMEOUT,
02230                 THREAD_COMM_BLACKLIST_TIMER_TIMEOUT,
02231                 THREAD_BLACKLIST_ENTRY_MAX_NBR,
02232                 THREAD_BLACKLIST_PURGE_NBR,
02233                 THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT);
02234 
02235         scan_request.native_commisioner = false;
02236         scan_request.joiner_flag = true;
02237 
02238         discover_ready = thread_bootsrap_discovery_ready_cb;
02239     }
02240 
02241     scan_request.channel_mask = cur->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0];
02242     scan_request.filter_tlv_data = NULL;
02243     scan_request.filter_tlv_length = 0;
02244     if (thread_discovery_network_scan(cur->id, &scan_request, discover_ready) != 0 ) {
02245         tr_error("Discovery scan start fail");
02246     }
02247 }
02248 void thread_bootstrap_state_machine(protocol_interface_info_entry_t *cur)
02249 {
02250     link_configuration_s *linkConfiguration;
02251 
02252     switch (cur->nwk_bootstrap_state) {
02253         case ER_ACTIVE_SCAN:
02254             tr_debug("Thread SM:Active Scan");
02255 
02256             thread_joiner_application_nvm_link_configuration_load(cur->id);
02257             linkConfiguration = thread_joiner_application_get_config(cur->id);
02258             if (!linkConfiguration) {
02259                 thread_bootstrap_start_network_discovery(cur);
02260                 return;
02261             }
02262 
02263             //SET Link by Static configuration
02264             tr_info("thread network attach start");
02265             if (thread_mle_service_register(cur->id,thread_joiner_application_random_mac_get(cur->id)) != 0 ||
02266                 thread_link_configuration_activate(cur, linkConfiguration) != 0) {
02267                 tr_error("Network Bootsrap Start Fail");
02268                 bootsrap_next_state_kick(ER_BOOTSTRAP_SCAN_FAIL, cur);
02269                 return;
02270             }
02271             if (thread_bootstrap_sync_after_reset_start(cur)) {
02272                 // Link syncronisation started
02273                 tr_debug("link synchronisation start");
02274                 return;
02275             }
02276             tr_debug("Parent Scan Start");
02277             thread_parent_scan(cur);
02278             break;
02279 
02280         case ER_SCAN:
02281             tr_debug("Thread SM:Start ER Scan");
02282             cur->nwk_nd_re_scan_count = 0;
02283             thread_network_attach_start(cur);
02284             break;
02285 
02286         case ER_MLE_ATTACH_READY:
02287         case ER_MLE_SYNCH:
02288         case ER_MLE_SCAN:
02289         case ER_CHILD_ID_REQ:
02290             tr_debug("Thread SM:Attach Ready");
02291             break;
02292 
02293         case ER_BOOTSRAP_DONE:
02294             tr_debug("Thread SM:Bootstrap Done");
02295             cur->nwk_nd_re_scan_count = 0;
02296             break;
02297         case ER_BOOTSTRAP_SCAN_FAIL:
02298             tr_debug("Thread SM:Scan Failed");
02299             nwk_bootsrap_state_update(ARM_NWK_NWK_SCAN_FAIL, cur);
02300             break;
02301 
02302         case ER_BOOTSTRAP_LEADER_UP:
02303             tr_debug("Thread SM:Leader Start");
02304             thread_leader_service_thread_partitition_generate(cur->id, false);
02305             break;
02306 
02307         case ER_BOOTSTRAP_NEW_FRAGMENT_START:
02308             tr_debug("Thread SM:Create New fragment");
02309             thread_leader_service_thread_partitition_generate(cur->id, true);
02310             break;
02311 
02312         default:
02313             tr_warn("Thread SM:Invalid state");
02314 
02315     }
02316 }
02317 void thread_bootstrap_stop(protocol_interface_info_entry_t *cur)
02318 {
02319     thread_address_registration_deinit();
02320     thread_anycast_address_policy_update(cur->thread_info, false);
02321     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD, NULL);
02322     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
02323     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
02324     thread_leader_service_leader_data_free(cur->thread_info);
02325     thread_bootstrap_all_nodes_multicast_unregister(cur);
02326     thread_data_base_init(cur->thread_info, cur->id);
02327     thread_dhcp_client_delete(cur->id);
02328     thread_nd_service_delete(cur->id);
02329     thread_child_id_request_entry_clean(cur);
02330     thread_registered_mcast_addr_entry_clean(cur);
02331     cur->mesh_callbacks = NULL;
02332 }
02333 
02334 void thread_bootstrap_child_update_trig(protocol_interface_info_entry_t *cur)
02335 {
02336     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
02337         if (cur->thread_info->thread_endnode_parent == NULL) {
02338             return;
02339         }
02340 
02341         if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
02342             //Set Pending if earlier proces is already started
02343             cur->thread_info->thread_endnode_parent->childUpdatePending = true;
02344             return;
02345         }
02346         //Trig event
02347         cur->thread_info->thread_endnode_parent->childUpdatePending = false;
02348         cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
02349         cur->thread_info->thread_endnode_parent->childUpdateProcessStatus = false;
02350 
02351         thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
02352     }
02353 }
02354 static void thread_border_router_locator_copy(protocol_interface_info_entry_t *cur,thread_commissioner_t *registered_commissioner , uint8_t *data)
02355 {
02356     memcpy(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
02357     memcpy(&registered_commissioner->border_router_address[8], ADDR_SHORT_ADR_SUFFIC, 6);
02358     memcpy(&registered_commissioner->border_router_address[14], data, 2);
02359 }
02360 /* \return -1 Failed
02361  *          0 OK, data not changed
02362  *          1 OK, data changed */
02363 static int thread_commission_data_tlv_parse(protocol_interface_info_entry_t *cur, uint8_t type, uint8_t length, uint8_t *data)
02364 {
02365     thread_commissioner_t *registered_commissioner = &cur->thread_info->registered_commissioner;
02366 
02367     switch (type) {
02368         // This is set by leader
02369         case THREAD_TLV_COMMISSIONER_SESSION_ID:
02370             if (length != 2) {
02371                 return -1;
02372             }
02373             if(registered_commissioner->session_id != common_read_16_bit(data)){
02374                 registered_commissioner->session_id = common_read_16_bit(data);
02375                 return 1;
02376             }
02377             break;
02378 
02379         case THREAD_TLV_STEERING_DATA:
02380             if (length > 16) {
02381                 return -1;
02382             }
02383             if(registered_commissioner->steering_data_len != length || memcmp(registered_commissioner->steering_data, data, length)){
02384                 memcpy(registered_commissioner->steering_data, data, length);
02385                 registered_commissioner->steering_data_len = length;
02386                 return 1;
02387             }
02388             break;
02389 
02390         case THREAD_TLV_BORDER_ROUTER_LOCATOR:
02391             if (length != 2) {
02392                 return -1;
02393             }
02394 
02395             registered_commissioner->commissioner_valid = true;
02396             if (!registered_commissioner->commissioner_valid ||
02397                 memcmp(&registered_commissioner->border_router_address[14], data, 2) ||
02398                 memcmp(registered_commissioner->border_router_address, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8)) {
02399                 thread_border_router_locator_copy(cur,registered_commissioner, data );
02400                 return 1;
02401             }
02402             break;
02403 
02404         default:
02405             break;
02406 
02407     }
02408     return 0;
02409 }
02410 static int thread_nd_prefix_context_allocate(protocol_interface_info_entry_t *cur, thread_prefix_tlv_t *prefixTlv, bool stableData)
02411 {
02412     thread_network_local_data_context_entry_t context;
02413     uint8_t cid;
02414     //check possible context id or current allocated
02415     cid = thread_nd_context_id_allocate(&cur->thread_info->networkDataStorage, &cur->thread_info->localServerDataBase, prefixTlv->Prefix, prefixTlv->PrefixLen);
02416     if (cid == 16) {
02417         return -1;
02418     }
02419     context.cid = cid;
02420     context.compression = true;
02421     context.stableData = stableData;
02422     context.contextPrefixLength = prefixTlv->PrefixLen;
02423     if (lowpan_context_update(&cur->lowpan_contexts, cid, 0xffff, prefixTlv->Prefix, prefixTlv->PrefixLen, stableData) != 0) {
02424         return -1;
02425     }
02426 
02427     if (thread_nd_local_list_add_contexts(&cur->thread_info->networkDataStorage, prefixTlv, &context) != 0) {
02428         //Free context if allocation fail
02429         lowpan_context_update(&cur->lowpan_contexts, cid, 0, prefixTlv->Prefix,  prefixTlv->PrefixLen, stableData);
02430         return -1;
02431     }
02432 
02433     return 0;
02434 }
02435 
02436 int thread_bootstrap_network_data_process(protocol_interface_info_entry_t *cur, uint8_t *network_data_ptr, uint16_t network_data_length)
02437 {
02438     int ret_val = 0;
02439     uint8_t addr[16];
02440     uint8_t *dptr;
02441     uint16_t length, data_length, flags;
02442     uint8_t prefix_bytes_len, subLength, preference;
02443     uint8_t type;
02444     bool stableData;
02445     bool update_data = false;
02446     thread_prefix_tlv_t prefixTlv;
02447     thread_network_local_data_context_entry_t context;
02448     thread_border_router_tlv_entry_t genericService;
02449     thread_network_data_cache_entry_t *networkDataStorage = &cur->thread_info->networkDataStorage;
02450 
02451     link_configuration_s *linkConfiguration  = thread_joiner_application_get_config(cur->id);
02452     if (!linkConfiguration) {
02453         return -1;
02454     }
02455 
02456     data_length = network_data_length;
02457     dptr = network_data_ptr;
02458     tr_debug("Start Parsing TLV one by One");
02459     while (data_length) {
02460         tr_debug("Main TLV: %s", trace_array(dptr, data_length));
02461 
02462         prefixTlv.Prefix = NULL;
02463         prefixTlv.PrefixLen = 0;
02464 
02465         type = *dptr++;
02466         if (type & THREAD_NWK_STABLE_DATA) {
02467             stableData = true;
02468         } else {
02469             stableData = false;
02470         }
02471 
02472         type &= THREAD_NWK_DATA_TYPE_MASK;
02473         length = *dptr++;
02474         if ((length + 2) > data_length) {
02475             return -1;
02476         }
02477 
02478         //SET Pointer & Length ready for next check
02479         data_length -= (length + 2);
02480         if (!stableData && !cur->thread_info->requestFullNetworkData) {
02481             //Skip unstable data when it not requsted
02482             dptr += length;
02483         } else if (type == THREAD_NWK_DATA_TYPE_PREFIX) {
02484             prefixTlv.domainId = *dptr++;
02485             prefixTlv.PrefixLen = *dptr++;
02486             //Decrement length by prefix length
02487             length -= 2;
02488             prefixTlv.Prefix = dptr;
02489             prefix_bytes_len = prefixBits_to_bytes(prefixTlv.PrefixLen);
02490 
02491             if (prefix_bytes_len > length) {
02492                 return -1;
02493             }
02494             length -= prefix_bytes_len;
02495             dptr += prefix_bytes_len;
02496             tr_debug("Prefix: %s", trace_ipv6_prefix(prefixTlv.Prefix, prefixTlv.PrefixLen));
02497 
02498             if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) {
02499 
02500                 while (length > 2) {
02501                     type = *dptr++;
02502                     subLength = *dptr++;
02503                     length -= 2;
02504                     if (type & THREAD_NWK_STABLE_DATA) {
02505                         stableData = true;
02506                     } else {
02507                         stableData = false;
02508                     }
02509                     type &= THREAD_NWK_DATA_TYPE_MASK;
02510 
02511                     tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength));
02512 
02513                     if (subLength <=  length) {
02514                         length -= subLength;
02515                         if (type == THREAD_NWK_DATA_TYPE_6LOWPAN_ID) {
02516                             while (subLength) {
02517                                 if (*dptr & THREAD_NWK_CONTEXT_COMPRESS_ENABLED) {
02518                                     context.compression = true;
02519                                 } else {
02520                                     context.compression = false;
02521                                 }
02522 
02523                                 context.cid = (*dptr++ & 0x0f);
02524                                 context.contextPrefixLength = *dptr++;
02525                                 context.stableData = stableData;
02526                                 subLength -= 2;
02527 
02528                                 if (thread_nd_verify_contex_id_is_free(networkDataStorage, prefixTlv.Prefix, &context) == 0) {
02529                                     thread_nd_local_list_add_contexts(networkDataStorage, &prefixTlv, &context);
02530 
02531                                 } else {
02532                                     tr_debug("CID reserved already");
02533                                 }
02534                             }
02535                         } else {
02536 
02537                             while (subLength) {
02538                                 genericService.routerID = common_read_16_bit(dptr);
02539                                 dptr += 2;
02540                                 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) {
02541                                     flags = common_read_16_bit(dptr);
02542                                     dptr += 2;
02543                                     subLength -= THREAD_BORDER_ROUTER_TLV_LENGTH;
02544                                     genericService.Prf = ((flags >> THREAD_PRF_BIT_MOVE) & 3);
02545                                 } else {
02546                                     /* HAS_ROUTE */
02547                                     preference = *dptr++;
02548                                     subLength -= THREAD_HAS_ROUTE_TLV_LENGTH;
02549                                     genericService.Prf = ((preference >> THREAD_HAS_ROUTE_PRF_BIT_MOVE) & 3);
02550                                 }
02551 
02552                                 genericService.stableData = stableData;
02553 
02554                                 if (type == THREAD_NWK_DATA_TYPE_BORDER_ROUTER) {
02555                                     genericService.P_configure = ((flags >> THREAD_P_CONFIGURE_BIT_MOVE) & 1);
02556                                     genericService.P_default_route = ((flags >> THREAD_P_DEF_ROUTE_BIT_MOVE) & 1);
02557                                     genericService.P_dhcp = ((flags >> THREAD_P_DHCP_BIT_MOVE) & 1);
02558                                     genericService.P_preferred = ((flags >> THREAD_P_PREFERRED_BIT_MOVE) & 1);
02559                                     genericService.P_slaac = ((flags >> THREAD_P_SLAAC_BIT_MOVE) & 1);
02560                                     genericService.P_on_mesh = ((flags >> THREAD_P_ON_MESH_BIT_MOVE) & 1);
02561                                     genericService.P_nd_dns = ((flags >> THREAD_P_ND_DNS_BIT_MOVE) & 1);
02562                                     if (thread_nd_local_list_add_on_mesh_prefix(networkDataStorage, &prefixTlv, &genericService) == 0) {
02563                                         if (networkDataStorage->stableUpdatePushed || networkDataStorage->temporaryUpdatePushed) {
02564                                             if (!genericService.P_slaac) {
02565                                                 //Delete Address by this Entry
02566                                                 tr_debug("Delete SLAAC address because not valid.");
02567                                                 addr_delete_matching(cur, prefixTlv.Prefix, 64, ADDR_SOURCE_SLAAC);
02568                                             } else {
02569                                                 ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
02570                                                     if (e->source == ADDR_SOURCE_SLAAC &&
02571                                                             bitsequal(e->address, prefixTlv.Prefix, 64)) {
02572                                                         if (genericService.P_preferred) {
02573                                                             tr_debug("SLAAC address set as preferred.");
02574                                                         } else {
02575                                                             tr_debug("SLAAC address set as NOT preferred.");
02576                                                         }
02577                                                         addr_set_preferred_lifetime(cur, e, genericService.P_preferred ? 0xfffffffff: 0);
02578                                                     }
02579                                                 }
02580                                             }
02581 
02582                                             if (!genericService.P_dhcp) {
02583                                                 //Delete DHCPv6 client
02584                                                 memcpy(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
02585                                                 memcpy(&addr[8], ADDR_SHORT_ADR_SUFFIC, 6);
02586                                                 common_write_16_bit(genericService.routerID, &addr[14]);
02587                                                 thread_dhcp_client_global_address_delete(cur->id, addr, prefixTlv.Prefix);
02588                                                 tr_debug("Delete DHCPv6 given address");
02589                                             }
02590                                         }
02591 
02592 
02593                                         //Allocate Context
02594                                         if (cur->thread_info->leader_private_data) {
02595                                             if (thread_nd_prefix_context_allocate(cur, &prefixTlv, stableData) != 0) {
02596                                                 //Mark Delete for this setup if context allocate fail
02597                                                 thread_nd_local_list_del_on_mesh_server(networkDataStorage, &prefixTlv, &genericService);
02598                                             }
02599                                         }
02600                                     }
02601                                 } else if (type == THREAD_NWK_DATA_TYPE_ROUTE) {
02602                                     if (genericService.routerID < 0xfffe) {
02603                                         thread_nd_local_list_add_route(networkDataStorage, &prefixTlv, &genericService);
02604                                         tr_debug("added route");
02605                                     }
02606                                 }
02607                             }
02608                         }
02609                     } else {
02610                         tr_debug("SERVER Parse fail");
02611                         break;
02612                     }
02613                 }
02614             } else {
02615                 tr_debug("Malform Prefix sub TLV");
02616                 dptr += length;
02617             }
02618 
02619         } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && stableData) {
02620             if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) {
02621                 tr_debug("Stable Commisssion TLV: %i", length);
02622                 // Stable commissioning data has the Timestamps and is not processed here
02623             } else {
02624                 tr_debug("Malformed stable Commisssion TLV: %i", length);
02625             }
02626             dptr += length;
02627 
02628         } else if (type == THREAD_NWK_DATA_TYPE_COMMISSION_DATA && !stableData) {
02629             if (thread_network_data_sub_tlv_malformed_check(dptr, length) == 0) {
02630                 int data_changed;
02631                 tr_debug("Unstable Commisssion TLV: %i", length);
02632                 // in thread 1.1 unstable has only commissioner information
02633                 cur->thread_info->registered_commissioner.commissioner_valid = false;
02634                 while (length > 2) {
02635                     type = *dptr++;
02636                     subLength = *dptr++;
02637                     length -= 2;
02638                     tr_debug("SubType: %02x, %s", type, trace_array(dptr, subLength));
02639 
02640                     if (subLength <= length) {
02641                         length -= subLength;
02642 
02643                         data_changed = thread_commission_data_tlv_parse(cur, type, subLength, dptr);
02644                         if (data_changed < 0)
02645                             tr_debug("Fail");
02646                         else {
02647                             if (data_changed == 1) {
02648                                 update_data = true;
02649                                 tr_debug("Changed");
02650                             } else {
02651                                 tr_debug("OK");
02652                             }
02653                         }
02654                         dptr += subLength;
02655                     } else {
02656                         tr_debug("SERVER Parse fail");
02657                         break;
02658                     }
02659                 }
02660             } else {
02661                 tr_debug("Malformed unstable Commisssion TLV: %i", length);
02662                 dptr += length;
02663             }
02664         } else if (type == THREAD_NWK_DATA_TYPE_SERVICE_DATA) {
02665             thread_network_data_service_entry_t service_entry;
02666 
02667             service_entry.T = (*dptr) >> 7;
02668             service_entry.S_id = (*dptr++) & 0x0f;
02669             service_entry.S_stable = stableData;
02670 
02671             if (!service_entry.T) {
02672                 service_entry.S_enterprise_number = common_read_32_bit(dptr);
02673                 dptr += 4;
02674                 length -= 4;
02675             } else {
02676                 service_entry.S_enterprise_number = THREAD_ENTERPRISE_NUMBER;
02677             }
02678 
02679             service_entry.S_service_data_length = *dptr++;
02680             service_entry.S_service_data = dptr;
02681             dptr += service_entry.S_service_data_length;
02682 
02683             tr_debug("Service data: %s, enterprise number: %"PRIu32, trace_array(service_entry.S_service_data,
02684                 service_entry.S_service_data_length), service_entry.S_enterprise_number);
02685 
02686             length -= 2 + service_entry.S_service_data_length;
02687 
02688             while (length > 2) {
02689                 type = *dptr++;
02690                 subLength = *dptr++;
02691                 length -= 2;
02692 
02693                 if (subLength <= length) {
02694                     tr_debug("SubType: %02x, length: %d, data: %s", type, length, trace_array(dptr, subLength));
02695 
02696                     length -= subLength;
02697 
02698                     thread_network_data_service_server_entry_t server = {0};
02699 
02700                     if (type & THREAD_NWK_STABLE_DATA) {
02701                         server.stable = true;
02702                     }
02703 
02704                     server.router_id = common_read_16_bit(dptr);
02705                     subLength -= 2;
02706                     dptr += 2;
02707 
02708                     server.server_data = dptr;
02709                     server.server_data_length = subLength;
02710                     tr_debug("Router ID: %04x, Server data: %s", server.router_id, trace_array(server.server_data, server.server_data_length));
02711 
02712                     thread_nd_local_list_add_service(networkDataStorage, &service_entry, &server);
02713                     dptr += subLength;
02714                 } else {
02715                     tr_debug("Server sub-TLV parse fail!");
02716                     return -1;
02717                 }
02718             }
02719         } else {
02720             return -1;
02721         }
02722     }
02723 
02724     if (update_data) {
02725         ret_val = 1;
02726     }
02727     return ret_val;
02728 }
02729 
02730 int thread_bootstrap_network_data_activate(protocol_interface_info_entry_t *cur)
02731 {
02732     //Mark old data to be be freed
02733     thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false);
02734 
02735     int retVal = thread_bootstrap_network_data_process(cur, cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len);
02736 
02737     if (retVal < 0) {
02738         tr_warn("network data update failed: %s", trace_array(cur->thread_info->networkDataStorage.network_data, cur->thread_info->networkDataStorage.network_data_len));
02739         return retVal;
02740     }
02741 
02742     // delete marked data
02743     if (thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur) ) {
02744         thread_bootstrap_child_update_trig(cur);
02745     }
02746 
02747     // Learn the routes and dhcp addresses from prefixes
02748     thread_bootstrap_network_prefixes_process(cur);
02749     //Add new anycast addressess learned from network data.
02750     thread_router_bootstrap_anycast_address_register(cur);
02751     // Update joiner router status
02752     thread_management_server_joiner_router_init(cur->id);
02753     thread_extension_joiner_router_init(cur->id);
02754 
02755     // Update border router relay
02756     thread_bbr_commissioner_proxy_service_update(cur->id);
02757     // update beacons
02758     thread_beacon_create_payload(cur);
02759 
02760     // Indicate network data change to other modules
02761     thread_extension_network_data_process(cur);
02762     thread_border_router_network_data_update_notify(cur);
02763     thread_bbr_network_data_update_notify(cur);
02764 
02765     return 0;
02766 }
02767 
02768 int thread_bootstrap_network_data_save(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint8_t* network_data_ptr, uint16_t network_data_len)
02769 {
02770     if (!cur || !cur->thread_info || !leader_data || network_data_len > THREAD_MAX_NETWORK_DATA_SIZE) {
02771         tr_warn("Network data saving failed");
02772         return -1;
02773     }
02774 
02775     if (thread_attach_ready(cur) != 0) {
02776         return -2;
02777     }
02778 
02779     if (thread_network_data_malformed_check(network_data_ptr, network_data_len) != 0) {
02780         tr_warn("Malformed nw data: %s", trace_array(network_data_ptr, network_data_len));
02781         return -3;
02782     }
02783 
02784     // Do not process the network data until we are synchronized
02785     tr_debug("learn new network data");
02786 
02787     if (thread_info(cur)->thread_leader_data->stableDataVersion != leader_data->stableDataVersion) {
02788         thread_info(cur)->thread_leader_data->stableDataVersion = leader_data->stableDataVersion;
02789         cur->thread_info->networkDataStorage.stableUpdatePushed = true;
02790     }
02791     if (thread_info(cur)->thread_leader_data->dataVersion != leader_data->dataVersion) {
02792         thread_info(cur)->thread_leader_data->dataVersion = leader_data->dataVersion;
02793         cur->thread_info->networkDataStorage.temporaryUpdatePushed = true;
02794     }
02795     if ((network_data_len!=cur->thread_info->networkDataStorage.network_data_len ||
02796             memcmp(cur->thread_info->networkDataStorage.network_data,network_data_ptr,network_data_len) != 0)){
02797         // Network data was changed so at least it will be unstable change
02798         cur->thread_info->networkDataStorage.temporaryUpdatePushed = true;
02799         tr_debug("Network data changed; size %d stable:%d, unstable:%d", network_data_len, cur->thread_info->networkDataStorage.stableUpdatePushed,cur->thread_info->networkDataStorage.temporaryUpdatePushed);
02800         memcpy(cur->thread_info->networkDataStorage.network_data, network_data_ptr,network_data_len);
02801         cur->thread_info->networkDataStorage.network_data_len = network_data_len;
02802     }
02803 
02804     return 0;
02805 }
02806 
02807 
02808 void thread_bootstrap_network_prefixes_process(protocol_interface_info_entry_t *cur)
02809 {
02810     // Route prefix is variable-length, so need to zero pad for ip6tos
02811     uint8_t addr[16];
02812     bool validToLearnRoutes, validToLearOnMeshRoute;
02813     thread_network_server_data_entry_t *weHostService = NULL;
02814     uint16_t routerId;
02815     tr_debug("Network Data:");
02816     routerId = cur->mac_parameters->mac_short_address;
02817     thread_network_data_cache_entry_t *networkData;
02818     networkData = &cur->thread_info->networkDataStorage;
02819     validToLearnRoutes = thread_route_possible_add(cur->thread_info->thread_device_mode);
02820     validToLearOnMeshRoute = thread_on_mesh_route_possible_add(cur->thread_info->thread_device_mode);
02821 
02822     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_BORDER_ROUTER, NULL);
02823 
02824     ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &networkData->localPrefixList ) {
02825         weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->routeList);
02826         tr_debug("Local ServicePrefix: %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen));
02827 
02828         if (!weHostService && validToLearnRoutes) {
02829             ns_list_foreach(thread_network_server_data_entry_t, curRouteItem, &curPrefix->routeList) {
02830                 thread_addr_write_mesh_local_16(addr, curRouteItem->routerID, cur->thread_info);
02831                 tr_debug("Add new route via: %s", trace_ipv6(addr));
02832                 ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curRouteItem->Prf);
02833             }
02834         }
02835 
02836         weHostService = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->borderRouterList);
02837         if(weHostService) {
02838             tr_debug( "I'm Hosting BR");
02839         }
02840 
02841         ns_list_foreach(thread_network_server_data_entry_t, curBorderRouter, &curPrefix->borderRouterList) {
02842             //Set Default route ::/0
02843             if (curBorderRouter->P_default_route) {
02844                 if (!(weHostService && weHostService->P_default_route) && validToLearnRoutes) {
02845                     thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
02846                     tr_debug("Add default route via: %s", trace_ipv6(addr));
02847                     ipv6_route_add(NULL, 0, cur->id, addr, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf);
02848                 }
02849             }
02850             ipv6_stack_route_advert_update(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, RA_PRF_LOW);
02851 
02852             if (thread_nd_on_mesh_address_valid(curBorderRouter)) {
02853                 if (validToLearOnMeshRoute) {
02854                     if (curBorderRouter->P_dhcp && weHostService && nd_proxy_enabled_for_upstream(cur->id) && nd_proxy_upstream_route_onlink(cur->id,curPrefix->servicesPrefix)) {
02855                         // don't add
02856                         tr_debug("Suppressing onlink %s for proxy", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen));
02857                     } else {
02858                         //add
02859                         tr_debug("Adding onlink %s", trace_ipv6_prefix(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen));
02860                         ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD_BORDER_ROUTER, 0xffffffff, curBorderRouter->Prf);
02861                     }
02862                 }
02863             }
02864 
02865             if (curBorderRouter->P_dhcp) {
02866                 /* All end device types perform BR RLOC16 -> ALOC16
02867                    replacement if stable network data was requested. */
02868                 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST ||
02869                     cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) &&
02870                     cur->thread_info->requestFullNetworkData == false) {
02871                     ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) {
02872                         curBorderRouter->routerID = 0xfc00;
02873                         curBorderRouter->routerID |= curRoute->cid;
02874                         tr_debug("Replaced router ID with ALOC16: %04x", curBorderRouter->routerID);
02875                     }
02876                 }
02877 
02878                 if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
02879                     thread_addr_write_mesh_local_16(addr, curBorderRouter->routerID, cur->thread_info);
02880 
02881                     if (thread_dhcp_client_get_global_address(cur->id, addr, curPrefix->servicesPrefix, cur->mac, thread_dhcp_client_gua_error_cb) == 0) {
02882                         tr_debug("GP Address Requested");
02883                     }
02884                 }
02885 
02886             } else {
02887                 /* All end device types perform RLOC16 -> 0xfffe
02888                    replacement if stable network data was requested. */
02889                 if ((cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST ||
02890                     cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) &&
02891                     cur->thread_info->requestFullNetworkData == false) {
02892                     curBorderRouter->routerID = 0xfffe;
02893                     tr_debug("Invalidated router ID: %04x", curBorderRouter->routerID);
02894                 }
02895             }
02896 
02897             if (curBorderRouter->P_preferred) {
02898                 if (!thread_dhcpv6_address_valid(curPrefix->servicesPrefix, &cur->ip_addresses)) {
02899                     icmpv6_slaac_address_add(cur, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, 0xffffffff, 0xffffffff, true, SLAAC_IID_DEFAULT);
02900                 }
02901             }
02902 
02903         } // for each borderRouterList
02904 
02905         ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) {
02906             uint8_t flags;
02907             flags = curRoute->cid;
02908             if (curRoute->compression) {
02909                 flags |= 0x10;
02910             }
02911 
02912             lowpan_context_update(&cur->lowpan_contexts, flags , 0xFFFF, curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, curRoute->stableData);
02913         }
02914     } // for each localPrefixList
02915 }
02916 
02917 void thread_bootstrap_network_data_update(protocol_interface_info_entry_t *cur)
02918 {
02919     if (!cur || !cur->thread_info) {
02920         return;
02921     }
02922 
02923     if (cur->thread_info->networkDataStorage.stableUpdatePushed) {
02924         tr_debug("Stable Network Data Update");
02925     } else if (cur->thread_info->networkDataStorage.temporaryUpdatePushed) {
02926         tr_debug("Temporary Network Data Update");
02927     } else {
02928         // No changes in network data detected so no processing done
02929         return;
02930     }
02931     tr_info("Network data updated");
02932     thread_bootstrap_network_data_activate(cur);
02933     thread_router_bootstrap_network_data_distribute(cur);
02934 
02935     cur->thread_info->networkDataStorage.stableUpdatePushed = false;
02936     cur->thread_info->networkDataStorage.temporaryUpdatePushed = false;
02937 }
02938 
02939 void thread_bootstrap_clear_neighbor_entries(protocol_interface_info_entry_t *cur)
02940 {
02941     if (cur == NULL || cur->thread_info == NULL) {
02942         return;
02943     }
02944 
02945     // Remove registered entries in the IP neighbor cache
02946     ns_list_foreach_safe(ipv6_neighbour_t, neighbour, &cur->ipv6_neighbour_cache.list) {
02947         if (neighbour->type == IP_NEIGHBOUR_REGISTERED) {
02948             ipv6_neighbour_entry_remove(&cur->ipv6_neighbour_cache, neighbour);
02949         }
02950     }
02951 
02952     mle_class_list_clean(cur->id);
02953 }
02954 
02955 void thread_bootstrap_dynamic_configuration_save(protocol_interface_info_entry_t *cur)
02956 {
02957     uint32_t mac_frame_counter;
02958     if (!cur->thread_info) {
02959         return;
02960     }
02961 
02962     if (thread_i_am_router(cur)) {
02963         /* Store information of our children to the dynamic storage */
02964         mle_neigh_table_list_t *neig_list = mle_class_active_list_get(cur->id);
02965         ns_list_foreach_safe(mle_neigh_table_entry_t, entry, neig_list) {
02966             if (thread_addr_is_child(mac_helper_mac16_address_get(cur), entry->short_adr)) {
02967                 thread_dynamic_storage_child_info_store(cur->id, entry);
02968             }
02969         }
02970     }
02971     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
02972     mac_helper_link_frame_counter_read(cur->id, &mac_frame_counter);
02973     // in error situation this returns 0 !!!!
02974     uint32_t mle_frame_counter = mle_service_security_get_frame_counter(cur->id);
02975     if (linkConfiguration) {
02976             thread_nvm_store_fast_data_check_and_write(mac_frame_counter, mle_frame_counter, linkConfiguration->key_sequence);
02977     }
02978     else {
02979         thread_nvm_store_frame_counters_check_and_write(mac_frame_counter, mle_frame_counter);
02980     }
02981 }
02982 
02983 bool thread_bootstrap_link_create_check(protocol_interface_info_entry_t *interface, uint16_t short_address)
02984 {
02985     if (interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE ||
02986             interface->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE) {
02987         // MED's never make any links so return false
02988         return false;
02989     }
02990 
02991     if(mle_class_free_entry_count_get(interface->id) < 1) {
02992         // We dont have room for any new links
02993         tr_warn("Link ignore no room for addr:%x", short_address);
02994         return false;
02995     }
02996     // TODO should check that we have enough room left for children
02997     // TODO Need to drop links for bad routers if no room
02998 
02999     if (interface->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
03000         //routers always make links
03001         return true;
03002     }
03003 
03004     if (thread_is_router_addr(short_address) == false) {
03005         //incoming advertisement is not from router so return false
03006         return false;
03007     }
03008 
03009     if (mle_class_active_neigh_counter(interface->id) < THREAD_REED_AND_END_DEVICE_NEIGHBOR_LINKS + 1) {
03010         return true;
03011     }
03012 
03013     return false;
03014 }
03015 
03016 bool thread_bootstrap_link_create_allowed(protocol_interface_info_entry_t *interface, uint16_t short_address, const uint8_t *src_addr)
03017 {
03018 #ifndef HAVE_DEBUG
03019     (void) short_address;
03020 #endif
03021     // Add blacklist of routers that newer answer to us
03022     if(mle_service_interface_tx_queue_size(interface->id) > THREAD_MAX_PARALLEL_MLE_LINK_REQUEST) {
03023         // Maximum parallel link requests
03024         tr_warn("Link ignore too many req addr:%x", short_address);
03025         return false;
03026     }
03027 
03028     if (blacklist_reject(src_addr)) {
03029         return false;
03030     }
03031 
03032     return true;
03033 }
03034 
03035 bool thread_bootstrap_should_register_address(protocol_interface_info_entry_t *cur)
03036 {
03037     // If we are a MTD, send requests to register addresses
03038     // Neither REEDs nor FEDs need to register their addresses
03039     uint8_t mode = thread_mode_get_by_interface_ptr(cur);
03040     return (mode & MLE_DEV_MASK) == MLE_RFD_DEV;
03041 }
03042 
03043 #endif