EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_bootstrap.c Source File

thread_bootstrap.c

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