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