EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

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