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