Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_mle_message_handler.c Source File

thread_mle_message_handler.c

00001 /*
00002  * Copyright (c) 2016-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 #include "nsconfig.h"
00030 #ifdef HAVE_THREAD
00031 
00032 #include "ns_trace.h"
00033 #include "common_functions.h"
00034 #include "NWK_INTERFACE/Include/protocol.h"
00035 #include <nsdynmemLIB.h>
00036 #include "Service_Libs/mle_service/mle_service_api.h"
00037 #include "Service_Libs/blacklist/blacklist.h"
00038 #include "6LoWPAN/Thread/thread_config.h"
00039 #include "6LoWPAN/Thread/thread_common.h"
00040 #include "6LoWPAN/Thread/thread_lowpower_private_api.h"
00041 #include "6LoWPAN/Thread/thread_mle_message_handler.h"
00042 #include "6LoWPAN/Thread/thread_bootstrap.h"
00043 #include "6LoWPAN/Thread/thread_management_internal.h"
00044 #include "6LoWPAN/Thread/thread_joiner_application.h"
00045 #include "6LoWPAN/Thread/thread_leader_service.h"
00046 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00047 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00048 #include "6LoWPAN/Thread/thread_extension.h"
00049 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00050 #include "6LoWPAN/Thread/thread_network_synch.h"
00051 #include "6LoWPAN/MAC/mac_helper.h"
00052 #include "6LoWPAN/MAC/mac_data_poll.h"
00053 #include "MLE/mle.h"
00054 #include "mac_api.h"
00055 #define TRACE_GROUP "thmh"
00056 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64);
00057 static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor);
00058 static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
00059 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
00060 static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
00061 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg);
00062 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin);
00063 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin);
00064 static void thread_parse_child_update_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin);
00065 
00066 /* Public functions */
00067 void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00068 {
00069     /* TODO's:
00070      * - Any incoming link configuration or advertisement message, or an incoming update sent to a
00071      *   link-local address, whose IP Hop Limit is not 255, may have been forwarded by a Router
00072      *   and MUST be discarded.
00073      */
00074 
00075     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00076 
00077     if (!cur) {
00078         return;
00079     }
00080 
00081     /* Check that message is from link-local scope */
00082     if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00083         return;
00084     }
00085 
00086     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
00087 
00088     // Always save lowpower queries
00089     thread_lowpower_process_request(mle_msg);
00090 
00091     switch (mle_msg->message_type) {
00092     case MLE_COMMAND_ACCEPT: {
00093         thread_parse_accept(cur, mle_msg, security_headers, linkMargin);
00094         break;
00095     }
00096 
00097     case MLE_COMMAND_METRIC_MANAGEMENT_REQUEST: {
00098         thread_lowpower_metrics_management_query_request_process(cur, mle_msg, security_headers, linkMargin);
00099         break;
00100     }
00101 
00102     case MLE_COMMAND_REJECT: {
00103         mle_neigh_table_entry_t *entry_temp;
00104         tr_warn("Reject Link");
00105         entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
00106         if (entry_temp) {
00107             mle_class_remove_entry(cur->id, entry_temp);
00108         }
00109         break;
00110     }
00111 
00112     case MLE_COMMAND_DATASET_ANNOUNCE: {
00113         thread_parse_annoucement(cur, mle_msg);
00114         break;
00115     }
00116 
00117     case MLE_COMMAND_ADVERTISEMENT: {
00118         thread_parse_advertisement(cur, mle_msg, security_headers, linkMargin);
00119         break;
00120     }
00121 
00122     case MLE_COMMAND_DATA_RESPONSE: {
00123         thread_parse_data_response(cur, mle_msg, linkMargin);
00124         break;
00125     }
00126 
00127     case MLE_COMMAND_CHILD_UPDATE_RESPONSE:
00128     {
00129         thread_parse_child_update_response(cur, mle_msg, security_headers, linkMargin);
00130         break;
00131     }
00132 
00133     case MLE_COMMAND_PARENT_RESPONSE: {
00134         tr_debug("MLE parent response received");
00135         thread_mle_parent_discover_receive_cb(interface_id, mle_msg, security_headers);
00136         break;
00137     }
00138     default:
00139         if ((thread_am_host(cur) || thread_am_reed(cur)) && mle_msg->message_type == MLE_COMMAND_CHILD_UPDATE_REQUEST){
00140             // Thread host and router in REED mode answer the message same way. Routers only process messages from child
00141             thread_host_child_update_request_process(cur, mle_msg, linkMargin);
00142         } else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
00143             thread_router_bootstrap_mle_receive_cb(interface_id, mle_msg, security_headers);
00144         } else {
00145             tr_warn("Not supported MLE message for host %d", mle_msg->message_type);
00146         }
00147     }
00148 
00149 }
00150 
00151 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
00152 {
00153     if (thread_info(cur)->thread_leader_data) {
00154         bool requestNetworkdata = false;
00155         if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion)) {
00156             requestNetworkdata = true;
00157 
00158         } else if (common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) {
00159             requestNetworkdata = true;
00160         }
00161 
00162         if (thread_info(cur)->thread_leader_data->partitionId != leaderData->partitionId) {
00163             requestNetworkdata = true;
00164             thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion - 1;
00165             thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion - 1;
00166         }
00167 
00168         thread_info(cur)->thread_leader_data->partitionId = leaderData->partitionId;
00169         thread_info(cur)->thread_leader_data->leaderRouterId = leaderData->leaderRouterId;
00170         thread_info(cur)->thread_leader_data->weighting = leaderData->weighting;
00171 
00172         if (requestNetworkdata) {
00173             thread_bootstrap_parent_network_data_request(cur, false);
00174         } else {
00175             thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion;
00176             thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion;
00177         }
00178     }
00179 }
00180 
00181 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64)
00182 {
00183     mle_message_timeout_params_t timeout;
00184     uint32_t keySequence;
00185     uint16_t bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
00186 
00187     if (bufId == 0) {
00188         return -1;
00189     }
00190 
00191     timeout.retrans_max = 2;
00192     timeout.timeout_init = 2;
00193     timeout.timeout_max = 3;
00194     timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00195 
00196     thread_management_get_current_keysequence(cur->id, &keySequence);
00197     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00198 
00199     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00200 
00201     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00202     ptr = mle_general_write_source_address(ptr, cur);
00203     ptr = thread_leader_data_tlv_write(ptr, cur);
00204 
00205     tr_debug("Synch Req");
00206 
00207     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
00208         tr_debug("Buffer overflow at message write");
00209     }
00210 
00211     mle_service_set_packet_callback(bufId, thread_link_request_timeout);
00212     mle_service_set_msg_destination_address(bufId, router_ll64);
00213     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00214     mle_service_send_message(bufId);
00215     return 0;
00216 }
00217 
00218 static bool thread_router_leader_data_process(protocol_interface_info_entry_t *cur, uint8_t *src_address, thread_leader_data_t *leaderData, mle_tlv_info_t *routeTlv, mle_neigh_table_entry_t *neighbor)
00219 {
00220     int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv);
00221 
00222     if (leaderDataUpdate == 1) {
00223         if (neighbor && neighbor->handshakeReady == 1) {
00224             // Request network data if we have a 2-way link
00225             tr_debug("Request New Network Data from %s", trace_ipv6(src_address));
00226             thread_network_data_request_send(cur, src_address, true);
00227         } else {
00228 
00229         }
00230     } else if (leaderDataUpdate == 2) {
00231         tr_debug("Start Merge");
00232         thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
00233         return false;
00234 
00235     } else if (leaderDataUpdate < 0) {
00236         tr_warn("Leader data failure");
00237         return false;
00238     }
00239     return true;
00240 }
00241 
00242 static bool thread_reed_partitions_merge(protocol_interface_info_entry_t *cur, uint16_t shortAddress, thread_leader_data_t heard_partition_leader_data)
00243 {
00244     if (thread_is_router_addr(shortAddress)) {
00245         return false;
00246     }
00247     if (thread_extension_version_check(thread_info(cur)->version)) {
00248         // lower weighting heard
00249         if (thread_info(cur)->thread_leader_data->weighting > heard_partition_leader_data.weighting) {
00250             return false;
00251         }
00252         // lower/same partition id heard
00253         if (thread_info(cur)->thread_leader_data->weighting == heard_partition_leader_data.weighting &&
00254                 thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId ) {
00255             return false;
00256         }
00257     } else if (thread_info(cur)->thread_leader_data->partitionId >= heard_partition_leader_data.partitionId){
00258         return false;
00259     }
00260     // can merge to a higher weighting/partition id
00261     thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
00262     return true;
00263 }
00264 
00265 static bool thread_router_advertiment_tlv_analyze(uint8_t *ptr, uint16_t data_length, thread_leader_data_t *leaderData, uint16_t *shortAddress, mle_tlv_info_t *routeTlv)
00266 {
00267     //Read Leader Data and verify connectivity
00268     // Leader data is mandatory
00269     if (!thread_leader_data_parse(ptr, data_length, leaderData)) {
00270         return false;
00271     }
00272 
00273     if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) {
00274         return false;
00275     }
00276 
00277     if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) {
00278         if (thread_is_router_addr(*shortAddress)) {
00279             //Sender is reeds
00280             return false;
00281         }
00282         routeTlv->dataPtr = NULL;
00283         routeTlv->tlvLen = 0;
00284     }
00285     return true;
00286 }
00287 
00288 static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mle_neigh_table_entry_t *entry_temp, uint16_t short_address)
00289 {
00290     if (!entry_temp) {
00291         return;
00292     }
00293 
00294     mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
00295 
00296     if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) {
00297         mle_entry_timeout_refresh(entry_temp);
00298     } else {
00299         entry_temp->last_contact_time = protocol_core_monotonic_time;
00300     }
00301 
00302     if (short_address != entry_temp->short_adr) {
00303         if (thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) {
00304             thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
00305             protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
00306         }
00307         entry_temp->short_adr = short_address;
00308         /* throw MLME_GET request, short address is changed automatically in get request callback */
00309         mlme_get_t get_req;
00310         get_req.attr = macDeviceTable;
00311         get_req.attr_index = entry_temp->attribute_index;
00312         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
00313     }
00314 
00315     return;
00316 }
00317 
00318 static void thread_parse_advertisement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
00319 {
00320     mle_tlv_info_t routeTlv;
00321     thread_leader_data_t leaderData;
00322     uint16_t shortAddress;
00323     mle_neigh_table_entry_t *entry_temp;
00324 
00325     // Check device mode & bootstrap state
00326     if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) ||
00327         (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) {
00328         return;
00329     }
00330 
00331     tr_debug("Received Advertisement");
00332 
00333     // Validate and parse TLV's
00334     if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) {
00335         return;
00336     }
00337 
00338     // Get MLE entry
00339     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
00340 
00341     if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
00342             && (thread_instance_id_matches(cur, &leaderData))) {
00343         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00344     }
00345 
00346     // Check parent status
00347     if (!thread_attach_active_router(cur)) {
00348         //processing for non routers
00349         if (thread_check_is_this_my_parent(cur, entry_temp)) {
00350             //advertisement from parent
00351             if ((thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) ||
00352                 (thread_info(cur)->thread_leader_data->weighting != leaderData.weighting)) {
00353                 //parent changed partition/weight - reset own routing information
00354                 thread_old_partition_data_purge(cur);
00355             }
00356             //check if network data needs to be requested
00357             if (!thread_bootstrap_request_network_data(cur, &leaderData, shortAddress)) {
00358                 tr_debug("Parent short address changed - re-attach");
00359                 thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00360                 return;
00361             }
00362         }
00363     }
00364 
00365     // Update MLE entry
00366     thread_update_mle_entry(cur, mle_msg, security_headers, entry_temp, shortAddress);
00367 
00368     // Process advertisement
00369     if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
00370         if (!thread_attach_active_router(cur)) {
00371             // REED and FED
00372             if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
00373                 if ((thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) &&
00374                         (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting)) {
00375                     // Create link to new neighbor no other processing allowed
00376                     thread_link_request_start(cur, mle_msg->packet_src_address);
00377                     return;
00378                 }
00379                 if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp)) {
00380                     // better partition found or new network data learn started
00381                     return;
00382                 }
00383             }
00384             // process REED advertisement from higher partition
00385             if (thread_reed_partitions_merge(cur, shortAddress, leaderData)) {
00386                 return;
00387             }
00388         } else {
00389             //Router
00390             if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) {
00391                 return;
00392             }
00393             thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress);
00394         }
00395     }
00396 
00397     // Process route TLV
00398     if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) &&
00399             (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){
00400         tr_debug("Update Route TLV %x", entry_temp->short_adr);
00401         thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp);
00402     }
00403 }
00404 static void thread_parse_accept(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
00405 {
00406     uint32_t llFrameCounter;
00407     uint32_t mleFrameCounter;
00408     uint16_t version, shortAddress;
00409     uint16_t messageId;
00410     uint8_t linkMarginfronNeigh;
00411     mle_neigh_table_entry_t *entry_temp;
00412     bool createNew;
00413 
00414     tr_info("MLE LINK ACCEPT");
00415 
00416     messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00417 
00418     if (messageId == 0) {
00419         tr_debug("Not for me");
00420         return;
00421     }
00422 
00423     if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) {
00424         //Free Response only if it is unicast
00425         mle_service_msg_free(messageId);
00426     }
00427 
00428     // TODO: Check missing TLV's
00429     if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
00430             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
00431             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
00432         return;
00433     }
00434 
00435     /* Call to determine whether or not we should create a new link */
00436     createNew = thread_bootstrap_link_create_check(cur, shortAddress);
00437 
00438     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew);
00439 
00440     if (!entry_temp) {
00441         thread_link_reject_send(cur, mle_msg->packet_src_address);
00442         return;
00443     }
00444 
00445     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00446         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00447     }
00448 
00449     //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
00450     if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) {
00451         mleFrameCounter = llFrameCounter;
00452     }
00453 
00454     entry_temp->threadNeighbor = true;
00455     entry_temp->short_adr = shortAddress;
00456     entry_temp->mle_frame_counter = mleFrameCounter;
00457     // Set full data as REED needs full data and SED will not make links
00458     entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
00459 
00460     mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex);
00461 
00462     if (entry_temp->timeout_rx) {
00463         mle_entry_timeout_refresh(entry_temp);
00464     } else {
00465         mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
00466     }
00467 
00468     if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) {
00469         // If we both are routers, mark the link as 2-way
00470         entry_temp->handshakeReady = 1;
00471         tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady);
00472     } else {
00473         tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady);
00474     }
00475 
00476     blacklist_update(mle_msg->packet_src_address, true);
00477 
00478     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
00479         thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
00480     }
00481 }
00482 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg)
00483 {
00484     uint64_t timestamp;
00485     uint16_t panid;
00486     uint8_t *ptr;
00487     uint8_t channel_page;
00488     uint16_t channel;
00489     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00490 
00491 
00492     tr_info("Recv Dataset Announce");
00493     if (8 > thread_tmfcop_tlv_data_get_uint64(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_ACTIVE_TIMESTAMP,&timestamp)) {
00494         tr_error("Missing timestamp TLV");
00495         return;
00496     }
00497     if (2 > thread_tmfcop_tlv_data_get_uint16(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_PANID,&panid)) {
00498         tr_error("Missing Panid TLV");
00499         return;
00500     }
00501     if (3 > thread_tmfcop_tlv_find(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_CHANNEL,&ptr)) {
00502         tr_error("Missing Channel TLV");
00503         return;
00504     }
00505     channel_page = ptr[0];
00506     channel = common_read_16_bit(&ptr[1]);
00507 
00508     if (linkConfiguration->timestamp == timestamp) {
00509         // We received same timestamp
00510         tr_debug("Same timestamp");
00511         return;
00512     }
00513 
00514     if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timestamp == timestamp){
00515         // We received same timestamp again
00516         tr_debug("Processing announce with same timestamp");
00517         return;
00518     }
00519 
00520 
00521     if (linkConfiguration->timestamp > timestamp) {
00522         // We received older time stamp we just announce back to originator channel
00523         thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, channel);
00524         return;
00525     }
00526 
00527     tr_debug("New configuration received");
00528     thread_bootstrap_temporary_attach(cur,channel_page, channel, panid, timestamp);
00529 }
00530 
00531 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
00532 {
00533     thread_leader_data_t leaderData;
00534     mle_tlv_info_t networkDataTlv;
00535     mle_tlv_info_t ConfigurationTlv;
00536     uint64_t active_timestamp = 0;
00537     uint64_t pending_timestamp = 0;// means no pending timestamp
00538     mle_neigh_table_entry_t *entry_temp;
00539     bool accept_new_data = false;
00540     bool leaderDataReceived;
00541 
00542     tr_debug("Data Response");
00543 
00544     if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00545         leaderDataReceived = true;
00546     } else {
00547         leaderDataReceived = false;
00548     }
00549     if (!leaderDataReceived) {
00550         tr_warn("no leader TLV");
00551         return;
00552     }
00553 
00554     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
00555 
00556     if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ||
00557             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
00558         if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) {
00559             // We are attached as child and just learn new data
00560             if (!thread_check_is_this_my_parent(cur, entry_temp)) {
00561                 return;
00562             }
00563         } else {
00564             if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00565                 // if receiving data response from different partition it is dropped
00566                 return;
00567             }
00568         }
00569     } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ||
00570             thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00571         if (!entry_temp) {
00572             tr_debug("Unknown neighbor");
00573             return;
00574         }
00575     }
00576 
00577     if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00578         thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
00579         thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
00580         thread_old_partition_data_purge(cur);
00581         accept_new_data = true;
00582     }
00583 
00584     //check response is for link metrics query
00585     thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length);
00586 
00587     if (cur->thread_info->networkDataRequested) {
00588         tr_debug("Requested network data received");
00589         cur->thread_info->networkDataRequested = false;
00590         accept_new_data = true;
00591     }
00592     if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) {
00593         tr_debug("Network data updated");
00594         accept_new_data = true;
00595     }
00596     // update operational datasets
00597 
00598     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00599     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00600         thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00601     }
00602     // TODO check if result is true then need to update all configurations
00603     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00604     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00605         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00606     }
00607     // Check if we are now in sync
00608     // if not matching must send data request again
00609     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp
00610             || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00611         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00612                 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00613                 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00614         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00615         return;
00616     }
00617     //Check Network Data TLV
00618     if (accept_new_data) {
00619         if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00620            thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00621            thread_bootstrap_network_data_update(cur);
00622         } else {
00623             tr_debug("SET NWK data Request state");
00624         }
00625     }
00626 
00627     // leader has finished synching network data after reset/restart
00628     if (cur->thread_info->leader_synced) {
00629         cur->thread_info->leader_synced = false;
00630         thread_leader_service_network_data_changed(cur, true, true);
00631     }
00632 }
00633 static int thread_host_child_update_response_send(protocol_interface_info_entry_t *cur, uint8_t *dst_address, mle_tlv_info_t *challengeTlv, mle_tlv_info_t *requestTlv)
00634 {
00635     uint16_t len = 150 + 64;
00636     uint8_t mode;
00637     uint32_t keySequence;
00638     uint8_t *ptr;
00639     if (!thread_info(cur)) {
00640         return -1;
00641     }
00642 
00643     uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE);
00644 
00645     if (bufId == 0) {
00646         return -1;
00647     }
00648 
00649     tr_debug("MLE Child update response");
00650 
00651     thread_management_get_current_keysequence(cur->id, &keySequence);
00652     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00653 
00654     ptr = mle_service_get_data_pointer(bufId);
00655 
00656     mode = thread_mode_get_by_interface_ptr(cur);
00657 
00658     //Write Mode Allways
00659     ptr = mle_tlv_write_mode(ptr, mode);
00660     //Set SRC
00661     ptr = mle_general_write_source_address(ptr, cur);
00662     //SET leader data
00663     ptr = thread_leader_data_tlv_write(ptr, cur);
00664 
00665     //Set Addresss TLV
00666     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_ADDRESS_REGISTRATION) &&
00667           (mode & MLE_FFD_DEV) == 0) {
00668         ptr = thread_address_registration_tlv_write(ptr, cur);
00669     }
00670 
00671     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_TIMEOUT)) {
00672         ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
00673     }
00674 
00675     if (challengeTlv && challengeTlv->tlvLen) {
00676         ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen);
00677         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00678         //SET MLE Frame Counter
00679         ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00680     }
00681 
00682     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
00683         tr_debug("Buffer overflow at message write");
00684     }
00685     mle_service_set_msg_destination_address(bufId, dst_address);
00686     mle_service_send_message(bufId);
00687     return 0;
00688 }
00689 
00690 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
00691 {
00692     thread_leader_data_t leaderData;
00693     mle_tlv_info_t networkDataTlv;
00694     mle_tlv_info_t ConfigurationTlv;
00695     mle_tlv_info_t challengeTlv;
00696     mle_tlv_info_t tlv_req;
00697     uint64_t active_timestamp = 0;
00698     uint64_t pending_timestamp = 0;// means no pending timestamp
00699     mle_neigh_table_entry_t *entry_temp;
00700     bool data_request_needed = false;
00701 
00702     tr_debug("Child update request");
00703     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
00704 
00705     if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) ||
00706         !entry_temp ||
00707         !thread_check_is_this_my_parent(cur, entry_temp)) {
00708         // Dropped if no leader data or not from parent
00709         tr_warn("invalid message");
00710         return;
00711     }
00712     mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00713     mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
00714 
00715     // Check if partition changed
00716     if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00717         thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
00718         thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
00719         thread_old_partition_data_purge(cur);
00720     }
00721     //Check Network Data TLV
00722     if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00723        thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00724        thread_bootstrap_network_data_update(cur);
00725     }
00726 
00727     if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion ||
00728         thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) {
00729         // version numbers not in sync need to send data request
00730         data_request_needed = true;
00731     }
00732 
00733     // update operational datasets
00734     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00735     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00736         thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00737     }
00738     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00739     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00740         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00741     }
00742     // Check if operational datasets are in sync
00743     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp ||
00744         thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00745         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00746                 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00747                 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00748         data_request_needed = true;
00749     }
00750     thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req);
00751 
00752     if (data_request_needed) {
00753         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00754     }
00755 }
00756 
00757 static void thread_parse_child_update_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, uint8_t linkMargin)
00758 {
00759     uint8_t mode;
00760     uint32_t timeout;
00761     mle_neigh_table_entry_t *entry_temp;
00762     thread_leader_data_t leaderData = {0};
00763     uint8_t status;
00764     bool leader_data_received;
00765 
00766     tr_debug("Child Update Response");
00767 
00768     leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
00769     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false);
00770 
00771     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) &&
00772         status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) {
00773         tr_debug("parent has connection error");
00774         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00775         return;
00776     }
00777 
00778     if (!entry_temp) {
00779         tr_debug("Not Neighbor");
00780         mle_tlv_info_t challengeTlv;
00781         mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00782         thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
00783         return;
00784     }
00785 
00786     if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX)
00787             && (thread_instance_id_matches(cur, &leaderData))) {
00788         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00789     } else {
00790         tr_debug("Key ID Mode 2 not used; dropped.");
00791         return;
00792     }
00793 
00794     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
00795         tr_debug("No Mode");
00796         return;
00797     }
00798 
00799     if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
00800         entry_temp->holdTime = 90;
00801         tr_debug("Setting child timeout, value=%"PRIu32, timeout);
00802         mle_entry_timeout_update(entry_temp, timeout);
00803         thread_info(cur)->thread_endnode_parent->childUpdateProcessStatus = true;
00804     }
00805     tr_debug("Keep-Alive -->Respond from Parent");
00806     mle_entry_timeout_refresh(entry_temp);
00807 
00808     //Save possible new Leader Data
00809     if (leader_data_received) {
00810         thread_save_leader_data(cur, &leaderData);
00811     }
00812     mac_data_poll_protocol_poll_mode_decrement(cur);
00813 }
00814 
00815 #endif