Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_host_bootstrap.c Source File

thread_host_bootstrap.c

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