EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_host_bootstrap.c Source File

thread_host_bootstrap.c

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