Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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