Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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-2019, 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 "string.h"
00034 #include "common_functions.h"
00035 #include "NWK_INTERFACE/Include/protocol.h"
00036 #include <nsdynmemLIB.h>
00037 #include "Service_Libs/mle_service/mle_service_api.h"
00038 #include "Service_Libs/blacklist/blacklist.h"
00039 #include "6LoWPAN/Thread/thread_config.h"
00040 #include "6LoWPAN/Thread/thread_common.h"
00041 #include "6LoWPAN/Thread/thread_lowpower_private_api.h"
00042 #include "6LoWPAN/Thread/thread_neighbor_class.h"
00043 #include "6LoWPAN/Thread/thread_mle_message_handler.h"
00044 #include "6LoWPAN/Thread/thread_bootstrap.h"
00045 #include "6LoWPAN/Thread/thread_management_internal.h"
00046 #include "6LoWPAN/Thread/thread_joiner_application.h"
00047 #include "6LoWPAN/Thread/thread_leader_service.h"
00048 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00049 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00050 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00051 #include "6LoWPAN/Thread/thread_network_synch.h"
00052 #include "6LoWPAN/Thread/thread_neighbor_class.h"
00053 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00054 #include "6LoWPAN/MAC/mac_helper.h"
00055 #include "6LoWPAN/MAC/mac_data_poll.h"
00056 #include "Common_Protocols/ipv6.h"
00057 #include "MLE/mle.h"
00058 #include "mac_api.h"
00059 #define TRACE_GROUP "thmh"
00060 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64);
00061 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, mac_neighbor_table_entry_t *neighbor);
00062 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);
00063 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData);
00064 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);
00065 static void thread_parse_annoucement(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg);
00066 static void thread_parse_data_response(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin);
00067 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin);
00068 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);
00069 
00070 /* Public functions */
00071 void thread_general_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00072 {
00073     /* TODO's:
00074      * - Any incoming link configuration or advertisement message, or an incoming update sent to a
00075      *   link-local address, whose IP Hop Limit is not 255, may have been forwarded by a Router
00076      *   and MUST be discarded.
00077      */
00078 
00079     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
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             mac_neighbor_table_entry_t *entry_temp;
00104             tr_warn("Reject Link");
00105             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
00106             if (entry_temp) {
00107                 mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), 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             thread_parse_child_update_response(cur, mle_msg, security_headers, linkMargin);
00129             break;
00130         }
00131 
00132         case MLE_COMMAND_PARENT_RESPONSE: {
00133             tr_debug("MLE parent response received");
00134             thread_mle_parent_discover_receive_cb(interface_id, mle_msg, security_headers);
00135             break;
00136         }
00137         default:
00138             if ((thread_am_host(cur) || thread_am_reed(cur)) && mle_msg->message_type == MLE_COMMAND_CHILD_UPDATE_REQUEST) {
00139                 // Thread host and router in REED mode answer the message same way. Routers only process messages from child
00140                 thread_host_child_update_request_process(cur, mle_msg, linkMargin);
00141             } else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
00142                 thread_router_bootstrap_mle_receive_cb(interface_id, mle_msg, security_headers);
00143             } else {
00144                 tr_warn("Not supported MLE message for host %d", mle_msg->message_type);
00145             }
00146     }
00147 
00148 }
00149 
00150 static void thread_save_leader_data(protocol_interface_info_entry_t *cur, thread_leader_data_t *leaderData)
00151 {
00152     if (thread_info(cur)->thread_leader_data) {
00153         bool requestNetworkdata = false;
00154         if (common_serial_number_greater_8(leaderData->dataVersion, thread_info(cur)->thread_leader_data->dataVersion)) {
00155             requestNetworkdata = true;
00156 
00157         } else if (common_serial_number_greater_8(leaderData->stableDataVersion, thread_info(cur)->thread_leader_data->stableDataVersion)) {
00158             requestNetworkdata = true;
00159         }
00160 
00161         if (!thread_partition_match(cur, leaderData)) {
00162             requestNetworkdata = true;
00163             thread_partition_info_update(cur, leaderData);
00164         }
00165 
00166         if (requestNetworkdata) {
00167             thread_bootstrap_parent_network_data_request(cur, false);
00168         } else {
00169             thread_info(cur)->thread_leader_data->stableDataVersion = leaderData->stableDataVersion;
00170             thread_info(cur)->thread_leader_data->dataVersion = leaderData->dataVersion;
00171         }
00172     }
00173 }
00174 
00175 static int8_t thread_link_request_start(protocol_interface_info_entry_t *cur, uint8_t *router_ll64)
00176 {
00177     mle_message_timeout_params_t timeout;
00178     uint32_t keySequence;
00179     uint16_t bufId = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
00180 
00181     if (bufId == 0) {
00182         return -1;
00183     }
00184 
00185     timeout.retrans_max = 2;
00186     timeout.timeout_init = 2;
00187     timeout.timeout_max = 3;
00188     timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00189 
00190     thread_management_get_current_keysequence(cur->id, &keySequence);
00191     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00192 
00193     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00194 
00195     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00196     ptr = mle_general_write_source_address(ptr, cur);
00197     ptr = thread_leader_data_tlv_write(ptr, cur);
00198 
00199     tr_debug("Synch Req");
00200 
00201     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00202         tr_debug("Buffer overflow at message write");
00203     }
00204 
00205     mle_service_set_packet_callback(bufId, thread_link_request_timeout);
00206     mle_service_set_msg_destination_address(bufId, router_ll64);
00207     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00208     mle_service_send_message(bufId);
00209     return 0;
00210 }
00211 
00212 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, mac_neighbor_table_entry_t *neighbor)
00213 {
00214     int leaderDataUpdate = thread_leader_data_validation(cur, leaderData, routeTlv);
00215 
00216     if (leaderDataUpdate == 1) {
00217         if (neighbor && neighbor->connected_device  == 1) {
00218             // Request network data if we have a 2-way link
00219             tr_debug("Request New Network Data from %s", trace_ipv6(src_address));
00220             thread_network_data_request_send(cur, src_address, true);
00221         }
00222     } else if (leaderDataUpdate == 2) {
00223         tr_debug("Start Merge");
00224         thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
00225         return false;
00226 
00227     } else if (leaderDataUpdate < 0) {
00228         tr_warn("Leader data failure");
00229         return false;
00230     }
00231     return true;
00232 }
00233 
00234 static bool thread_heard_lower_partition(protocol_interface_info_entry_t *cur, thread_leader_data_t heard_partition_leader_data)
00235 {
00236     if (heard_partition_leader_data.weighting < thread_info(cur)->thread_leader_data->weighting) {
00237         return true;
00238     }
00239     if (heard_partition_leader_data.weighting == thread_info(cur)->thread_leader_data->weighting &&
00240             heard_partition_leader_data.partitionId < thread_info(cur)->thread_leader_data->partitionId) {
00241         return true;
00242     }
00243     return false;
00244 }
00245 
00246 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)
00247 {
00248     //Read Leader Data and verify connectivity
00249     // Leader data is mandatory
00250     if (!thread_leader_data_parse(ptr, data_length, leaderData)) {
00251         return false;
00252     }
00253 
00254     if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, ptr, data_length, shortAddress)) {
00255         return false;
00256     }
00257 
00258     if (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, ptr, data_length, routeTlv)) {
00259         if (thread_is_router_addr(*shortAddress)) {
00260             //Sender is reeds
00261             return false;
00262         }
00263         routeTlv->dataPtr = NULL;
00264         routeTlv->tlvLen = 0;
00265     }
00266     return true;
00267 }
00268 
00269 static void thread_update_mle_entry(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, mle_security_header_t *security_headers, mac_neighbor_table_entry_t *entry_temp, uint16_t short_address)
00270 {
00271     if (!entry_temp) {
00272         return;
00273     }
00274 
00275     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
00276     mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex);
00277 
00278     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
00279     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00280 
00281     if (!thread_attach_active_router(cur) && !thread_check_is_this_my_parent(cur, entry_temp)) {
00282         mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
00283     }
00284 
00285     if (short_address != entry_temp->mac16 ) {
00286         if (thread_router_addr_from_addr(entry_temp->mac16 ) == cur->thread_info->routerShortAddress) {
00287             thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
00288             protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16 );
00289         }
00290         entry_temp->mac16  = short_address;
00291         /* throw MLME_GET request, short address is changed automatically in get request callback */
00292         mlme_get_t get_req;
00293         get_req.attr = macDeviceTable;
00294         get_req.attr_index = entry_temp->index ;
00295         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
00296     }
00297 
00298     return;
00299 }
00300 
00301 static bool thread_parse_advertisement_from_parent(protocol_interface_info_entry_t *cur, thread_leader_data_t *leader_data, uint16_t short_address)
00302 {
00303     //check if network data needs to be requested
00304     if (!thread_bootstrap_request_network_data(cur, leader_data, short_address)) {
00305         tr_debug("Parent short address changed - re-attach");
00306         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00307         return false;
00308     }
00309 
00310     return true;
00311 }
00312 
00313 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)
00314 {
00315     mle_tlv_info_t routeTlv;
00316     thread_leader_data_t leaderData;
00317     mac_neighbor_table_entry_t *entry_temp;
00318     uint16_t shortAddress;
00319     bool adv_from_my_partition;
00320     bool my_parent;
00321 
00322     // Check device mode & bootstrap state
00323     if ((thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) ||
00324             (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY)) {
00325         return;
00326     }
00327 
00328     tr_debug("Received Advertisement");
00329 
00330     // Validate and parse TLV's
00331     if (!thread_router_advertiment_tlv_analyze(mle_msg->data_ptr, mle_msg->data_length, &leaderData, &shortAddress, &routeTlv)) {
00332         return;
00333     }
00334 
00335     // Get MLE entry
00336     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
00337     if (entry_temp) {
00338         thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
00339         thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00340     }
00341 
00342     // Check if this is from my parent
00343     my_parent = thread_check_is_this_my_parent(cur, entry_temp);
00344 
00345     adv_from_my_partition = thread_partition_match(cur, &leaderData);
00346 
00347     if ((security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) && adv_from_my_partition) {
00348         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00349     }
00350 
00351     if (entry_temp && !adv_from_my_partition && !my_parent) {
00352         // Remove MLE entry that are located in other partition and is not my parent
00353         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
00354         entry_temp = NULL;
00355     }
00356 
00357     /* Check parent status */
00358     if (!thread_attach_active_router(cur) && my_parent) {
00359         if (!thread_parse_advertisement_from_parent(cur, &leaderData, shortAddress)) {
00360             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
00361             return;
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         /* REED and FED */
00371         if (!thread_attach_active_router(cur)) {
00372             /* Check if advertisement is from same partition */
00373             if (thread_partition_match(cur, &leaderData)) {
00374                 if (!entry_temp && thread_bootstrap_link_create_check(cur, shortAddress) && thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
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                 /* Advertisement from higher / lower partition */
00380             } else {
00381                 // Check if better partition is heard
00382                 if (thread_bootstrap_partition_process(cur, thread_get_router_count_from_route_tlv(&routeTlv), &leaderData, &routeTlv) > 0) {
00383                     tr_debug("Start Merge");
00384                     thread_bootstrap_connection_error(cur->id, CON_ERROR_PARTITION_MERGE, NULL);
00385                     return;
00386                 }
00387 
00388                 // REED advertisement to lower partition to help merge faster
00389                 if (thread_heard_lower_partition(cur, leaderData)) {
00390                     thread_router_bootstrap_reed_merge_advertisement(cur);
00391                 }
00392             }
00393             /* ROUTER */
00394         } else {
00395             if (!thread_router_leader_data_process(cur, mle_msg->packet_src_address, &leaderData, &routeTlv, entry_temp)) {
00396                 return;
00397             }
00398             thread_router_bootstrap_advertiment_analyze(cur, mle_msg->packet_src_address, entry_temp, shortAddress);
00399         }
00400     }
00401 
00402     // Process route TLV
00403     if ((entry_temp && routeTlv.dataPtr && routeTlv.tlvLen) && thread_partition_match(cur, &leaderData)) {
00404         tr_debug("Update Route TLV %x", entry_temp->mac16 );
00405         thread_router_bootstrap_route_tlv_push(cur, routeTlv.dataPtr, routeTlv.tlvLen, linkMargin, entry_temp);
00406     }
00407 }
00408 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)
00409 {
00410     uint32_t llFrameCounter;
00411     uint32_t mleFrameCounter;
00412     uint16_t version, shortAddress;
00413     uint16_t messageId;
00414     uint8_t linkMarginfronNeigh;
00415     mac_neighbor_table_entry_t *entry_temp;
00416     bool createNew, new_entry_created;
00417 
00418     tr_info("MLE LINK ACCEPT");
00419 
00420     messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00421 
00422     if (messageId == 0) {
00423         tr_debug("No matching challenge");
00424         return;
00425     }
00426 
00427     if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) {
00428         //Free Response only if it is unicast
00429         mle_service_msg_free(messageId);
00430     }
00431 
00432     // TODO: Check missing TLV's
00433     if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
00434             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
00435             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
00436         return;
00437     }
00438 
00439     /* Call to determine whether or not we should create a new link */
00440     createNew = thread_bootstrap_link_create_check(cur, shortAddress);
00441 
00442     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, createNew, &new_entry_created);
00443 
00444     if (!entry_temp) {
00445         thread_link_reject_send(cur, mle_msg->packet_src_address);
00446         return;
00447     }
00448     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, new_entry_created);
00449     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00450 
00451     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00452         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00453     }
00454 
00455     //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
00456     if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter))) {
00457         mleFrameCounter = llFrameCounter;
00458     }
00459 
00460     entry_temp->mac16  = shortAddress;
00461     mle_service_frame_counter_entry_add(cur->id, entry_temp->index , mleFrameCounter);
00462     // Set full data as REED needs full data and SED will not make links
00463     thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index , true);
00464     mlme_device_descriptor_t device_desc;
00465     mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 , llFrameCounter, false);
00466     mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , security_headers->KeyIndex, new_entry_created);
00467     uint32_t timeout;
00468 
00469     if (new_entry_created) {
00470         timeout = THREAD_DEFAULT_LINK_LIFETIME;
00471     } else {
00472         timeout = entry_temp->link_lifetime ;
00473     }
00474 
00475     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
00476 
00477     if (thread_i_am_router(cur) && thread_is_router_addr(entry_temp->mac16 )) {
00478         // If we both are routers, mark the link as 2-way
00479         entry_temp->connected_device  = 1;
00480         tr_debug("Marked link as 2-way, handshakeReady=%d", entry_temp->connected_device );
00481     } else {
00482         tr_debug("Marked link as 1-way, handshakeReady=%d", entry_temp->connected_device );
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->mac16 , 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 && 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 && 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     mac_neighbor_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 = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
00564 
00565     if (entry_temp) {
00566         thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
00567         thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00568     }
00569 
00570     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER ||
00571             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
00572         if (thread_info(cur)->thread_attached_state == THREAD_STATE_CONNECTED) {
00573             // We are attached as child and just learn new data
00574             if (!thread_check_is_this_my_parent(cur, entry_temp)) {
00575                 return;
00576             }
00577         } else {
00578             if (!thread_partition_match(cur, &leaderData)) {
00579                 // if receiving data response from different partition it is dropped
00580                 return;
00581             }
00582         }
00583     } else if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE ||
00584                thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00585         if (!entry_temp) {
00586             tr_debug("Unknown neighbor");
00587             return;
00588         }
00589     }
00590 
00591     if (!thread_partition_match(cur, &leaderData)) {
00592         thread_partition_info_update(cur, &leaderData);
00593         accept_new_data = true;
00594     }
00595 
00596     //check response is for link metrics query
00597     thread_lowpower_process_response(mle_msg->packet_src_address, cur->id, mle_msg->data_ptr, mle_msg->data_length);
00598 
00599     if (cur->thread_info->networkDataRequested) {
00600         tr_debug("Requested network data received");
00601         cur->thread_info->networkDataRequested = false;
00602         accept_new_data = true;
00603     }
00604     if (1 == thread_leader_data_validation(cur, &leaderData, NULL)) {
00605         tr_debug("Network data updated");
00606         accept_new_data = true;
00607     }
00608     // update operational datasets
00609 
00610     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00611     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00612         thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00613     }
00614     // TODO check if result is true then need to update all configurations
00615     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00616     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00617         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00618     }
00619     // Check if we are now in sync
00620     // if not matching must send data request again
00621     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp
00622             || thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00623         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00624                  active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00625                  pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00626         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00627         return;
00628     }
00629     //Check Network Data TLV
00630     if (accept_new_data) {
00631         if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00632             thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00633             thread_bootstrap_network_data_update(cur);
00634         } else {
00635             tr_debug("SET NWK data Request state");
00636         }
00637     }
00638 
00639     // leader has finished synching network data after reset/restart
00640     if (cur->thread_info->leader_synced) {
00641         cur->thread_info->leader_synced = false;
00642         thread_leader_service_network_data_changed(cur, true, true);
00643     }
00644 }
00645 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)
00646 {
00647     uint16_t len = 150 + 64;
00648     uint8_t mode;
00649     uint32_t keySequence;
00650     uint8_t *ptr;
00651     if (!thread_info(cur)) {
00652         return -1;
00653     }
00654 
00655     uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE);
00656 
00657     if (bufId == 0) {
00658         return -1;
00659     }
00660 
00661     tr_debug("MLE Child update response");
00662 
00663     thread_management_get_current_keysequence(cur->id, &keySequence);
00664     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00665 
00666     ptr = mle_service_get_data_pointer(bufId);
00667 
00668     mode = thread_mode_get_by_interface_ptr(cur);
00669 
00670     //Write Mode Allways
00671     ptr = mle_tlv_write_mode(ptr, mode);
00672     //Set SRC
00673     ptr = mle_general_write_source_address(ptr, cur);
00674     //SET leader data
00675     ptr = thread_leader_data_tlv_write(ptr, cur);
00676 
00677     //Set Addresss TLV
00678     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr, requestTlv->tlvLen, MLE_TYPE_ADDRESS_REGISTRATION) &&
00679             (mode & MLE_FFD_DEV) == 0) {
00680         ptr = thread_address_registration_tlv_write(ptr, cur);
00681     }
00682 
00683     if (requestTlv && mle_tlv_requested(requestTlv->dataPtr, requestTlv->tlvLen, MLE_TYPE_TIMEOUT)) {
00684         ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
00685     }
00686 
00687     if (challengeTlv && challengeTlv->tlvLen) {
00688         ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen);
00689         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00690         //SET MLE Frame Counter
00691         ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00692     }
00693 
00694     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00695         tr_debug("Buffer overflow at message write");
00696     }
00697     mle_service_set_msg_destination_address(bufId, dst_address);
00698     mle_service_send_message(bufId);
00699     return 0;
00700 }
00701 
00702 static bool thread_address_registration_tlv_search(if_address_entry_t *entry, mle_tlv_info_t *tlv_info)
00703 {
00704     uint8_t context;
00705     uint16_t length = tlv_info->tlvLen;
00706     uint8_t *ptr = tlv_info->dataPtr;
00707 
00708     while (length) {
00709         context = *ptr++;
00710         if (context & 0x80) {
00711             if (memcmp(ptr, entry->address + 8, 8) == 0) {
00712                 return true;
00713             }
00714             ptr += 8;
00715             length -= 9;
00716         } else {
00717             if (memcmp(ptr, entry->address, 16) == 0) {
00718                 return true;
00719             }
00720             ptr += 16;
00721             length -= 17;
00722         }
00723     }
00724 
00725     return false;
00726 
00727 }
00728 
00729 static bool thread_address_registration_tlv_check(protocol_interface_info_entry_t *cur, mle_tlv_info_t *tlv_info)
00730 {
00731     bool ret_val = true;
00732 
00733     ns_list_foreach_safe(if_address_entry_t, e, &cur->ip_addresses) {
00734         if (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_GLOBAL || (addr_ipv6_scope(e->address, cur) == IPV6_SCOPE_REALM_LOCAL &&
00735                                                                       !thread_addr_is_mesh_local_16(e->address, cur))) {
00736 
00737             if (thread_address_registration_tlv_search(e, tlv_info) == false) {
00738                 tr_debug("Address %s registration to parent failed", trace_ipv6(e->address));
00739                 addr_set_preferred_lifetime(cur, e, 0); // deprecate address
00740                 ret_val = false;
00741             } else if (e->preferred_lifetime == 0) {
00742                 addr_set_preferred_lifetime(cur, e, 0xffffffff); // set preferred lifetime to infinite
00743             }
00744         }
00745     }
00746     thread_bootstrap_child_address_registration_response_process(cur);
00747 
00748     return ret_val;
00749 }
00750 
00751 static void thread_host_child_update_request_process(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t linkMargin)
00752 {
00753     thread_leader_data_t leaderData;
00754     mle_tlv_info_t networkDataTlv;
00755     mle_tlv_info_t ConfigurationTlv;
00756     mle_tlv_info_t challengeTlv;
00757     mle_tlv_info_t tlv_req;
00758     uint64_t active_timestamp = 0;
00759     uint64_t pending_timestamp = 0;// means no pending timestamp
00760     mac_neighbor_table_entry_t *entry_temp;
00761     bool data_request_needed = false;
00762     mle_tlv_info_t tlv_info = {MLE_TYPE_SRC_ADDRESS, 0, 0};
00763 
00764     tr_debug("Child update request");
00765     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
00766 
00767     if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData) ||
00768             !entry_temp ||
00769             !thread_check_is_this_my_parent(cur, entry_temp)) {
00770         // Dropped if no leader data or not from parent
00771         tr_warn("invalid message");
00772         return;
00773     }
00774 
00775     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
00776     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00777 
00778     mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00779     mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
00780 
00781     // Check if partition changed
00782     if (!thread_partition_match(cur, &leaderData)) {
00783         thread_partition_info_update(cur, &leaderData);
00784     }
00785     //Check Network Data TLV
00786     if (mle_tlv_read_tlv(MLE_TYPE_NETWORK_DATA, mle_msg->data_ptr, mle_msg->data_length, &networkDataTlv)) {
00787         thread_bootstrap_network_data_save(cur, &leaderData, networkDataTlv.dataPtr, networkDataTlv.tlvLen);
00788         thread_bootstrap_network_data_update(cur);
00789     }
00790 
00791     // Check Address Registration TLV
00792     if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) {
00793         thread_address_registration_tlv_check(cur, &tlv_info);
00794     }
00795 
00796     if (thread_info(cur)->thread_leader_data->stableDataVersion != leaderData.stableDataVersion ||
00797             thread_info(cur)->thread_leader_data->dataVersion != leaderData.dataVersion) {
00798         // version numbers not in sync need to send data request
00799         data_request_needed = true;
00800     }
00801 
00802     // update operational datasets
00803     mle_tlv_read_tlv(MLE_TYPE_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00804     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp)) {
00805         thread_active_operational_dataset_process(cur, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen, active_timestamp);
00806     }
00807     mle_tlv_read_tlv(MLE_TYPE_PENDING_OPERATIONAL_DATASET, mle_msg->data_ptr, mle_msg->data_length, &ConfigurationTlv);
00808     if (mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp)) {
00809         thread_pending_operational_dataset_process(cur, pending_timestamp, ConfigurationTlv.dataPtr, ConfigurationTlv.tlvLen);
00810     }
00811     // Check if operational datasets are in sync
00812     if (thread_joiner_application_active_timestamp_get(cur->id) < active_timestamp ||
00813             thread_joiner_application_pending_config_timestamp_get(cur->id) < pending_timestamp) {
00814         tr_debug("Request new network data with configurations active %"PRIX64", %"PRIX64" Pending %"PRIX64", %"PRIX64,
00815                  active_timestamp, thread_joiner_application_active_timestamp_get(cur->id),
00816                  pending_timestamp, thread_joiner_application_pending_config_timestamp_get(cur->id));
00817         data_request_needed = true;
00818     }
00819     thread_host_child_update_response_send(cur, mle_msg->packet_src_address, &challengeTlv, &tlv_req);
00820 
00821     if (data_request_needed) {
00822         thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00823     }
00824 }
00825 
00826 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)
00827 {
00828     uint8_t mode;
00829     uint32_t timeout;
00830     mac_neighbor_table_entry_t *entry_temp;
00831     thread_leader_data_t leaderData = {0};
00832     uint8_t status;
00833     bool leader_data_received;
00834     mle_tlv_info_t tlv_info = {MLE_TYPE_SRC_ADDRESS, 0, 0};
00835 
00836     if (cur->thread_info->thread_endnode_parent == NULL) {
00837         return;
00838     }
00839 
00840     tr_debug("Child Update Response");
00841 
00842     //mle_service_buffer_find
00843     leader_data_received = thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData);
00844     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
00845 
00846     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status) &&
00847             status == 1 && thread_check_is_this_my_parent(cur, entry_temp)) {
00848         tr_debug("parent has connection error");
00849         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
00850         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
00851         return;
00852     }
00853 
00854     if (!entry_temp) {
00855         tr_debug("Not Neighbor");
00856         mle_tlv_info_t challengeTlv;
00857         mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
00858         thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
00859         return;
00860     }
00861 
00862     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00863         thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
00864         thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00865         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00866     } else {
00867         tr_debug("Key ID Mode 2 not used; dropped.");
00868         return;
00869     }
00870 
00871     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
00872         tr_debug("No Mode");
00873         return;
00874     }
00875 
00876     timeout = cur->thread_info->host_link_timeout;
00877     if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
00878         tr_debug("Setting child timeout, value=%"PRIu32, timeout);
00879     }
00880 
00881     if (true == mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &tlv_info)) {
00882         thread_address_registration_tlv_check(cur, &tlv_info);
00883     }
00884 
00885     tr_debug("Keep-Alive -->Respond from Parent");
00886     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
00887 
00888     //Save possible new Leader Data
00889     if (leader_data_received) {
00890         thread_save_leader_data(cur, &leaderData);
00891     }
00892 
00893     if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) {
00894         if (cur->thread_info->childUpdateReqTimer < 1) {
00895             cur->thread_info->childUpdateReqTimer = 0.8 * timeout;
00896         }
00897     }
00898     //This process is ready
00899     cur->thread_info->thread_endnode_parent->childUpdateProcessActive = false;
00900     if (cur->thread_info->thread_endnode_parent->childUpdatePending) {
00901         tr_debug("Child Update Pending");
00902         thread_bootsrap_event_trig(THREAD_CHILD_UPDATE, cur->bootStrapId, ARM_LIB_HIGH_PRIORITY_EVENT);
00903         return;
00904     }
00905 
00906     mac_data_poll_protocol_poll_mode_decrement(cur);
00907 
00908 }
00909 
00910 #endif