Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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