Knight KE / Mbed OS Game_Master
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, NULL);
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         }
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_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data)
00241 {
00242     if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) {
00243         return true;
00244     }
00245     if (heard_partition_leader_data.weighting == thread_info(cur)->thread_leader_data->weighting &&
00246             heard_partition_leader_data.partitionId < thread_info(cur)->thread_leader_data->partitionId) {
00247         return true;
00248     }
00249     return false;
00250 }
00251 
00252 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)
00253 {
00254     //Read Leader Data and verify connectivity
00255     // Leader data is mandatory
00256     if (!thread_leader_data_parse(ptr, data_length, leaderData)) {
00257         return false;
00258     }
00259 
00260     if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) {
00261         return false;
00262     }
00263 
00264     if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) {
00265         if (thread_is_router_addr(*shortAddress)) {
00266             //Sender is reeds
00267             return false;
00268         }
00269         routeTlv->dataPtr = NULL;
00270         routeTlv->tlvLen = 0;
00271     }
00272     return true;
00273 }
00274 
00275 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)
00276 {
00277     if (!entry_temp) {
00278         return;
00279     }
00280 
00281     mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
00282 
00283     if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) {
00284         mle_entry_timeout_refresh(entry_temp);
00285     } else {
00286         entry_temp->last_contact_time = protocol_core_monotonic_time;
00287     }
00288 
00289     if (short_address != entry_temp->short_adr) {
00290         if (thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) {
00291             thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
00292             protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
00293         }
00294         entry_temp->short_adr = short_address;
00295         /* throw MLME_GET request, short address is changed automatically in get request callback */
00296         mlme_get_t get_req;
00297         get_req.attr = macDeviceTable;
00298         get_req.attr_index = entry_temp->attribute_index;
00299         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
00300     }
00301 
00302     return;
00303 }
00304 
00305 static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address)
00306 {
00307     if ((thread_info(cur)->thread_leader_data->partitionId != leader_data->partitionId) ||
00308         (thread_info(cur)->thread_leader_data->weighting != leader_data->weighting)) {
00309         //parent changed partition/weight - reset own routing information
00310         thread_old_partition_data_purge(cur);
00311     }
00312     //check if network data needs to be requested
00313     if (!thread_bootstrap_request_network_data(cur, leader_data, short_address)) {
00314         tr_debug("Parent short address changed - re-attach");
00315         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00316         return false;
00317     }
00318 
00319     return true;
00320 }
00321 
00322 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)
00323 {
00324     mle_tlv_info_t routeTlv;
00325     thread_leader_data_t leaderData;
00326     mle_neigh_table_entry_t *entry_temp;
00327     uint16_t shortAddress;
00328     bool adv_from_my_partition;
00329     bool my_parent;
00330 
00331     // Check device mode & bootstrap state
00332     if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) ||
00333         (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) {
00334         return;
00335     }
00336 
00337     tr_debug("Received Advertisement");
00338 
00339     // Validate and parse TLV's
00340     if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) {
00341         return;
00342     }
00343 
00344     // Get MLE entry
00345     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
00346 
00347     // Check if this is from my parent
00348     my_parent = thread_check_is_this_my_parent(cur, entry_temp);
00349 
00350     adv_from_my_partition = thread_instance_id_matches(cur, &leaderData);
00351 
00352     if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) {
00353         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00354     }
00355 
00356     if (entry_temp && !adv_from_my_partition && !my_parent ) {
00357         // Remove MLE entry that are located in other partition and is not my parent
00358         mle_class_remove_entry(cur->id, entry_temp);
00359         entry_temp = NULL;
00360     }
00361 
00362     /* Check parent status */
00363     if (!thread_attach_active_router(cur) && my_parent) {
00364         if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) {
00365             return;
00366         }
00367     }
00368 
00369     // Update MLE entry
00370     thread_update_mle_entry(cur, mle_msg, security_headers, entry_temp, shortAddress);
00371 
00372     // Process advertisement
00373     if (thread_info(cur)->thread_device_mode != THREAD_DEVICE_MODE_END_DEVICE) {
00374         /* REED and FED */
00375         if (!thread_attach_active_router(cur)) {
00376             /* Check if advertisement is from same partition */
00377             if (thread_info(cur)->thread_leader_data->weighting == leaderData.weighting && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId ) {
00378                 if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
00379                     // Create link to new neighbor no other processing allowed
00380                     thread_link_request_start(cur, mle_msg->packet_src_address);
00381                     return;
00382                 }
00383             /* Advertisement from higher / lower partition */
00384             } else {
00385                 // Check if better partition is heard
00386                 if (thread_bootstrap_partition_process(cur, thread_get_router_count_from_route_tlv(&routeTlv), &leaderData, &routeTlv) > 0) {
00387                     tr_debug("Start Merge");
00388                     thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
00389                     return;
00390                 }
00391 
00392                 // REED advertisement to lower partition to help merge faster
00393                 if (thread_heard_lower_partition(cur,leaderData)) {
00394                     thread_router_bootstrap_reed_merge_advertisement(cur);
00395                 }
00396             }
00397         /* ROUTER */
00398         } else {
00399             if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp) ) {
00400                 return;
00401             }
00402             thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress);
00403         }
00404     }
00405 
00406     // Process route TLV
00407     if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) &&
00408             (thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId)){
00409         tr_debug("Update Route TLV %x", entry_temp->short_adr);
00410         thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen , linkMargin, entry_temp);
00411     }
00412 }
00413 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)
00414 {
00415     uint32_t llFrameCounter;
00416     uint32_t mleFrameCounter;
00417     uint16_t version, shortAddress;
00418     uint16_t messageId;
00419     uint8_t linkMarginfronNeigh;
00420     mle_neigh_table_entry_t *entry_temp;
00421     bool createNew, new_entry_created;
00422 
00423     tr_info("MLE LINK ACCEPT");
00424 
00425     messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00426 
00427     if (messageId == 0) {
00428         tr_debug("No matching challenge");
00429         return;
00430     }
00431 
00432     if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) {
00433         //Free Response only if it is unicast
00434         mle_service_msg_free(messageId);
00435     }
00436 
00437     // TODO: Check missing TLV's
00438     if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
00439             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
00440             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
00441         return;
00442     }
00443 
00444     /* Call to determine whether or not we should create a new link */
00445     createNew = thread_bootstrap_link_create_check(cur, shortAddress);
00446 
00447     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry_created);
00448 
00449     if (!entry_temp) {
00450         thread_link_reject_send(cur, mle_msg->packet_src_address);
00451         return;
00452     }
00453 
00454     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00455         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00456     }
00457 
00458     //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
00459     if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) {
00460         mleFrameCounter = llFrameCounter;
00461     }
00462 
00463     entry_temp->threadNeighbor = true;
00464     entry_temp->short_adr = shortAddress;
00465     entry_temp->mle_frame_counter = mleFrameCounter;
00466     // Set full data as REED needs full data and SED will not make links
00467     entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
00468 
00469     mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry_created);
00470 
00471     if (entry_temp->timeout_rx) {
00472         mle_entry_timeout_refresh(entry_temp);
00473     } else {
00474         mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
00475     }
00476 
00477     if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->short_adr)) {
00478         // If we both are routers, mark the link as 2-way
00479         entry_temp->handshakeReady = 1;
00480         tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->handshakeReady);
00481     } else {
00482         tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->handshakeReady);
00483     }
00484 
00485     blacklist_update(mle_msg->packet_src_address, true);
00486 
00487     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
00488         thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
00489     }
00490 }
00491 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg)
00492 {
00493     uint64_t timestamp;
00494     uint16_t panid;
00495     uint8_t *ptr;
00496     uint8_t channel_page;
00497     uint16_t channel;
00498     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00499 
00500 
00501     tr_info("Recv Dataset Announce");
00502     if (8 > thread_tmfcop_tlv_data_get_uint64(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_ACTIVE_TIMESTAMP,&timestamp)) {
00503         tr_error("Missing timestamp TLV");
00504         return;
00505     }
00506     if (2 > thread_tmfcop_tlv_data_get_uint16(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_PANID,&panid)) {
00507         tr_error("Missing Panid TLV");
00508         return;
00509     }
00510     if (3 > thread_tmfcop_tlv_find(mle_msg->data_ptr, mle_msg->data_length,MLE_TYPE_CHANNEL,&ptr)) {
00511         tr_error("Missing Channel TLV");
00512         return;
00513     }
00514     channel_page = ptr[0];
00515     channel = common_read_16_bit(&ptr[1]);
00516 
00517     if (linkConfiguration->timestamp == timestamp) {
00518         // We received same timestamp
00519         tr_debug("Same timestamp");
00520         return;
00521     }
00522 
00523     if (cur->thread_info->announcement_info && cur->thread_info->announcement_info->timestamp == timestamp){
00524         // We received same timestamp again
00525         tr_debug("Processing announce with same timestamp");
00526         return;
00527     }
00528 
00529 
00530     if (linkConfiguration->timestamp > timestamp) {
00531         // We received older time stamp we just announce back to originator channel
00532         thread_bootstrap_announce_send(cur, linkConfiguration->channel_page, linkConfiguration->rfChannel, linkConfiguration->panId, linkConfiguration->timestamp, channel);
00533         return;
00534     }
00535 
00536     tr_debug("New configuration received");
00537     thread_bootstrap_temporary_attach(cur,channel_page, channel, panid, timestamp);
00538 }
00539 
00540 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
00541 {
00542     thread_leader_data_t leaderData;
00543     mle_tlv_info_t networkDataTlv;
00544     mle_tlv_info_t ConfigurationTlv;
00545     uint64_t active_timestamp = 0;
00546     uint64_t pending_timestamp = 0;// means no pending timestamp
00547     mle_neigh_table_entry_t *entry_temp;
00548     bool accept_new_data = false;
00549     bool leaderDataReceived;
00550 
00551     tr_debug("Data Response");
00552 
00553     if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00554         leaderDataReceived = true;
00555     } else {
00556         leaderDataReceived = false;
00557     }
00558     if (!leaderDataReceived) {
00559         tr_warn("no leader TLV");
00560         return;
00561     }
00562 
00563     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
00564 
00565     if(cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ||
00566             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
00567         if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) {
00568             // We are attached as child and just learn new data
00569             if (!thread_check_is_this_my_parent(cur, entry_temp)) {
00570                 return;
00571             }
00572         } else {
00573             if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00574                 // if receiving data response from different partition it is dropped
00575                 return;
00576             }
00577         }
00578     } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ||
00579             thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00580         if (!entry_temp) {
00581             tr_debug("Unknown neighbor");
00582             return;
00583         }
00584     }
00585 
00586     if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00587         thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
00588         thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
00589         thread_old_partition_data_purge(cur);
00590         accept_new_data = true;
00591     }
00592 
00593     //check response is for link metrics query
00594     thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length);
00595 
00596     if (cur->thread_info->networkDataRequested) {
00597         tr_debug("Requested network data received");
00598         cur->thread_info->networkDataRequested = false;
00599         accept_new_data = true;
00600     }
00601     if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) {
00602         tr_debug("Network data updated");
00603         accept_new_data = true;
00604     }
00605     // update operational datasets
00606 
00607     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00608     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00609         thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00610     }
00611     // TODO check if result is true then need to update all configurations
00612     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00613     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00614         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00615     }
00616     // Check if we are now in sync
00617     // if not matching must send data request again
00618     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp
00619             || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00620         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00621                 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00622                 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00623         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00624         return;
00625     }
00626     //Check Network Data TLV
00627     if (accept_new_data) {
00628         if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00629            thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00630            thread_bootstrap_network_data_update(cur);
00631         } else {
00632             tr_debug("SET NWK data Request state");
00633         }
00634     }
00635 
00636     // leader has finished synching network data after reset/restart
00637     if (cur->thread_info->leader_synced) {
00638         cur->thread_info->leader_synced = false;
00639         thread_leader_service_network_data_changed(cur, true, true);
00640     }
00641 }
00642 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)
00643 {
00644     uint16_t len = 150 + 64;
00645     uint8_t mode;
00646     uint32_t keySequence;
00647     uint8_t *ptr;
00648     if (!thread_info(cur)) {
00649         return -1;
00650     }
00651 
00652     uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE);
00653 
00654     if (bufId == 0) {
00655         return -1;
00656     }
00657 
00658     tr_debug("MLE Child update response");
00659 
00660     thread_management_get_current_keysequence(cur->id, &keySequence);
00661     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00662 
00663     ptr = mle_service_get_data_pointer(bufId);
00664 
00665     mode = thread_mode_get_by_interface_ptr(cur);
00666 
00667     //Write Mode Allways
00668     ptr = mle_tlv_write_mode(ptr, mode);
00669     //Set SRC
00670     ptr = mle_general_write_source_address(ptr, cur);
00671     //SET leader data
00672     ptr = thread_leader_data_tlv_write(ptr, cur);
00673 
00674     //Set Addresss TLV
00675     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_ADDRESS_REGISTRATION) &&
00676           (mode & MLE_FFD_DEV) == 0) {
00677         ptr = thread_address_registration_tlv_write(ptr, cur);
00678     }
00679 
00680     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr,requestTlv->tlvLen,MLE_TYPE_TIMEOUT)) {
00681         ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
00682     }
00683 
00684     if (challengeTlv && challengeTlv->tlvLen) {
00685         ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen);
00686         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00687         //SET MLE Frame Counter
00688         ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00689     }
00690 
00691     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
00692         tr_debug("Buffer overflow at message write");
00693     }
00694     mle_service_set_msg_destination_address(bufId, dst_address);
00695     mle_service_send_message(bufId);
00696     return 0;
00697 }
00698 
00699 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
00700 {
00701     thread_leader_data_t leaderData;
00702     mle_tlv_info_t networkDataTlv;
00703     mle_tlv_info_t ConfigurationTlv;
00704     mle_tlv_info_t challengeTlv;
00705     mle_tlv_info_t tlv_req;
00706     uint64_t active_timestamp = 0;
00707     uint64_t pending_timestamp = 0;// means no pending timestamp
00708     mle_neigh_table_entry_t *entry_temp;
00709     bool data_request_needed = false;
00710 
00711     tr_debug("Child update request");
00712     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
00713 
00714     if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) ||
00715         !entry_temp ||
00716         !thread_check_is_this_my_parent(cur, entry_temp)) {
00717         // Dropped if no leader data or not from parent
00718         tr_warn("invalid message");
00719         return;
00720     }
00721     mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00722     mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
00723 
00724     // Check if partition changed
00725     if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
00726         thread_info(cur)->thread_leader_data->leaderRouterId = leaderData.leaderRouterId;
00727         thread_info(cur)->thread_leader_data->partitionId = leaderData.partitionId;
00728         thread_old_partition_data_purge(cur);
00729     }
00730     //Check Network Data TLV
00731     if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00732        thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00733        thread_bootstrap_network_data_update(cur);
00734     }
00735 
00736     if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion ||
00737         thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) {
00738         // version numbers not in sync need to send data request
00739         data_request_needed = true;
00740     }
00741 
00742     // update operational datasets
00743     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00744     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00745         thread_active_operational_dataset_process(cur,ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00746     }
00747     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00748     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00749         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00750     }
00751     // Check if operational datasets are in sync
00752     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp ||
00753         thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00754         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00755                 active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00756                 pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00757         data_request_needed = true;
00758     }
00759     thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req);
00760 
00761     if (data_request_needed) {
00762         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00763     }
00764 }
00765 
00766 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)
00767 {
00768     uint8_t mode;
00769     uint32_t timeout;
00770     mle_neigh_table_entry_t *entry_temp;
00771     thread_leader_data_t leaderData = {0};
00772     uint8_t status;
00773     bool leader_data_received;
00774 
00775     if (cur->thread_info->thread_endnode_parent == NULL) {
00776         return;
00777     }
00778 
00779     tr_debug("Child Update Response");
00780 
00781     //mle_service_buffer_find
00782     leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
00783     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
00784 
00785     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) &&
00786         status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) {
00787         tr_debug("parent has connection error");
00788         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00789         return;
00790     }
00791 
00792     if (!entry_temp) {
00793         tr_debug("Not Neighbor");
00794         mle_tlv_info_t challengeTlv;
00795         mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00796         thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
00797         return;
00798     }
00799 
00800     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00801         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00802     } else {
00803         tr_debug("Key ID Mode 2 not used; dropped.");
00804         return;
00805     }
00806 
00807     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
00808         tr_debug("No Mode");
00809         return;
00810     }
00811 
00812     timeout = cur->thread_info->host_link_timeout;
00813     if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
00814         entry_temp->holdTime = 90;
00815         tr_debug("Setting child timeout, value=%"PRIu32, timeout);
00816         mle_entry_timeout_update(entry_temp, timeout);
00817     }
00818 
00819     tr_debug("Keep-Alive -->Respond from Parent");
00820     mle_entry_timeout_refresh(entry_temp);
00821 
00822     //Save possible new Leader Data
00823     if (leader_data_received) {
00824         thread_save_leader_data(cur, &leaderData);
00825     }
00826 
00827     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00828         if  (cur->thread_info->childUpdateReqTimer < 1) {
00829             cur->thread_info->childUpdateReqTimer = 0.8 * timeout;
00830         }
00831     }
00832     //This process is ready
00833     cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
00834     if (cur->thread_info->thread_endnode_parent->childUpdatePending) {
00835         tr_debug("Child Update Pending");
00836         thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
00837         return;
00838     }
00839 
00840     mac_data_poll_protocol_poll_mode_decrement(cur);
00841 
00842 }
00843 
00844 #endif