takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_bootstrap.c Source File

thread_bootstrap.c

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