takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_host_bootstrap.c Source File

thread_host_bootstrap.c

00001 /*
00002  * Copyright (c) 2015-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * \file thread_host_bootstrap.c
00032  * \brief Add short description about this file!!!
00033  *
00034  */
00035 
00036 #include "nsconfig.h"
00037 #ifdef HAVE_THREAD
00038 #include <string.h>
00039 #include <ns_types.h>
00040 #include <nsdynmemLIB.h>
00041 #include "eventOS_event.h"
00042 #include "eventOS_event_timer.h"
00043 #include "shalib.h"
00044 #include "common_functions.h"
00045 #include "NWK_INTERFACE/Include/protocol.h"
00046 #include "net_thread_test.h"
00047 #include "ns_trace.h"
00048 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00049 #include "6LoWPAN/Thread/thread_common.h"
00050 #include "6LoWPAN/Thread/thread_routing.h"
00051 #include "6LoWPAN/Thread/thread_nd.h"
00052 #include "6LoWPAN/Thread/thread_network_synch.h"
00053 #include "6LoWPAN/Thread/thread_bootstrap.h"
00054 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00055 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00056 #include "6LoWPAN/Thread/thread_leader_service.h"
00057 #include "6LoWPAN/Thread/thread_management_internal.h"
00058 #include "6LoWPAN/Thread/thread_network_synch.h"
00059 #include "6LoWPAN/Thread/thread_lowpower_private_api.h"
00060 #include "6LoWPAN/Thread/thread_extension.h"
00061 #include "6LoWPAN/Thread/thread_joiner_application.h"
00062 #include "6LoWPAN/Thread/thread_management_internal.h"
00063 #include "6LoWPAN/Thread/thread_management_client.h"
00064 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00065 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00066 #include "6LoWPAN/Thread/thread_neighbor_class.h"
00067 #include "thread_management_if.h"
00068 #include "Common_Protocols/ipv6.h"
00069 #include "MPL/mpl.h"
00070 #include "MLE/mle_tlv.h"
00071 #include "thread_config.h"
00072 #include "Service_Libs/mle_service/mle_service_api.h"
00073 #include "Service_Libs/blacklist/blacklist.h"
00074 #include "6LoWPAN/MAC/mac_helper.h"
00075 #include "6LoWPAN/MAC/mac_data_poll.h"
00076 #include "Core/include/address.h"
00077 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00078 
00079 #define TRACE_GROUP "tebs"
00080 
00081 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties);
00082 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
00083 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries);
00084 
00085 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
00086 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
00087 
00088 static int thread_parent_request_build(protocol_interface_info_entry_t *cur);
00089 
00090 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur);
00091 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader);
00092 
00093 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur);
00094 
00095 
00096 void thread_child_set_default_route(protocol_interface_info_entry_t *cur)
00097 {
00098     thread_parent_info_t *parent = cur->thread_info->thread_endnode_parent;
00099 
00100     if (!parent) {
00101         tr_debug("child default route set fail");
00102         return;
00103     }
00104     cur->lowpan_info &= ~INTERFACE_NWK_ROUTER_DEVICE;
00105     uint8_t ula[16];
00106     // SET Default route to ::/0
00107     memcpy(ula, ADDR_LINK_LOCAL_PREFIX, 8);
00108     memcpy(&ula[8], parent->mac64 , 8);
00109     ula[8] ^= 2;
00110     if (ipv6_route_add(NULL, 0, cur->id, ula, ROUTE_THREAD, 0xffffffff, 0) == NULL) {
00111         tr_error("fail to add default route");
00112     }
00113 }
00114 
00115 static void thread_network_data_clean(protocol_interface_info_entry_t *cur)
00116 {
00117     tr_debug("Clean network data");
00118     thread_network_data_router_id_mark_delete(&cur->thread_info->networkDataStorage, 0xffff, false);
00119     thread_network_data_router_id_free(&cur->thread_info->networkDataStorage, false, cur);
00120 }
00121 
00122 static void thread_merge_prepare(protocol_interface_info_entry_t *cur)
00123 {
00124     thread_clean_old_16_bit_address_based_addresses(cur);
00125     mpl_clear_realm_scope_seeds(cur);
00126     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_HOST, NULL);
00127     ipv6_route_table_remove_info(cur->id, ROUTE_THREAD_PROXIED_DUA_HOST, NULL);
00128     thread_partition_data_purge(cur);
00129     thread_network_data_clean(cur);
00130     cur->nwk_mode = ARM_NWK_GP_IP_MODE;
00131 }
00132 
00133 //This function is for Thread Parent scan callback
00134 static bool thread_parent_discover_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00135 {
00136     protocol_interface_info_entry_t *cur;
00137     bool new_entry_created;
00138 
00139     cur = protocol_stack_interface_info_get_by_id(interface_id);
00140     if (!cur) {
00141         return false;
00142     }
00143 
00144     cur->nwk_nd_re_scan_count++;
00145 
00146     tr_debug("Parse parent scan result");
00147     if (cur->thread_info->thread_attach_scanned_parent) {
00148         uint8_t ll64[16];
00149         thread_scanned_parent_t *parent = cur->thread_info->thread_attach_scanned_parent;
00150         link_configuration_s *linkConfiguration;
00151         mac_neighbor_table_entry_t *entry_temp;
00152 
00153         linkConfiguration = thread_joiner_application_get_config(interface_id);
00154         if (!linkConfiguration) {
00155             return false;
00156         }
00157 
00158         /* SED requires that scanned parent is added to MLE table */
00159         memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8);
00160         memcpy(&ll64[8], parent->mac64 , 8);
00161         ll64[8] ^= 2;
00162         entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, true, &new_entry_created);
00163         if (entry_temp == NULL) {
00164             return false;
00165         }
00166         thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , parent->linkMarginToParent, new_entry_created);
00167         thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00168 
00169         entry_temp->mac16  = parent->shortAddress;
00170         entry_temp->link_role  = PRIORITY_PARENT_NEIGHBOUR;
00171 
00172         mle_service_frame_counter_entry_add(interface_id, entry_temp->index , parent->mleFrameCounter);
00173 
00174         thread_management_key_sets_calc(cur, linkConfiguration, cur->thread_info->thread_attach_scanned_parent->keySequence);
00175         thread_key_guard_timer_calculate(cur, linkConfiguration, true);
00176 
00177         mlme_device_descriptor_t device_desc;
00178         mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 ,parent->linLayerFrameCounter, false);
00179         mac_helper_devicetable_set(&device_desc, cur,entry_temp->index , mac_helper_default_key_index_get(cur), new_entry_created);
00180         mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
00181 
00182         if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00183             nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 50);
00184         }
00185 
00186         tr_debug("Parent found, send child ID req");
00187         thread_attach_child_id_request_build(cur);
00188         return false;
00189 
00190     } else {
00191         uint8_t *dataPtr;
00192         uint16_t dataLength;
00193 
00194         if (usedAllRetries) {
00195             if (thread_is_connected(cur)) {
00196                 // Did not find any better partition to join. Be happy.
00197                 cur->nwk_bootstrap_state = ER_MLE_ATTACH_READY;
00198                 return true;
00199             }
00200             // Trig new state which call this
00201             thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL);
00202             return false;
00203         }
00204 
00205         //GET Data pointer
00206         dataPtr = mle_service_get_payload_start_point(msgId);
00207         dataLength = mle_service_get_payload_length(msgId);
00208 
00209         if (dataPtr) {
00210             mle_tlv_info_t tlv_info;
00211             //Scan MLE_TYPE_SCAN_MASK
00212             if (mle_tlv_option_discover(dataPtr, dataLength, MLE_TYPE_SCAN_MASK, &tlv_info)) {
00213                 dataPtr = tlv_info.dataPtr;
00214                 *dataPtr |= 0x40; //ADD REED Bit
00215             }
00216         }
00217     }
00218     return true;
00219 }
00220 
00221 static int thread_parent_request_build(protocol_interface_info_entry_t *cur)
00222 {
00223     uint8_t *ptr;
00224     uint8_t mode;
00225     mle_message_timeout_params_t timeout;
00226     uint32_t keySequence;
00227     uint8_t scanMask = 0x80;
00228 
00229     mle_service_interface_tx_queue_clean(cur->id);
00230 
00231     uint16_t buf_id = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_PARENT_REQUEST);
00232     if (buf_id == 0) {
00233         return -1;
00234     }
00235 
00236     timeout.retrans_max = THREAD_PARENT_REQUEST_MAX_RETRY_CNT;
00237     timeout.timeout_init = THREAD_PARENT_REQ_SCANMASK_R_TIMEOUT;
00238     timeout.timeout_max = THREAD_PARENT_REQ_SCANMASK_RE_TIMEOUT;
00239     timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00240 
00241     if (cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH ||
00242         cur->thread_info->thread_attached_state == THREAD_STATE_REATTACH_RETRY ||
00243         cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED ||
00244         cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
00245         // When doing re-attach End devices are immediately accepted as parents
00246         scanMask |= 0x40;
00247         timeout.timeout_init = THREAD_PARENT_REQ_SCANMASK_RE_TIMEOUT;
00248     }
00249 
00250     thread_management_get_current_keysequence(cur->id, &keySequence);
00251     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
00252 
00253     //SET Multicast to all Router ff02::2
00254     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_ROUTERS);
00255     tr_debug("Thread parent request");
00256 
00257     ptr = mle_service_get_data_pointer(buf_id);
00258     ptr = mle_tlv_write_scan_mask(ptr, scanMask);
00259     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00260     mode = thread_mode_get_by_interface_ptr(cur);
00261 
00262     /* If we are a SLEEPY host, we do NOT set RX_ON_IDLE bit in parent requests */
00263     /*   NOTE: the RX_ON_IDLE is temporarily set on the interface during bootstrap */
00264     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00265         mode &= ~MLE_RX_ON_IDLE;
00266     }
00267 
00268     ptr = mle_tlv_write_mode(ptr, mode);
00269     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
00270         tr_debug("Buffer overflow at message write");
00271     }
00272 
00273     cur->nwk_nd_re_scan_count = 1;
00274 
00275     mle_service_set_packet_callback(buf_id, thread_parent_discover_timeout_cb);
00276     if (cur->thread_info->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER) {
00277         mle_service_interface_receiver_handler_update(cur->id, thread_mle_parent_discover_receive_cb);
00278     } else {
00279         mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
00280     }
00281 
00282     mle_service_set_msg_timeout_parameters_fast(buf_id, &timeout);
00283     mle_service_send_message(buf_id);
00284     return 0;
00285 }
00286 
00287 void thread_network_attach_start(protocol_interface_info_entry_t *cur)
00288 {
00289     if (thread_parent_request_build(cur) == 0) {
00290         tr_debug("MLE Parent request");
00291         cur->nwk_bootstrap_state = ER_MLE_SCAN;
00292         cur->bootsrap_state_machine_cnt = 0;
00293         /* advance trickle timer by 6 (in 100ms ticks) seconds if needed */
00294         thread_routing_trickle_advance(&cur->thread_info->routing, 6*10);
00295     } else {
00296         cur->bootsrap_state_machine_cnt = 5;
00297     }
00298 }
00299 
00300 static int thread_end_device_synch_response_validate(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint16_t data_length, uint8_t linkMargin, uint8_t *src_address, mle_security_header_t *securityHeader)
00301 {
00302     uint8_t shortAddress[2];
00303     uint8_t status, mode;
00304     uint16_t srcAddress;
00305     uint16_t address16;
00306     uint32_t llFrameCounter;
00307     thread_leader_data_t leaderData;
00308     mac_neighbor_table_entry_t *entry_temp;
00309     bool new_entry_created;
00310 
00311     tr_debug("Validate Link Synch Response");
00312     //Check First Status
00313     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, ptr, data_length, &status)) {
00314         tr_debug("Synch status response %x",status);
00315         //Clean synch state and start
00316         return -1;
00317     }
00318     // Validate response
00319     // MLE_TYPE_MODE
00320     // Address
00321     // MLE_TYPE_SRC_ADDRESS
00322     // MLE_TYPE_LEADER_DATA
00323     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, ptr, data_length, &mode) ||
00324             !mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, &srcAddress) ||
00325             !mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, ptr, data_length, &address16) ||
00326             !thread_leader_data_parse(ptr, data_length, &leaderData) ||
00327             !mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, ptr, data_length, &llFrameCounter)) {
00328         tr_debug("missing TLV's");
00329         return -1;
00330     }
00331 
00332     if (securityHeader->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00333         thread_management_key_synch_req(cur->id, common_read_32_bit(securityHeader->Keysource));
00334         // if learning key sequence from link sync actual guard timer value is not known
00335         thread_key_guard_timer_reset(cur);
00336     } else {
00337         tr_debug("Key ID Mode 2 not used; dropped.");
00338         return -3;
00339     }
00340 
00341     //Update parent link information
00342     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), src_address, true, &new_entry_created);
00343 
00344     if (!entry_temp) {
00345         tr_debug("Neighbor allocate fail");
00346         return -2;
00347     }
00348     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, new_entry_created);
00349     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00350 /*
00351 
00352 */
00353     entry_temp->mac16  = srcAddress;
00354     entry_temp->connected_device  = 1;
00355     entry_temp->link_role  = PRIORITY_PARENT_NEIGHBOUR; // Make this our parent
00356     common_write_16_bit(entry_temp->mac16 , shortAddress);
00357 
00358     mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress);
00359     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, thread_info(cur)->host_link_timeout);
00360 
00361     mlme_device_descriptor_t device_desc;
00362     mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 ,llFrameCounter, false);
00363     mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , securityHeader->KeyIndex, new_entry_created);
00364 
00365     thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
00366     thread_bootstrap_update_ml16_address(cur, address16);
00367     //SET Parent Info and free scan response info
00368     thread_info(cur)->thread_endnode_parent->shortAddress = srcAddress;
00369     thread_info(cur)->thread_endnode_parent->router_id = srcAddress >> 10;
00370     memcpy(thread_info(cur)->thread_endnode_parent->mac64, entry_temp->mac64 , 8);
00371 
00372     mle_tlv_info_t routing;
00373     if (mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, &routing)) {
00374         thread_router_bootstrap_route_tlv_push(cur, routing.dataPtr, routing.tlvLen, linkMargin, entry_temp);
00375     }
00376 
00377     //Copy Leader Data
00378     *thread_info(cur)->thread_leader_data = leaderData;
00379 
00380     /*save the data version to one less than what was received so that any inconsistencies in network data is
00381      * fixed by a data request to parent
00382      */
00383     thread_info(cur)->thread_leader_data->stableDataVersion = leaderData.stableDataVersion - 1;
00384     thread_info(cur)->thread_leader_data->dataVersion = leaderData.dataVersion - 1;
00385 
00386 
00387     return 0;
00388 
00389 }
00390 
00391 static void thread_child_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00392 {
00393     (void) interface_id;
00394     tr_debug("Thread MLE message child_synch handler");
00395     //State machine What packet shuold accept in this case
00396     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
00397 
00398     /* Check that message is from link-local scope */
00399     if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00400         return;
00401     }
00402 
00403     uint16_t messageId;
00404     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
00405     //State machine What packet shuold accept in this case
00406     switch (mle_msg->message_type) {
00407     case MLE_COMMAND_CHILD_UPDATE_RESPONSE:
00408 
00409         messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00410 
00411         if (messageId == 0) {
00412             tr_debug("No matching challenge");
00413             return;
00414         }
00415 
00416         if (thread_end_device_synch_response_validate(cur, mle_msg->data_ptr, mle_msg->data_length, linkMargin, mle_msg->packet_src_address, security_headers) != 0) {
00417             tr_warn("End device synch failed");
00418             mle_service_msg_free(messageId);
00419             thread_bootsrap_device_synch_fail(cur);
00420             return;
00421         }
00422         mle_tlv_info_t networkDataTlv;
00423         thread_leader_data_t leaderData;
00424         tr_debug("End device synch Possible");
00425 
00426         cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED;
00427         // read network data, and leader data check. Send data request sent if pending set is not in sync
00428         if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv) &&
00429             thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) && thread_joiner_application_pending_delay_timer_in_sync(cur->id)) {
00430             thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00431         } else {
00432             thread_bootstrap_parent_network_data_request(cur, true);
00433         }
00434         thread_bootstrap_attached_ready(cur);
00435 
00436         //SET For sleepy state and mode update
00437         if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00438             nwk_thread_host_control(cur, NET_HOST_FAST_POLL_MODE, 1);
00439             //TRIG Child Update state
00440             thread_bootstrap_child_update_trig(cur);
00441         }
00442 
00443         mle_service_msg_free(messageId);
00444         break;
00445     }
00446 }
00447 
00448 static bool thread_host_prefer_parent_response(protocol_interface_info_entry_t *cur, thread_scanned_parent_t *scanned_parent, uint16_t version, thread_connectivity_t *connectivity)
00449 {
00450     (void) connectivity;
00451     (void) cur;
00452 
00453     if (!thread_extension_version_check(thread_info(cur)->version)) {
00454         return false;
00455     }
00456 
00457     if (version < scanned_parent->version) {
00458         tr_debug("prefer existing parent response from %"PRIX16, scanned_parent->shortAddress);
00459         return true;
00460     }
00461 
00462     return false;
00463 }
00464 
00465 /* MLE callback for parent response messages.
00466  *
00467  * The Parent Response contains these TLVs:
00468  * - Source Address TLV
00469  * - Leader Data TLV
00470  * - Link-layer Frame Counter TLV
00471  * - MLE Frame Counter TLV (optional)
00472  * - Response TLV
00473  * - Challenge TLV
00474  * - Link Margin TLV
00475  * - Connectivity TLV
00476  * - Version TLV
00477  */
00478 void thread_mle_parent_discover_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00479 {
00480     (void) interface_id;
00481     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
00482 
00483     /* Check that message is from link-local scope */
00484     if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00485         return;
00486     }
00487 
00488     tr_debug("MLE Parent response handler");
00489     //State machine What packet should accept in this case
00490     switch (mle_msg->message_type) {
00491         case MLE_COMMAND_PARENT_RESPONSE: {
00492             thread_scanned_parent_t *scan_result = NULL;
00493             uint16_t messageId;
00494             uint16_t srcAddress, version;
00495             uint32_t llFrameCounter;
00496             uint32_t mleFrameCounter;
00497             uint8_t rssiValue;
00498             mle_tlv_info_t challengeTlv;
00499             uint8_t currentMargin, newMargin;
00500             thread_link_quality_e newLqi;
00501             thread_leader_data_t leaderData;
00502             thread_connectivity_t connectivityTlv;
00503             bool accept_response;
00504 
00505             tr_info("Parent Response");
00506             if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) {
00507                 tr_debug("Wrong key mode %u ", security_headers->KeyIdMode);
00508                 return;
00509             }
00510             messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00511 
00512             if (messageId == 0) {
00513                 tr_debug("No matching challenge");
00514                 return;
00515             }
00516 
00517             //Read Leader Data and verify connectivity
00518             if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00519                 return;
00520             }
00521             if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &rssiValue)) {
00522                 return;
00523             }
00524             if (!thread_connectivity_tlv_parse(mle_msg->data_ptr, mle_msg->data_length, &connectivityTlv)) {
00525                 return;
00526             }
00527             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &srcAddress)) {
00528                 return;
00529             }
00530             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) {
00531                 return;
00532             }
00533             if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) {
00534                 return;
00535             }
00536             if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) {
00537                 return;
00538             }
00539             //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
00540             if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter)) {
00541                 mleFrameCounter = llFrameCounter;
00542             }
00543 
00544             /**
00545              * At THREAD_STATE_REATTACH state only accept same Partition ID and Higher ID than current
00546              */
00547             if (thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH || thread_info(cur)->thread_attached_state == THREAD_STATE_REATTACH_RETRY) {
00548                 tr_debug("Reattach");
00549                 if (thread_info(cur)->thread_leader_data) {
00550                     if (!thread_partition_match(cur, &leaderData)) {
00551                         //accept only same ID at reattach phase
00552                         return;
00553                     }
00554                     //Compare ID - when downgrading, accept all
00555                     if (!thread_info(cur)->releaseRouterId) {
00556                         if (!common_serial_number_greater_8(connectivityTlv.idSequence, thread_info(cur)->routing.router_id_sequence)) {
00557                             tr_debug("Drop old partition by old ID");
00558                             return;
00559                         } else {
00560                             tr_debug("Accept old partition by new ID");
00561                         }
00562                     }
00563                 }
00564             } else if (thread_info(cur)->thread_attached_state == THREAD_STATE_ATTACH_ANY ||
00565                     thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED ||
00566                     thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
00567                 if (thread_info(cur)->thread_leader_data) {
00568                     if (thread_partition_match(cur, &leaderData)) {
00569                         //accept only different ID at anyattach phase
00570                         tr_debug("Drop old partition");
00571                         return;
00572                     }
00573                 } else {
00574                     //TODO Fix this
00575                     tr_error("No leader Data allocated for AnyAttach,Why?");
00576                 }
00577             }
00578 
00579             if (blacklist_reject(mle_msg->packet_src_address)) {
00580                 tr_debug("Drop Parent Response because blacklisted");
00581                 return;
00582             }
00583 
00584             /* Calculate this parent link margin */
00585             newMargin = thread_calculate_link_margin(mle_msg->dbm, rssiValue);
00586             newLqi = thread_link_margin_to_quality(newMargin << THREAD_LINK_MARGIN_SCALING);
00587             tr_debug("Parent scan count %d addr:%04x Margin:%d  lqi:%d", cur->nwk_nd_re_scan_count, srcAddress, newMargin, newLqi);
00588             if (newLqi == QUALITY_BAD) {
00589                 tr_debug("Drop Bad Link");
00590                 accept_response = false;
00591             } else {
00592                 if (cur->nwk_nd_re_scan_count <= 1) {
00593                     if (newLqi == QUALITY_20dB) {
00594                         accept_response = true;
00595                     } else {
00596                         tr_debug("Drop first time less than QUALITY_20dB");
00597                         accept_response = false;
00598                     }
00599                 } else {
00600                     accept_response = true;
00601                 }
00602             }
00603 
00604             if (thread_extension_enabled(cur) &&
00605                 thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER &&
00606                 leaderData.weighting < thread_info(cur)->partition_weighting) {
00607                 // Only applies to extensions and only routers that can form new partitions can ignore lower weight
00608                 tr_debug("Drop parent due weighting %d<%d", leaderData.weighting, thread_info(cur)->partition_weighting);
00609                 return;
00610             }
00611 
00612             if (accept_response) {
00613                 if (thread_info(cur)->thread_attach_scanned_parent == NULL) {
00614                     thread_info(cur)->thread_attach_scanned_parent = ns_dyn_mem_temporary_alloc(sizeof(thread_scanned_parent_t));
00615                     if (!thread_info(cur)->thread_attach_scanned_parent) {
00616                         return;
00617                     }
00618                     thread_info(cur)->thread_attach_scanned_parent->child_id_request_id = 0;
00619                     scan_result = thread_info(cur)->thread_attach_scanned_parent;
00620                     tr_debug("Partition %"PRIu32, leaderData.partitionId);
00621                 } else {
00622                     uint32_t currentPartitionId = thread_info(cur)->thread_attach_scanned_parent->leader_data.partitionId;
00623                     uint8_t currentWeighting = thread_info(cur)->thread_attach_scanned_parent->leader_data.weighting;
00624                     tr_debug("Current partition %"PRIu32" old:%"PRIu32" weighting %"PRIu8" old:%"PRIu8,
00625                         currentPartitionId, leaderData.partitionId, currentWeighting, leaderData.weighting);
00626 
00627                     if ((leaderData.partitionId != currentPartitionId) ||
00628                         (leaderData.weighting != currentWeighting)) {
00629                         int retVal = thread_bootstrap_partition_process(cur, connectivityTlv.activeRouters, &leaderData,NULL);
00630                         if (retVal > 0) {
00631                             // New partition is Higher
00632                             scan_result = thread_info(cur)->thread_attach_scanned_parent;
00633                         }
00634                     }
00635                     else if (leaderData.partitionId == currentPartitionId) {
00636                         thread_link_quality_e currentLqi;
00637                         //Calculate Current summed LQI
00638                         scan_result = thread_info(cur)->thread_attach_scanned_parent;
00639                         currentMargin = thread_parent_margin_calc(scan_result->linkMarginFromParent, scan_result->linkMarginToParent);
00640                         currentLqi = thread_link_margin_to_quality(currentMargin << THREAD_LINK_MARGIN_SCALING);
00641                         tr_debug("Compare LQI from margins:");
00642                         tr_debug("New Margin %d vs Cur %d", newMargin, currentMargin);
00643                         tr_debug("New Lqi %d vs Cur %d", newLqi, currentLqi);
00644                         if (newLqi > currentLqi) {
00645                             /*Override old parent data*/
00646                             tr_debug("Better Parent Lqi");
00647                         } else {
00648                             if (newLqi == currentLqi) {
00649                                 //Compare if REED
00650                                 if (thread_is_router_addr(scan_result->shortAddress) &&
00651                                         !thread_is_router_addr(srcAddress) ) {
00652                                     scan_result = NULL;
00653                                     tr_debug("Dropped Response from REED over router");
00654                                 } else if (connectivityTlv.parentPriority > scan_result->parentPriority) {
00655                                     tr_debug("Better parent priority %d>%d", connectivityTlv.parentPriority, scan_result->parentPriority);
00656                                 } else if (connectivityTlv.parentPriority < scan_result->parentPriority) {
00657                                     tr_debug("Dropped Response - lower parent priority %d<%d", connectivityTlv.parentPriority, scan_result->parentPriority);
00658                                     scan_result = NULL;
00659                                 } else {
00660                                     tr_debug("Similar LQI check connectivity old: %d,%d,%d new:%d,%d,%d",
00661                                             scan_result->linkQuality3, scan_result->linkQuality2, scan_result->linkQuality1,
00662                                             connectivityTlv.linkQuality3, connectivityTlv.linkQuality2, connectivityTlv.linkQuality1);
00663 
00664                                     if (scan_result->linkQuality3 > connectivityTlv.linkQuality3) {
00665                                         scan_result = NULL;
00666                                     }
00667                                     if (scan_result &&
00668                                             scan_result->linkQuality3 == connectivityTlv.linkQuality3 &&
00669                                             scan_result->linkQuality2 > connectivityTlv.linkQuality2) {
00670                                         scan_result = NULL;
00671                                     }
00672                                     if (scan_result &&
00673                                             scan_result->linkQuality3 == connectivityTlv.linkQuality3 &&
00674                                             scan_result->linkQuality2 == connectivityTlv.linkQuality2 &&
00675                                             scan_result->linkQuality1 > connectivityTlv.linkQuality1) {
00676                                         scan_result = NULL;
00677                                     }
00678                                     if(!scan_result) {
00679                                         tr_debug("Dropped Connectivity is not as good");
00680                                     }
00681                                 }
00682                             } else {
00683                                 scan_result = NULL;
00684                             }
00685                         }
00686                     }
00687                     if (scan_result && thread_host_prefer_parent_response(cur, scan_result, version, &connectivityTlv)){
00688                         scan_result = NULL;
00689                     }
00690 
00691                 }
00692             }
00693 
00694             if (scan_result) {
00695                 // save the result
00696                 thread_leader_data_t *leader;
00697                 scan_result->linkMarginToParent = thread_compute_link_margin(mle_msg->dbm);
00698                 scan_result->linkMarginFromParent = rssiValue;
00699                 scan_result->linLayerFrameCounter = llFrameCounter;
00700                 scan_result->mleFrameCounter = mleFrameCounter;
00701                 scan_result->shortAddress = srcAddress;
00702                 scan_result->version = version;
00703                 memcpy(scan_result->challengeData, challengeTlv.dataPtr, challengeTlv.tlvLen);
00704                 scan_result->chal_len = challengeTlv.tlvLen;
00705                 //Save MAC address from LL64
00706                 memcpy(scan_result->mac64, (mle_msg->packet_src_address + 8), 8);
00707                 scan_result->mac64[0] ^= 2;
00708                 leader = &scan_result->leader_data;
00709                 //Copy Leader Data
00710                 *leader = leaderData;
00711                 scan_result->routeCostToLeader = connectivityTlv.leaderCost;
00712                 scan_result->linkQuality3 = connectivityTlv.linkQuality3;
00713                 scan_result->linkQuality2 = connectivityTlv.linkQuality2;
00714                 scan_result->linkQuality1 = connectivityTlv.linkQuality1;
00715                 scan_result->parentPriority = connectivityTlv.parentPriority;
00716                 scan_result->activeRouters = connectivityTlv.activeRouters;
00717                 scan_result->security_key_index = security_headers->KeyIndex;
00718 
00719                 thread_routing_update_link_margin(cur, scan_result->shortAddress, scan_result->linkMarginToParent, scan_result->linkMarginFromParent);
00720                 scan_result->keySequence = common_read_32_bit(security_headers->Keysource);
00721                 tr_debug("Current %"PRIu32" RX %"PRIu32" Cnt%"PRIu32, scan_result->leader_data.partitionId, leaderData.partitionId, scan_result->linLayerFrameCounter);
00722             }
00723              break;
00724         }
00725         default:
00726             break;
00727     }
00728 
00729 }
00730 
00731 /* Callback for child ID request.
00732  *
00733  * Child ID Response contains these TLVs:
00734  *   - Source Address TLV
00735  *   - Leader Data TLV
00736  *   - Address16 TLV
00737  *   - Network Data TLV (optional)
00738  *   - Route64 TLV (optional)
00739  *   - Address Registration TLV (optional)
00740  *   - Active Operational Dataset TLV (optional)
00741  *   - Pending Operational Dataset TLV (optional)
00742 */
00743 static void thread_mle_child_request_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00744 {
00745     thread_leader_data_t leaderData;
00746     mac_neighbor_table_entry_t *entry_temp;
00747     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
00748     link_configuration_s *link_configuration;
00749     link_configuration = thread_joiner_application_get_config(cur->id);
00750     if (!link_configuration) {
00751         return;
00752     }
00753 
00754     /* Check that message is from link-local scope */
00755     if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00756         return;
00757     }
00758 
00759     tr_debug("Thread MLE Child ID response handler");
00760 
00761     switch (mle_msg->message_type) {
00762 
00763         case MLE_COMMAND_CHILD_ID_RESPONSE: {
00764             uint8_t src_mac64[8];
00765             uint8_t shortAddress[2];
00766             uint16_t childId;
00767             mle_tlv_info_t routeTlv, addressRegisteredTlv, networkDataTlv;
00768             mle_tlv_info_t ConfigurationTlv;
00769             uint64_t pending_timestamp = 0;
00770             uint64_t active_timestamp;
00771             thread_scanned_parent_t *scan_result = thread_info(cur)->thread_attach_scanned_parent;
00772             bool new_entry_created;
00773 
00774             tr_info("Recv Child ID Response");
00775 
00776             // Validate that response is coming from the scanned parent candidate
00777             memcpy(src_mac64, (mle_msg->packet_src_address + 8), 8);
00778             src_mac64[0] ^= 2;
00779             if (memcmp(src_mac64, scan_result->mac64, 8) != 0) {
00780                 tr_debug("Drop Child ID response from previous request");
00781                 return;
00782             }
00783 
00784             // Clear old data
00785             if (cur->thread_info->releaseRouterId) {
00786                 thread_bootstrap_clear_neighbor_entries(cur);
00787             }
00788 
00789             cur->thread_info->localServerDataBase.release_old_address = true;
00790 
00791             thread_neighbor_list_clean(cur);
00792             thread_leader_service_stop(interface_id);
00793             thread_leader_service_leader_data_free(cur->thread_info);
00794             thread_merge_prepare(cur);
00795 
00796             // Create entry for new parent
00797             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, &new_entry_created);
00798             if (entry_temp == NULL) {
00799                 // todo: what to do here?
00800                 return;
00801             }
00802             thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , thread_compute_link_margin(mle_msg->dbm), new_entry_created);
00803             thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00804 
00805             //Parse mandatory TLV's
00806             if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00807                 return;
00808             }
00809             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &entry_temp->mac16 )) {
00810                 return;
00811             }
00812 
00813             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, mle_msg->data_ptr, mle_msg->data_length, &childId)) {
00814                 return;
00815             }
00816 
00817             //Read Optional TLV's
00818             mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv);
00819             mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv);
00820             mle_tlv_read_tlv(MLE_TYPE_ROUTE, mle_msg->data_ptr, mle_msg->data_length, &routeTlv);
00821             // update operational datasets
00822             mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00823             if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00824                 thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00825             }
00826             // TODO check if result is true then need to update all configurations
00827             mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00828             if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00829                 thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00830             } else if (pending_timestamp < thread_joiner_application_pending_config_timestamp_get(cur->id)) {
00831                 // parent did not have timestamp but we haver
00832                 tr_info("save pending set for leader");
00833                 thread_joiner_application_next_pending_config_save(cur->id);
00834                 thread_joiner_application_pending_config_delete(cur->id);
00835             }
00836 
00837             *thread_info(cur)->thread_leader_data = leaderData;
00838 
00839             thread_parent_info_t *parent = thread_parent_data_allocate(cur->thread_info);
00840             if (!parent) {
00841                 tr_debug("Parent allocate fail.");
00842                 return;
00843             }
00844 
00845             common_write_16_bit(entry_temp->mac16 , shortAddress);
00846             //Update possible reed address by real router address
00847             scan_result->shortAddress = entry_temp->mac16 ;
00848 
00849             entry_temp->connected_device  = 1;
00850             entry_temp->link_role  = PRIORITY_PARENT_NEIGHBOUR;
00851 
00852             mac_helper_coordinator_address_set(cur, ADDR_802_15_4_SHORT , shortAddress);
00853             mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, thread_info(cur)->host_link_timeout);
00854 
00855             if (scan_result->security_key_index != security_headers->KeyIndex) {
00856                 // KeyIndex has been changed between parent_response and child_id_response, reset link layer frame counter
00857                 scan_result->linLayerFrameCounter = 0;
00858                 scan_result->security_key_index = security_headers->KeyIndex;
00859             }
00860             mlme_device_descriptor_t device_desc;
00861             mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 ,scan_result->linLayerFrameCounter, false);
00862             mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , security_headers->KeyIndex, new_entry_created);
00863 
00864             thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
00865 
00866             thread_bootstrap_update_ml16_address(cur, childId);
00867             if (!thread_is_router_addr(thread_info(cur)->routerShortAddress)) {
00868                 thread_info(cur)->routerShortAddress = 0xfffe;
00869             }
00870 
00871             mle_service_msg_free(scan_result->child_id_request_id);
00872 
00873             scan_result->child_id_request_id = 0;
00874             //SET Parent Info and free scan response info
00875             parent->pathCostToLeader = thread_sum_rx_path_cost_and_link_cost(scan_result->linkMarginToParent, scan_result->linkMarginFromParent, scan_result->routeCostToLeader);
00876             parent->shortAddress = scan_result->shortAddress;
00877             parent->router_id = (scan_result->shortAddress >> 10);
00878             memcpy(parent->mac64, scan_result->mac64, 8);
00879             //Check Network Data TLV
00880             if (networkDataTlv.tlvType == MLE_TYPE_NETWORK_DATA) {
00881                 thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00882             } else {
00883                 cur->thread_info->thread_leader_data->dataVersion--;
00884                 cur->thread_info->thread_leader_data->stableDataVersion--;
00885             }
00886 
00887             blacklist_update(mle_msg->packet_src_address, true);
00888 
00889             //
00890             if (routeTlv.tlvType == MLE_TYPE_ROUTE && routeTlv.tlvLen) {
00891                 thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , thread_compute_link_margin(mle_msg->dbm), entry_temp);
00892             }
00893             thread_bootstrap_attached_ready(cur);
00894 
00895             break;
00896         }
00897         default:
00898             tr_debug("Skip msg type %d", mle_msg->message_type);
00899             break;
00900 
00901     }
00902 }
00903 
00904 static int8_t thread_end_device_synch_start(protocol_interface_info_entry_t *cur)
00905 {
00906     mle_message_timeout_params_t timeout;
00907     uint32_t keySequence;
00908     uint16_t buf_id = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, true,MLE_COMMAND_CHILD_UPDATE_REQUEST);
00909     if (buf_id == 0) {
00910         return -1;
00911     }
00912     uint8_t tlv_req[3];
00913 
00914     thread_management_get_current_keysequence(cur->id, &keySequence);
00915     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
00916     uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(buf_id);
00917     //Set Parent Address
00918     memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
00919     address_ptr += 8;
00920     memcpy(address_ptr, cur->thread_info->thread_endnode_parent->mac64, 8);
00921     *address_ptr ^= 2;
00922     uint8_t *ptr = mle_service_get_data_pointer(buf_id);
00923     //Add mode
00924     ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur));
00925     ptr = thread_address_registration_tlv_write(ptr, cur);
00926     tlv_req[0] = MLE_TYPE_ADDRESS16;
00927     tlv_req[1] = MLE_TYPE_NETWORK_DATA;
00928 
00929     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
00930         // REEDs request Route64 as well
00931         tlv_req[2] = MLE_TYPE_ROUTE;
00932         ptr = mle_tlv_req_tlv(ptr, tlv_req, 3);
00933     } else {
00934         ptr = mle_tlv_req_tlv(ptr, tlv_req, 2);
00935     }
00936 
00937     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
00938         tr_debug("Buffer overflow at message write");
00939     }
00940 
00941     tr_debug("Send MLE Child Update Request (Child synchronisation)");
00942     timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT;
00943     timeout.timeout_init = 1;
00944     timeout.timeout_max = 3;
00945     timeout.delay = MLE_NO_DELAY;
00946 
00947     mle_service_set_packet_callback(buf_id, thread_device_synch_timeout);
00948     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
00949     mle_service_send_message(buf_id);
00950     return 0;
00951 }
00952 
00953 void thread_endevice_synch_start(protocol_interface_info_entry_t *cur)
00954 {
00955     if (cur->thread_info->thread_endnode_parent) {
00956         bool new_entry_created;
00957 
00958         // Add the parent to the MLE neighbor table
00959         mac_neighbor_table_entry_t *mac_entry = mac_neighbor_entry_get_by_mac64(mac_neighbor_info(cur), cur->thread_info->thread_endnode_parent->mac64, true, &new_entry_created);
00960         if (mac_entry) {
00961             //Add link margin 64
00962             thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, mac_entry->index ,64, new_entry_created);
00963             thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, mac_entry->index );
00964 
00965             mac_entry->mac16  = cur->thread_info->thread_endnode_parent->shortAddress;
00966             mac_entry->connected_device  = 1;
00967 
00968             // In case we don't get response to sync; use temporary timeout here,
00969             // Child ID Response handler will set correct value later
00970             mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), mac_entry, mac_entry->link_lifetime );
00971 
00972             // Add the parent to the MAC table (for e.g. secured/fragmented Child Update Response)
00973             mlme_device_descriptor_t device_desc;
00974             mac_helper_device_description_write(cur, &device_desc, mac_entry->mac64 , mac_entry->mac16 ,0, false);
00975             mac_helper_devicetable_set(&device_desc, cur, mac_entry->index , cur->mac_parameters->mac_default_key_index, new_entry_created);
00976         }
00977     }
00978 
00979     //Send Child Synch
00980     if (thread_end_device_synch_start(cur) == 0) {
00981         //SET Child synch receiver handler
00982         mle_service_interface_receiver_handler_update(cur->id, thread_child_synch_receive_cb);
00983         cur->nwk_bootstrap_state = ER_MLE_SYNCH;
00984     }
00985 }
00986 
00987 static bool thread_child_id_req_timeout(int8_t interface_id, uint16_t msgId, bool usedAllRetries)
00988 {
00989     mac_neighbor_table_entry_t *entry_temp;
00990     thread_scanned_parent_t *scanned_parent;
00991     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00992 
00993     (void)msgId;
00994 
00995     if (!cur) {
00996         return false;
00997     }
00998 
00999     // Not last retry - keep trying
01000     if (!usedAllRetries) {
01001         return true;
01002     }
01003 
01004     //Do not release message inside this call MLE service will do that.
01005     cur->thread_info->thread_attach_scanned_parent->child_id_request_id = 0;
01006 
01007     uint8_t *addr = mle_service_get_msg_destination_address_pointer(msgId);
01008     tr_debug("Child ID Request timed out: %s", trace_ipv6(addr));
01009 
01010     blacklist_update(addr, false);
01011 
01012     scanned_parent = cur->thread_info->thread_attach_scanned_parent;
01013 
01014     /* Used all retries - if we are on any attach state or */
01015     /* if we don't have route to leader, start any-attach */
01016     if (thread_info(cur)->thread_attached_state == THREAD_STATE_NETWORK_DISCOVER ||
01017             -1 == thread_route_ready_to_leader(cur) || !scanned_parent) {
01018         tr_debug("start any-attach");
01019         thread_bootstrap_connection_error(interface_id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL);
01020         goto exit;
01021     }
01022 
01023     /* Go back to old partition */
01024     tr_debug("Back to old partition");
01025 
01026     /* If scanned parent is from other partition, delete from MLE table */
01027     if ((scanned_parent->leader_data.partitionId != thread_info(cur)->thread_leader_data->partitionId) ||
01028         (scanned_parent->leader_data.weighting != thread_info(cur)->thread_leader_data->weighting)) {
01029         entry_temp = mac_neighbor_table_address_discover(mac_neighbor_info(cur), scanned_parent->mac64, ADDR_802_15_4_LONG );
01030         if (entry_temp) {
01031             bool my_parent = thread_check_is_this_my_parent(cur, entry_temp);
01032             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01033             if (my_parent) {
01034                 tr_debug("No parent resp - any-attach");
01035                 thread_bootstrap_connection_error(interface_id, CON_ERROR_NETWORK_ATTACH_FAIL, NULL);
01036                 goto exit;
01037             }
01038         }
01039     }
01040 
01041     if (thread_info(cur)->thread_endnode_parent) {
01042         mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , thread_info(cur)->thread_endnode_parent->mac64);
01043     }
01044     if (cur->thread_info->routerShortAddress == 0xfffe ||
01045             !thread_is_router_addr(cur->thread_info->routerShortAddress)) {
01046         thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED;
01047     } else {
01048         thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER;
01049     }
01050 
01051     cur->thread_info->localServerDataBase.release_old_address = false;
01052     cur->thread_info->releaseRouterId = false;
01053     cur->thread_info->networkDataRequested = false;
01054 
01055     cur->nwk_bootstrap_state = ER_BOOTSRAP_DONE;
01056 
01057 exit:
01058     mle_service_interface_receiver_handler_update(cur->id, thread_general_mle_receive_cb);
01059 
01060     ns_dyn_mem_free(cur->thread_info->thread_attach_scanned_parent);
01061     cur->thread_info->thread_attach_scanned_parent = NULL;
01062 
01063     return false;
01064 }
01065 
01066 static int thread_attach_child_id_request_build(protocol_interface_info_entry_t *cur)
01067 {
01068     uint8_t *ptr, *address_ptr;
01069     uint8_t mode;
01070     mle_message_timeout_params_t timeout;
01071     uint32_t keySequence;
01072     uint16_t buf_id = mle_service_msg_allocate(cur->id, 128, false, MLE_COMMAND_CHILD_ID_REQUEST);
01073     if (buf_id == 0) {
01074         return -1;
01075     }
01076 
01077     thread_scanned_parent_t *scan_parent = thread_info(cur)->thread_attach_scanned_parent;
01078 
01079     //Set ll64
01080     address_ptr = mle_service_get_msg_destination_address_pointer(buf_id);
01081     memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
01082     memcpy(address_ptr + 8 , scan_parent->mac64, 8);
01083     address_ptr[8] ^= 2;
01084 
01085     thread_management_get_current_keysequence(cur->id, &keySequence);
01086     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
01087 
01088     uint8_t request_tlv_list[3];
01089     uint8_t macShort[2];
01090     uint8_t reqTlvCnt;
01091     mode = thread_mode_get_by_interface_ptr(cur);
01092     common_write_16_bit(scan_parent->shortAddress, macShort);
01093     //SET Coordinator Address
01094     mac_helper_coordinator_address_set(cur, ADDR_802_15_4_LONG , scan_parent->mac64);
01095 
01096     ptr = mle_service_get_data_pointer(buf_id);
01097     /* Allocate a new challenge */
01098     ptr = mle_tlv_write_mode(ptr, thread_mode_get_by_interface_ptr(cur));
01099     ptr = mle_general_write_link_layer_framecounter(ptr, cur);
01100     //SET MLE Frame Counter
01101     ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
01102     ptr = mle_tlv_write_response(ptr, scan_parent->challengeData, scan_parent->chal_len);
01103 
01104     //Add ML-EID
01105     if ((mode & MLE_FFD_DEV) == 0) {
01106         ptr = thread_address_registration_tlv_write(ptr, cur);
01107     }
01108 
01109     reqTlvCnt = 2;
01110     request_tlv_list[0] = MLE_TYPE_NETWORK_DATA;
01111 
01112     request_tlv_list[1] = MLE_TYPE_ADDRESS16;
01113     if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
01114         request_tlv_list[2] = MLE_TYPE_ROUTE;
01115         reqTlvCnt = 3;
01116     }
01117     ptr = mle_tlv_req_tlv(ptr, request_tlv_list, reqTlvCnt);
01118     ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
01119     //Set Version
01120     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
01121     //add only active timestamp to the child id request
01122     ptr = thread_active_timestamp_write(cur, ptr);
01123 
01124     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
01125         tr_debug("Buffer overflow at message write");
01126     }
01127     timeout.retrans_max = THREAD_CHILD_ID_REQUEST_MAX_RETRY_CNT;
01128     timeout.timeout_init = 1;
01129     timeout.timeout_max = 3;
01130     timeout.delay = MLE_NO_DELAY;
01131 
01132     mle_service_set_packet_callback(buf_id, thread_child_id_req_timeout);
01133     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
01134     mle_service_send_message(buf_id);
01135     //Update MLE handler state
01136     mle_service_interface_receiver_handler_update(cur->id, thread_mle_child_request_receive_cb);
01137     cur->nwk_bootstrap_state = ER_CHILD_ID_REQ;
01138     scan_parent->child_id_request_id = buf_id;
01139     return 0;
01140 }
01141 
01142 static bool thread_child_update_timeout_cb(int8_t interface_id, uint16_t msgId, bool usedAllRerties)
01143 {
01144     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01145     if (!cur || !cur->thread_info->thread_endnode_parent) {
01146         return false;
01147     }
01148     if (msgId != cur->thread_info->childUpdateReqMsgId) {
01149         //Wrong message id
01150         return false;
01151     }
01152 
01153     if (usedAllRerties) {
01154         tr_debug("Child Update timed out");
01155         cur->thread_info->thread_endnode_parent->childUpdatePending = false;
01156         cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
01157         mac_data_poll_protocol_poll_mode_decrement(cur);
01158         thread_bootstrap_reset_restart(cur->id);
01159         tr_debug("Restart attachment");
01160         return false;
01161     }
01162     if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
01163         // we have not received response so re-send
01164         return true;
01165     }
01166 
01167     return false;
01168 
01169 }
01170 
01171 bool thread_host_bootstrap_child_update(protocol_interface_info_entry_t *cur, const uint8_t *mac64)
01172 {
01173     mle_message_timeout_params_t timeout;
01174     uint8_t mode;
01175     uint32_t keySequence;
01176 
01177 
01178     if (!cur->thread_info->thread_endnode_parent) {
01179         tr_debug("Not end device parent info for NUD");
01180         return false;
01181     }
01182 
01183     if (cur->thread_info->thread_endnode_parent->childUpdateProcessActive) {
01184         //Set Pending if earlier process is already started
01185         cur->thread_info->thread_endnode_parent->childUpdatePending = true;
01186         return false;
01187     }
01188     //Trig event
01189     cur->thread_info->thread_endnode_parent->childUpdatePending = false;
01190     cur->thread_info->thread_endnode_parent->childUpdateProcessActive = true;
01191 
01192 
01193     tr_debug("Child Update Request");
01194 
01195     mode = thread_mode_get_by_interface_ptr(cur);
01196 
01197     //Build packet
01198 
01199     uint16_t bufId = mle_service_msg_allocate(cur->id, 150 + 3 + 6 + 10, false, MLE_COMMAND_CHILD_UPDATE_REQUEST);
01200     if (bufId == 0) {
01201         return false;
01202     }
01203 
01204     thread_management_get_current_keysequence(cur->id, &keySequence);
01205     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
01206 
01207     uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(bufId);
01208     memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
01209     memcpy(address_ptr + 8, mac64, 8);
01210     address_ptr[8] ^= 2;
01211 
01212     uint8_t *ptr = mle_service_get_data_pointer(bufId);
01213     ptr = mle_tlv_write_mode(ptr, mode);
01214     ptr = mle_general_write_source_address(ptr, cur);
01215     ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
01216     ptr = thread_leader_data_tlv_write(ptr, cur);
01217 
01218     //Set Addresss TLV
01219     if ((mode & MLE_FFD_DEV) == 0) {
01220         ptr = thread_address_registration_tlv_write(ptr, cur);
01221     }
01222 
01223     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
01224         tr_debug("Buffer overflow at message write");
01225     }
01226     timeout.retrans_max = 3;
01227     timeout.timeout_init = 1;
01228     timeout.timeout_max = 4;
01229     timeout.delay = MLE_NO_DELAY;
01230     net_host_mode_t macHostMode;
01231     if (mac_data_poll_host_mode_get(cur,&macHostMode) == 0 && macHostMode == NET_HOST_RX_ON_IDLE) {
01232         thread_end_device_mode_set(cur, false);
01233     }
01234     mac_data_poll_init_protocol_poll(cur);
01235     cur->thread_info->childUpdateReqMsgId = bufId;
01236     mle_service_set_packet_callback(bufId, thread_child_update_timeout_cb);
01237     mle_service_set_msg_timeout_parameters(bufId, &timeout);
01238     mle_service_send_message(bufId);
01239 
01240     return true;
01241 }
01242 int thread_host_bootstrap_child_update_negative_response(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, mle_tlv_info_t *challenge)
01243 {
01244     uint32_t keySequence;
01245 
01246     if (!challenge) {
01247         return -2;
01248     }
01249 
01250     uint16_t bufId = mle_service_msg_allocate(cur->id, 16 + challenge->tlvLen, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE);
01251 
01252     if (bufId == 0) {
01253         return -1;
01254     }
01255     tr_debug("MLE Child negative Response");
01256 
01257     thread_management_get_current_keysequence(cur->id, &keySequence);
01258     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
01259 
01260     uint8_t *ptr = mle_service_get_data_pointer(bufId);
01261 
01262     *ptr++ = MLE_TYPE_STATUS;
01263     *ptr++ = 1;
01264     *ptr++ = MLE_STATUS_ERROR;
01265 
01266     if (challenge->tlvLen) {
01267         //Add response
01268         ptr = mle_tlv_write_response(ptr, challenge->dataPtr, challenge->tlvLen);
01269     }
01270 
01271     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
01272         tr_debug("Buffer overflow at message write");
01273     }
01274 
01275     mle_service_set_msg_destination_address(bufId, dstAddress);
01276     mle_service_send_message(bufId);
01277     return 0;
01278 }
01279 
01280 
01281 #endif
01282