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_router_bootstrap.c Source File

thread_router_bootstrap.c

00001 /*
00002  * Copyright (c) 2015-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 
00030 /*
00031  * \file thread_router_bootstrap.c
00032  * \brief Add short description about this file!!!
00033  *
00034  */
00035 #include "nsconfig.h"
00036 #include <string.h>
00037 #include <ns_types.h>
00038 #include <ns_list.h>
00039 #include <nsdynmemLIB.h>
00040 #include "eventOS_event.h"
00041 #include "eventOS_event_timer.h"
00042 #include "randLIB.h"
00043 #include "shalib.h"
00044 #include "common_functions.h"
00045 #include "NWK_INTERFACE/Include/protocol.h"
00046 #include "net_thread_test.h"
00047 #include "ns_trace.h"
00048 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00049 #include "6LoWPAN/Thread/thread_common.h"
00050 #include "6LoWPAN/Thread/thread_routing.h"
00051 #include "6LoWPAN/Thread/thread_nd.h"
00052 #include "6LoWPAN/Thread/thread_bootstrap.h"
00053 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00054 #include "6LoWPAN/Thread/thread_host_bootstrap.h"
00055 #include "6LoWPAN/Thread/thread_management_internal.h"
00056 #include "6LoWPAN/Thread/thread_network_synch.h"
00057 #include "6LoWPAN/Thread/thread_discovery.h"
00058 #include "6LoWPAN/Thread/thread_joiner_application.h"
00059 #include "6LoWPAN/Thread/thread_management_client.h"
00060 #include "6LoWPAN/Thread/thread_management_server.h"
00061 #include "6LoWPAN/Thread/thread_leader_service.h"
00062 #include "6LoWPAN/Thread/thread_beacon.h"
00063 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00064 #include "6LoWPAN/Thread/thread_lowpower_private_api.h"
00065 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00066 #include "6LoWPAN/Thread/thread_nvm_store.h"
00067 #include "6LoWPAN/Thread/thread_neighbor_class.h"
00068 #include "6LoWPAN/Thread/thread_ccm.h"
00069 #include "thread_management_if.h"
00070 #include "Common_Protocols/ipv6.h"
00071 #include "Common_Protocols/icmpv6.h"
00072 #include "Common_Protocols/icmpv6_radv.h"
00073 #include "MLE/mle.h"
00074 #include "MLE/mle_tlv.h"
00075 #include "thread_config.h"
00076 #include "multicast_api.h"
00077 #include "Service_Libs/nd_proxy/nd_proxy.h"
00078 #include "Service_Libs/mle_service/mle_service_api.h"
00079 #include "Service_Libs/blacklist/blacklist.h"
00080 #include "DHCPv6_client/dhcpv6_client_api.h"
00081 #include "6LoWPAN/MAC/mac_helper.h"
00082 #include "mac_api.h"
00083 #include "6LoWPAN/MAC/mac_data_poll.h"
00084 #include "thread_border_router_api.h"
00085 #include "Core/include/ns_address_internal.h"
00086 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00087 
00088 #ifdef HAVE_THREAD_ROUTER
00089 
00090 #define TRACE_GROUP "trbs"
00091 
00092 static uint8_t *thread_tlv_add(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint8_t tlv_type, uint8_t mode);
00093 
00094 static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf);
00095 
00096 static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9]);
00097 static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
00098 static void thread_bootstrap_client_router_id_release_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9]);
00099 
00100 static int thread_router_synch_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t *tlvReq, uint8_t tlvReqLen);
00101 static int thread_router_accept_to_endevice(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t *challenge, uint8_t chalLen);
00102 static int thread_router_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t type, bool rssi_tlv, uint8_t rssi);
00103 static int thread_child_update_response(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t mode, uint16_t short_address, uint32_t timeout, mle_tlv_info_t *addressRegisterTlv, mle_tlv_info_t *tlvReq, mle_tlv_info_t *challengeTlv, uint64_t active_timestamp, uint64_t pending_timestamp);
00104 static int mle_build_and_send_data_response_msg(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t *data_ptr, uint16_t data_len, mle_tlv_info_t *request_tlv, uint8_t mode);
00105 static int thread_attach_parent_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, uint8_t *challenge, uint16_t chalLen, uint8_t linkMargin, uint8_t scanMask, uint8_t mode);
00106 static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, thread_pending_child_id_req_t *child_req, struct mac_neighbor_table_entry *neigh_info);
00107 
00108 static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info_entry_t *cur);
00109 static bool thread_child_id_request(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *entry_temp);
00110 
00111 
00112 #ifdef HAVE_THREAD_V2
00113 static bool thread_router_bootstrap_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur);
00114 #else
00115 #define thread_router_bootstrap_is_reed_upgrade_allowed(cur) (true)
00116 #endif
00117 
00118 static bool thread_router_parent_address_check(protocol_interface_info_entry_t *cur, uint8_t *source_addr)
00119 {
00120     if (thread_info(cur)->thread_endnode_parent &&
00121             addr_iid_matches_eui64(source_addr + 8, thread_info(cur)->thread_endnode_parent->mac64)) {
00122         return true;
00123     }
00124 
00125     return false;
00126 }
00127 
00128 static void thread_send_proactive_an(protocol_interface_info_entry_t *cur)
00129 {
00130     ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
00131         if (e->source == ADDR_SOURCE_DHCP || e->source == ADDR_SOURCE_SLAAC) {
00132             uint8_t br_ml_addr[16];
00133             ns_list_foreach(thread_network_data_prefix_cache_entry_t, prefix, &cur->thread_info->networkDataStorage.localPrefixList) {
00134                 uint8_t prefixBytesLen = prefixBits_to_bytes(prefix->servicesPrefixLen);
00135 
00136                 if (memcmp(e->address, prefix->servicesPrefix, prefixBytesLen) != 0) {
00137                     continue;
00138                 }
00139 
00140                 ns_list_foreach(thread_network_server_data_entry_t, br, &prefix->borderRouterList) {
00141                     if (br->routerID == 0xfffe) {
00142                         continue;
00143                     }
00144 
00145                     uint16_t rloc16 = mac_helper_mac16_address_get(cur);
00146 
00147                     thread_addr_write_mesh_local_16(br_ml_addr, br->routerID, cur->thread_info);
00148                     tr_debug("Sending proactive AN to border router: %s", trace_ipv6(br_ml_addr));
00149                     thread_management_client_proactive_an(cur->id, e->address, rloc16, cur->iid_slaac, br_ml_addr);
00150                 }
00151             }
00152         }
00153     }
00154 }
00155 
00156 int thread_router_bootstrap_mle_advertise(protocol_interface_info_entry_t *cur)
00157 {
00158     /* How was this 40 calculated? Seems to be more than enough, at least.
00159      * MODE = 2+1, SRC_ADDR = 2+2, LINK = 2+1+4*neighbours, ROUTE = 2+MLE_ROUTE_MIN_OPTION_LEN+routers
00160      * Total = 10 + neighbours * 4
00161      */
00162     uint16_t neig_cache_size = 40 + 3;
00163     uint8_t *ptr;
00164 
00165     if (!cur) {
00166         return -1;
00167     }
00168 
00169     if (!thread_is_connected(cur)) {
00170         return -1;
00171     }
00172 
00173     if (thread_i_am_router(cur)) {
00174         neig_cache_size += thread_route_option_size(cur);
00175         neig_cache_size += thread_leader_data_tlv_size(cur);
00176     }
00177 
00178     uint16_t buf_id = mle_service_msg_allocate(cur->id, neig_cache_size, false, MLE_COMMAND_ADVERTISEMENT);
00179     if (buf_id == 0) {
00180         return -1;
00181     }
00182 
00183     uint32_t keySequence;
00184     if (thread_management_get_current_keysequence(cur->id, &keySequence) == 0) {
00185         mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
00186     }
00187 
00188     //SET Destination address
00189     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_NODES);
00190 
00191     ptr = mle_service_get_data_pointer(buf_id);
00192     ptr = mle_general_write_source_address(ptr, cur);
00193     if (thread_i_am_router(cur)) {
00194         ptr = thread_route_option_write(cur, ptr);
00195     } else {
00196         *ptr++ = MLE_TYPE_ROUTE;
00197         *ptr++ = 0;
00198     }
00199 
00200     ptr = thread_leader_data_tlv_write(ptr, cur);
00201 
00202     if (mle_service_update_length_by_ptr(buf_id, ptr) != 0) {
00203         tr_debug("Buffer overflow at message write");
00204     }
00205 
00206     tr_debug("Send MLE Secured Advertisement");
00207     return mle_service_send_message(buf_id);
00208 
00209 }
00210 
00211 static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry, buffer_t *buf)
00212 {
00213     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00214     if (!linkConfiguration) {
00215         return;
00216     }
00217 
00218     buffer_t *new_buf = buffer_clone(buf);
00219     if ((new_buf->info  & B_DIR_MASK) == B_DIR_UP) {
00220         buffer_data_pointer(new_buf)[IPV6_HDROFF_HOP_LIMIT] = --new_buf->options .hop_limit ;
00221     }
00222 
00223     new_buf->info  = (buffer_info_t)(B_DIR_DOWN | B_TO_IPV6_TXRX | B_FROM_IPV6_FWD);
00224     uint8_t next_hop[16];
00225     memcpy(next_hop, ADDR_LINK_LOCAL_PREFIX, 8);
00226     memcpy(&next_hop[8], entry->mac64 , 8);
00227     next_hop[8] ^= 2;
00228 
00229     ipv6_buffer_route_to(new_buf, next_hop, cur);
00230     protocol_push(new_buf);
00231     tr_debug("Cloned %s to %s", tr_ipv6(buf->dst_sa .address ), tr_ipv6(next_hop));
00232 }
00233 
00234 static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf)
00235 {
00236     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
00237 
00238     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
00239         if (!cur_entry->rx_on_idle) {
00240             clone_multicast_to_unicast(cur, cur_entry, buf);
00241         }
00242     }
00243 }
00244 
00245 static void thread_multicast_forward_to_child(protocol_interface_info_entry_t *cur, buffer_t *buffer)
00246 {
00247     mle_multicast_push_to_sleep_child(cur, buffer);
00248 }
00249 
00250 static void thread_registered_mcast_forward_to_child(protocol_interface_info_entry_t *cur, buffer_t *buffer)
00251 {
00252     thread_registered_mcast_addr_t *addr = thread_registered_mcast_addr_entry_find(cur, buffer->dst_sa .address );
00253 
00254     if (addr) {
00255         tr_debug("Forwarding to registered multicast address: %s", trace_ipv6(addr->address));
00256 
00257         ns_list_foreach(thread_mcast_child_t, child, &addr->children) {
00258             mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), child->mac64, ADDR_802_15_4_LONG );
00259             if (entry && !entry->rx_on_idle ) {
00260                 clone_multicast_to_unicast(cur, entry, buffer);
00261             }
00262         }
00263     }
00264 }
00265 
00266 void thread_router_bootstrap_multicast_forwarder_enable(protocol_interface_info_entry_t *cur, buffer_t *buf)
00267 {
00268     //tr_debug("Considering forward %s (%s)", tr_ipv6(buf->dst_sa.address), (buf->info & B_DIR_MASK) == B_DIR_UP ? "up" : "down");
00269     if (addr_ipv6_multicast_scope(buf->dst_sa .address ) <= IPV6_SCOPE_INTERFACE_LOCAL) {
00270         return;
00271     }
00272 
00273     // Safe guard: do NOT forward received link-local
00274     // multicast packets to our sleepy children
00275     if ((buf->info  & B_DIR_MASK) == B_DIR_UP &&
00276             addr_ipv6_multicast_scope(buf->dst_sa .address ) <= IPV6_SCOPE_LINK_LOCAL) {
00277         tr_debug("Received link-local multicast; return...");
00278         return;
00279     }
00280 
00281     uint8_t addr[16];
00282     thread_bootstrap_all_nodes_address_generate(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
00283     if (addr_ipv6_equal(buf->dst_sa .address , addr)) {
00284         thread_multicast_forward_to_child(cur, buf);
00285         return;
00286     }
00287     thread_bootstrap_all_nodes_address_generate(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
00288     if (addr_ipv6_equal(buf->dst_sa .address , addr)) {
00289         thread_multicast_forward_to_child(cur, buf);
00290         return;
00291     }
00292     thread_registered_mcast_forward_to_child(cur, buf);
00293 }
00294 
00295 static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00296 {
00297     thread_leader_data_t leaderData;
00298     uint8_t linkMarginfronNeigh;
00299     uint16_t version, shortAddress, address16;
00300     uint32_t llFrameCounter;
00301     mle_tlv_info_t routing;
00302     mac_neighbor_table_entry_t *entry_temp;
00303     tr_debug("Thread MLE message router sync");
00304     //State machine What packet shuold accept in this case
00305     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
00306 
00307     /* Check that message is from link-local scope */
00308     if (!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00309         return;
00310     }
00311 
00312     if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00313         return;
00314     }
00315 
00316     //Validate ready TLV for router Synch
00317     if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
00318             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, mle_msg->data_ptr, mle_msg->data_length, &address16)) ||
00319             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
00320             (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, mle_msg->data_ptr, mle_msg->data_length, &routing)) ||
00321             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
00322         return ;
00323     }
00324 
00325     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
00326 
00327     switch (mle_msg->message_type) {
00328         case MLE_COMMAND_ACCEPT: {
00329             tr_info("Accept (ROUTER handler)");
00330             uint32_t mleFrameCounter;
00331             bool new_neigbour;
00332             uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00333 
00334             if (messageId == 0) {
00335                 tr_debug("No matching challenge");
00336                 return;
00337             }
00338             /*Link accept command has an optional MLE Frame counter TLV, if this is not present use link layer frame counter TLV
00339              * as MLE frame counter TLV*/
00340             if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter)) {
00341                 mleFrameCounter = llFrameCounter;
00342             }
00343 
00344             if (!thread_is_router_addr(address16)) {
00345                 return;
00346             }
00347             //Allocate neighbor entry
00348             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, true, &new_neigbour);
00349             if (!entry_temp) {
00350                 return;
00351             }
00352 
00353             if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
00354                 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
00355                 thread_key_guard_timer_reset(cur);
00356             } else {
00357                 tr_error("Key ID Mode 2 not used; dropped.");
00358                 return;
00359             }
00360 
00361             thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, new_neigbour);
00362             thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
00363 
00364             //Free Response
00365             mle_service_msg_free(messageId);
00366             entry_temp->mac16  = shortAddress;
00367 
00368             //when allocating neighbour entry, use MLE Frame counter if present to validate further advertisements from the neighbour
00369             mle_service_frame_counter_entry_add(cur->id, entry_temp->index , mleFrameCounter);
00370             uint32_t timeout_tlv;
00371 
00372             mle_tlv_info_t mle_tlv_info;
00373 
00374             if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_TIMEOUT, &mle_tlv_info) > 0) {
00375                 timeout_tlv = common_read_32_bit(mle_tlv_info.dataPtr);
00376             } else {
00377                 if (new_neigbour) {
00378                     timeout_tlv = THREAD_DEFAULT_LINK_LIFETIME;
00379                 } else {
00380                     timeout_tlv = entry_temp->link_lifetime ;
00381                 }
00382             }
00383 
00384             mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout_tlv);
00385 
00386             if (thread_is_router_addr(shortAddress)) {
00387                 entry_temp->connected_device  = 1;
00388             }
00389             thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index , true);
00390 
00391             if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
00392                 thread_routing_update_link_margin(cur, entry_temp->mac16 , linkMargin, linkMarginfronNeigh);
00393             }
00394 
00395             mlme_device_descriptor_t device_desc;
00396             mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 , llFrameCounter, false);
00397             mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , security_headers->KeyIndex, new_neigbour);
00398 
00399             //Copy Leader Data
00400             *cur->thread_info->thread_leader_data = leaderData;
00401             thread_bootstrap_update_ml16_address(cur, address16);
00402             thread_info(cur)->routerShortAddress = address16;
00403             thread_info(cur)->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER;
00404             if (cur->thread_info->thread_leader_data->leaderRouterId == thread_router_id_from_addr(address16)) {
00405                 if (thread_leader_service_thread_partitition_restart(interface_id, &routing)) {
00406                     return;
00407                 }
00408                 thread_network_data_request_send(cur, mle_msg->packet_src_address, false);
00409                 // force leader to learn active/pending sets from data response
00410                 cur->thread_info->leader_synced = true;
00411                 // Prevent the Leader to learn network data from data response
00412                 cur->thread_info->networkDataRequested = false;
00413                 tr_info("Router synch OK as Leader");
00414             } else {
00415                 // Decrement data version and request network data to be updated
00416                 cur->thread_info->thread_leader_data->dataVersion--;
00417                 cur->thread_info->thread_leader_data->stableDataVersion--;
00418                 thread_network_data_request_send(cur, mle_msg->packet_src_address, true);
00419                 // remove any existing rloc mapping in nvm
00420                 thread_nvm_store_mleid_rloc_map_remove();
00421                 tr_info("Router synch OK as Router");
00422             }
00423 
00424             thread_router_bootstrap_route_tlv_push(cur, routing.dataPtr, routing.tlvLen, linkMargin, entry_temp);
00425             thread_bootstrap_attached_ready(cur);
00426         }
00427 
00428         break;
00429         default:
00430 
00431             break;
00432     }
00433 }
00434 
00435 static int thread_router_synch_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t *tlvReq, uint8_t tlvReqLen)
00436 {
00437     uint16_t length = 127;
00438     uint8_t i, tlvType;
00439     mle_message_timeout_params_t timeout;
00440     struct link_configuration *linkConfiguration;
00441     linkConfiguration = thread_joiner_application_get_config(cur->id);
00442     if (!linkConfiguration) {
00443         return -1;
00444     }
00445 
00446     tr_debug("MLE Router Link Synh response");
00447 
00448     for (i = 0; i < tlvReqLen; i++) {
00449         tlvType = tlvReq[i];
00450         if (tlvType == MLE_TYPE_NETWORK_DATA) {
00451             length += 2 + thread_network_data_tlv_size(cur, true);
00452             break;
00453         }
00454     }
00455 
00456     uint16_t bufId = mle_service_msg_allocate(cur->id, length, false, MLE_COMMAND_ACCEPT);
00457     if (bufId == 0) {
00458         return -1;
00459     }
00460 
00461     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00462 
00463     ptr = thread_leader_data_tlv_write(ptr, cur);
00464     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00465     ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00466     //SET MLE Frame Counter
00467     ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00468 
00469     ptr = mle_tlv_write_response(ptr, challenge, chalLen);
00470     ptr = mle_general_write_source_address(ptr, cur);
00471 
00472     for (i = 0; i < tlvReqLen; i++) {
00473         tlvType = tlvReq[i];
00474         if (tlvType == MLE_TYPE_NETWORK_DATA) {
00475             ptr = thread_network_data_tlv_write(cur, ptr, true);
00476         } else if (tlvType == MLE_TYPE_ROUTE) {
00477             ptr = thread_route_option_write(cur, ptr);
00478         } else if (tlvType == MLE_TYPE_ADDRESS16) {
00479             ptr = mle_tlv_write_short_address(ptr, shortAddress);
00480         } else if (tlvType == MLE_TYPE_RSSI) {
00481 
00482         }
00483     }
00484 
00485     timeout.retrans_max = 0;
00486     timeout.timeout_init = 0;
00487     timeout.timeout_max = 0;
00488     timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00489     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00490         tr_debug("Buffer overflow at message write");
00491     }
00492     //SET Destination address
00493     mle_service_set_msg_destination_address(bufId, mle_msg->packet_src_address);
00494     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00495     uint32_t keySequence;
00496     thread_management_get_current_keysequence(cur->id, &keySequence);
00497     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00498 
00499     mle_service_send_message(bufId);
00500     return 0;
00501 }
00502 
00503 static int thread_router_accept_to_endevice(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t *challenge, uint8_t chalLen)
00504 {
00505     mle_message_timeout_params_t timeout;
00506     uint16_t bufId = mle_service_msg_allocate(cur->id, 64, false, MLE_COMMAND_ACCEPT);
00507     if (bufId == 0) {
00508         return -1;
00509     }
00510 
00511     if (addr_is_ipv6_multicast(mle_msg->packet_src_address)) {
00512         timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00513     } else {
00514         timeout.delay = MLE_NO_DELAY;
00515     }
00516     tr_debug("MLE Router Link Request response to REED or ED");
00517 
00518     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00519 
00520     timeout.retrans_max = 0;
00521     timeout.timeout_init = 0;
00522     timeout.timeout_max = 0;
00523 
00524     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00525     ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00526     //SET MLE Frame Counter
00527     ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00528     ptr = mle_tlv_write_response(ptr, challenge, chalLen);
00529     ptr = thread_leader_data_tlv_write(ptr, cur);
00530     ptr = mle_general_write_source_address(ptr, cur);
00531 
00532     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00533         tr_debug("Buffer overflow at message write");
00534     }
00535     //SET Destination address
00536     mle_service_set_msg_destination_address(bufId, mle_msg->packet_src_address);
00537     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00538     uint32_t keySequence;
00539     thread_management_get_current_keysequence(cur->id, &keySequence);
00540     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00541     mle_service_send_message(bufId);
00542     return 0;
00543 
00544 }
00545 
00546 static int thread_router_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t type, bool rssi_tlv, uint8_t rssi)
00547 {
00548     mle_message_timeout_params_t timeout;
00549     uint16_t bufId;
00550     (void)shortAddress;
00551     uint32_t keySequence;
00552     if (type == MLE_COMMAND_ACCEPT) {
00553         timeout.retrans_max = 0;
00554         timeout.timeout_init = 0;
00555         timeout.timeout_max = 0;
00556         bufId = mle_service_msg_allocate(cur->id, 128, false, type);
00557     } else {
00558         timeout.retrans_max = 1;
00559         timeout.timeout_init = 2;
00560         timeout.timeout_max = 3;
00561         bufId = mle_service_msg_allocate(cur->id, 128, true, type);
00562     }
00563     if (bufId == 0) {
00564         return -1;
00565     }
00566 
00567     if (addr_is_ipv6_multicast(mle_msg->packet_dst_address)) {
00568         timeout.delay = MLE_HALF_SECOND_MAX_DELAY;
00569     } else {
00570         timeout.delay = MLE_NO_DELAY;
00571     }
00572 
00573     tr_debug("MLE Router Link Request response");
00574 
00575     thread_management_get_current_keysequence(cur->id, &keySequence);
00576     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00577 
00578     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00579 
00580     ptr = thread_leader_data_tlv_write(ptr, cur);
00581     if (rssi_tlv) {
00582         ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00583         ptr = mle_tlv_rssi_tlv(ptr, rssi);
00584         if (type != MLE_COMMAND_ACCEPT) {
00585             uint8_t req_tlv = MLE_TYPE_RSSI;
00586             ptr = mle_tlv_req_tlv(ptr, &req_tlv, 1);
00587 
00588         }
00589     }
00590 
00591     if (challenge && chalLen) {
00592         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00593         //SET MLE Frame Counter
00594         ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00595         ptr = mle_tlv_write_response(ptr, challenge, chalLen);
00596     }
00597 
00598     ptr = mle_general_write_source_address(ptr, cur);
00599 
00600     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00601         tr_debug("Buffer overflow at message write");
00602     }
00603     mle_service_set_msg_destination_address(bufId, mle_msg->packet_src_address);
00604     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00605     mle_service_send_message(bufId);
00606     return 0;
00607 
00608 }
00609 
00610 static uint16_t thread_tlv_len(protocol_interface_info_entry_t *cur, uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t mode)
00611 {
00612     // Calculates the extra length for bigger TLVs it is assumed that smaller ones fit in extra reserved space
00613     uint16_t len = 0;
00614     for (uint16_t i = 0; i < tlv_len; i++) {
00615         if (*tlv_ptr == MLE_TYPE_ROUTE) {
00616             len +=  thread_route_option_size(cur);
00617         } else if (*tlv_ptr == MLE_TYPE_NETWORK_DATA) {
00618             len += 2 + thread_network_data_tlv_size(cur, mode & MLE_THREAD_REQ_FULL_DATA_SET);
00619         } else if (*tlv_ptr == MLE_TYPE_ADDRESS16) {
00620             //Short Address
00621             len += 4;
00622         }
00623         tlv_ptr++;
00624     }
00625     return len;
00626 }
00627 
00628 static uint8_t *thread_tlv_add(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint8_t tlv_type, uint8_t mode)
00629 {
00630     struct link_configuration *linkConfiguration;
00631     linkConfiguration = thread_joiner_application_get_config(cur->id);
00632     if (!linkConfiguration) {
00633         return ptr;
00634     }
00635 
00636     switch (tlv_type) {
00637         case MLE_TYPE_SRC_ADDRESS:
00638             /* Add a MLE Source Address TLV */
00639             ptr = mle_general_write_source_address(ptr, cur); /* TODO cur normally first in param list */
00640             break;
00641         case MLE_TYPE_MODE: {
00642             /* Add a MLE Mode TLV */
00643             *ptr++ = MLE_TYPE_MODE;
00644             *ptr++ = 1;
00645             *ptr++ = thread_mode_get_by_interface_ptr(cur);
00646         }
00647         break;
00648         case MLE_TYPE_TIMEOUT:
00649             /* Add a MLE Timeout TLV */
00650             ptr = mle_tlv_write_timeout(ptr, cur->thread_info->host_link_timeout);
00651             break;
00652         case MLE_TYPE_LL_FRAME_COUNTER:
00653             /* Add a MLE Timeout TLV */
00654             ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00655             break;
00656         case MLE_TYPE_NWK_PARAM:
00657             /* Add a MLE Network Parameter TLV */
00658             /* TODO */
00659             break;
00660         case MLE_TYPE_MLE_FRAME_COUNTER:
00661             /* Add a MLE MLE Frame Counter TLV */
00662             /* TODO */
00663             /* Not ostensibly used in Thread */
00664             break;
00665         case MLE_TYPE_ROUTE:
00666             /* Add a MLE Router Table TLV */
00667             ptr = thread_route_option_write(cur, ptr);
00668             break;
00669         case MLE_TYPE_ADDRESS16:
00670             /* Add a MLE Short Address TLV */
00671             /* TODO */
00672             break;
00673         case MLE_TYPE_LEADER_DATA:
00674             ptr = thread_leader_data_tlv_write(ptr, cur);
00675             break;
00676         case MLE_TYPE_NETWORK_DATA:
00677             ptr = thread_network_data_tlv_write(cur, ptr, mode & MLE_THREAD_REQ_FULL_DATA_SET);
00678             break;
00679         case MLE_TYPE_SCAN_MASK:
00680             break;
00681         case MLE_TYPE_CONNECTIVITY:
00682             break;
00683         case MLE_TYPE_RSSI:
00684             break;
00685         default:
00686             /* No other TLV type can be requested */
00687             /* LQI possibly - but not for thread */
00688             break;
00689     }
00690     return ptr;
00691 }
00692 
00693 static int thread_child_update_response(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t mode, uint16_t short_address, uint32_t timeout, mle_tlv_info_t *addressRegisterTlv, mle_tlv_info_t *tlvReq, mle_tlv_info_t *challengeTlv, uint64_t active_timestamp, uint64_t pending_timestamp)
00694 {
00695     uint16_t i;
00696     uint16_t len = 64;
00697     uint32_t keySequence;
00698     bool add_active_configuration = false;
00699     bool add_pending_configuration = false;
00700     uint64_t own_pending_timestamp = 0;
00701     uint8_t *ptr;
00702     if (!thread_info(cur)) {
00703         return -1;
00704     }
00705     link_configuration_s *link_configuration;
00706     link_configuration = thread_joiner_application_get_config(cur->id);
00707 
00708     if (!link_configuration) {
00709         return -1;
00710     }
00711 
00712     len += 10; // active timestamp tlv size
00713     len += thread_pending_timestamp_tlv_size(cur);
00714 
00715     if (!active_timestamp || active_timestamp != link_configuration->timestamp) {
00716         len += thread_active_operational_dataset_size(cur);
00717         add_active_configuration = true;
00718     }
00719     own_pending_timestamp = thread_joiner_application_pending_config_timestamp_get(cur->id);
00720     // if pending config is not in sync from requested device
00721     if (!pending_timestamp ||
00722             (own_pending_timestamp && own_pending_timestamp != pending_timestamp)) {
00723         len += thread_pending_operational_dataset_size(cur);
00724         add_pending_configuration = true;
00725     }
00726     if (tlvReq && tlvReq->tlvLen) {
00727         mle_tlv_ignore(tlvReq->dataPtr, tlvReq->tlvLen, MLE_TYPE_LL_FRAME_COUNTER);
00728         len += thread_tlv_len(cur, tlvReq->dataPtr, tlvReq->tlvLen, mode);
00729     }
00730     if (addressRegisterTlv && addressRegisterTlv->tlvLen) {
00731         len += addressRegisterTlv->tlvLen;
00732     }
00733 
00734     uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_UPDATE_RESPONSE);
00735 
00736     if (bufId == 0) {
00737         return -1;
00738     }
00739 
00740     tr_debug("MLE Child synch response");
00741 
00742     thread_management_get_current_keysequence(cur->id, &keySequence);
00743     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00744 
00745     ptr = mle_service_get_data_pointer(bufId);
00746 
00747     ptr = mle_tlv_write_mode(ptr, mode); //Write Mode Allways
00748 
00749     if (addressRegisterTlv && addressRegisterTlv->tlvLen) {
00750         *ptr++ = MLE_TYPE_ADDRESS_REGISTRATION;
00751         *ptr++ = addressRegisterTlv->tlvLen;
00752         memcpy(ptr, addressRegisterTlv->dataPtr, addressRegisterTlv->tlvLen);
00753         ptr += addressRegisterTlv->tlvLen;
00754     }
00755     //Set SRC
00756     ptr = mle_general_write_source_address(ptr, cur);
00757     //SET leader data
00758     ptr = thread_leader_data_tlv_write(ptr, cur);
00759     if (timeout) {
00760         ptr = mle_tlv_write_timeout(ptr, timeout);
00761     }
00762 
00763     if (challengeTlv && challengeTlv->tlvLen) {
00764         ptr = mle_tlv_write_response(ptr, challengeTlv->dataPtr, challengeTlv->tlvLen);
00765         ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00766         //SET MLE Frame Counter
00767         ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00768     }
00769 
00770     if (tlvReq && tlvReq->tlvLen) {
00771         /* Go through the requested TLV mask */
00772         for (i = 0; i < tlvReq->tlvLen; i++) {
00773             ptr = thread_tlv_add(cur, ptr, tlvReq->dataPtr[i], mode);
00774         }
00775         if (mle_tlv_requested(tlvReq->dataPtr, tlvReq->tlvLen, MLE_TYPE_ADDRESS16)) {
00776             ptr = mle_tlv_write_short_address(ptr, short_address);
00777         }
00778         if (mle_tlv_requested(tlvReq->dataPtr, tlvReq->tlvLen, MLE_TYPE_NETWORK_DATA)) {
00779             ptr = thread_active_timestamp_write(cur, ptr);
00780             ptr = thread_pending_timestamp_write(cur, ptr);
00781             if (add_active_configuration) {
00782                 ptr = thread_active_operational_dataset_write(cur, ptr);
00783             }
00784             if (add_pending_configuration) {
00785                 ptr = thread_pending_operational_dataset_write(cur, ptr);
00786             }
00787         }
00788     }
00789 
00790     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00791         tr_debug("Buffer overflow at message write");
00792     }
00793     mle_service_set_msg_destination_address(bufId, dst_address);
00794     mle_service_send_message(bufId);
00795     return 0;
00796 
00797 }
00798 
00799 static int mle_build_and_send_data_response_msg(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t *data_ptr, uint16_t data_len, mle_tlv_info_t *request_tlv, uint8_t mode)
00800 {
00801     uint16_t length = 64 + 20 + 4; // source address 4 bytes
00802     uint8_t *ptr;
00803     uint_fast16_t i;
00804     uint64_t active_timestamp = 0;
00805     uint64_t pending_timestamp = 0;
00806     bool add_active_configuration = false;
00807     bool add_pending_configuration = false;
00808     bool active_timestamp_present_in_request = false;
00809     bool pending_timestamp_present_in_request = false;
00810     uint64_t own_pending_timestamp = 0;
00811     link_configuration_s *link_configuration;
00812     link_configuration = thread_joiner_application_get_config(cur->id);
00813 
00814     if (!link_configuration) {
00815         return 0;
00816     }
00817 
00818     active_timestamp_present_in_request = mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, data_ptr, data_len, &active_timestamp);
00819     pending_timestamp_present_in_request = mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, data_ptr, data_len, &pending_timestamp);
00820 
00821     length += thread_pending_timestamp_tlv_size(cur);
00822 
00823     if (!active_timestamp_present_in_request || active_timestamp != link_configuration->timestamp) {
00824         length += thread_active_operational_dataset_size(cur);
00825         add_active_configuration = true;
00826     }
00827     own_pending_timestamp = thread_joiner_application_pending_config_timestamp_get(cur->id);
00828     // if pending config is not in sync from requested device
00829     if (!pending_timestamp_present_in_request ||
00830             (own_pending_timestamp && own_pending_timestamp != pending_timestamp)) {
00831         length += thread_pending_operational_dataset_size(cur);
00832         add_pending_configuration = true;
00833     }
00834 
00835     // Leader data is added by default
00836     mle_tlv_ignore(request_tlv->dataPtr, request_tlv->tlvLen, MLE_TYPE_LEADER_DATA);
00837     length += thread_tlv_len(cur, request_tlv->dataPtr, request_tlv->tlvLen, mode);
00838 
00839     //link metrics info
00840     length += thread_lowpower_link_metrics_length(cur, dst_address);
00841 
00842     uint16_t bufId =  mle_service_msg_allocate(cur->id, length, false, MLE_COMMAND_DATA_RESPONSE);
00843 
00844     if (bufId == 0) {
00845         return -1;
00846     }
00847 
00848     tr_debug("Send MLE data response, %s mode=%x", trace_ipv6(dst_address), mode);
00849     ptr = mle_service_get_data_pointer(bufId);
00850 
00851     ptr = thread_leader_data_tlv_write(ptr, cur);
00852     /* Go through the requested TLV mask */
00853     for (i = 0; i < request_tlv->tlvLen; i++) {
00854         ptr = thread_tlv_add(cur, ptr, request_tlv->dataPtr[i], mode);
00855     }
00856 
00857     ptr = thread_active_timestamp_write(cur, ptr);
00858     ptr = thread_pending_timestamp_write(cur, ptr);
00859     ptr = mle_general_write_source_address(ptr, cur);
00860     if (add_active_configuration) {
00861         ptr = thread_active_operational_dataset_write(cur, ptr);
00862     }
00863     if (add_pending_configuration) {
00864         ptr = thread_pending_operational_dataset_write(cur, ptr);
00865     }
00866     ptr = thread_lowpower_link_metrics_write(cur, dst_address, ptr);
00867 
00868     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00869         tr_debug("Buffer overflow at message write");
00870     }
00871     mle_service_set_msg_destination_address(bufId, dst_address);
00872     //Set Security
00873     uint32_t keySequence;
00874     thread_management_get_current_keysequence(cur->id, &keySequence);
00875     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00876 
00877     mle_service_send_message(bufId);
00878     return 0;
00879 
00880 
00881 }
00882 
00883 //this responds with zeros currently, needs to be updated after results are computed
00884 
00885 static int thread_attach_parent_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, uint8_t *challenge, uint16_t chalLen, uint8_t linkMargin, uint8_t scanMask, uint8_t mode)
00886 {
00887     /**
00888      * This Message need to add Next Items:
00889      * - MLE_TYPE_SRC_ADDRESS
00890      * - MLE_TYPE_LEADER_DATA
00891      * - MLE_TYPE_LL_FRAME_COUNTER
00892      * - MLE_TYPE_MLE FRAME_COUNTER
00893      * - MLE_TYPE_CHALLENGE
00894      * - MLE_TYPE_RESPONSE
00895      * - MLE_TYPE_CONNECTIVITY
00896      * - MLE_TYPE_RSSI
00897      * - MLE_TYPE_VERSION
00898      */
00899 
00900     mle_message_timeout_params_t timeout;
00901 
00902     uint16_t bufId = mle_service_msg_allocate(cur->id, 128, true, MLE_COMMAND_PARENT_RESPONSE);
00903     if (bufId == 0) {
00904         return -1;
00905     }
00906     tr_debug("Build MLE Parent response");
00907 
00908     uint32_t keySequence;
00909     uint8_t *ptr = mle_service_get_data_pointer(bufId);
00910 
00911     //Set Security
00912     thread_management_get_current_keysequence(cur->id, &keySequence);
00913     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
00914 
00915     //SET Leader Data
00916     ptr = thread_leader_data_tlv_write(ptr, cur);
00917 
00918     // SET Connectivity TLV
00919     ptr = thread_connectivity_tlv_write(ptr, cur, mode);
00920 
00921     //SET LL Frame Counter
00922     ptr = mle_general_write_link_layer_framecounter(ptr, cur);
00923     //SET MLE Frame Counter
00924     ptr = mle_tlv_write_framecounter(ptr, mle_service_security_get_frame_counter(cur->id));
00925     //SET Source Address
00926     ptr = mle_general_write_source_address(ptr, cur);
00927     //SET Response
00928     if (challenge != NULL) {
00929         ptr = mle_tlv_write_response(ptr, challenge, chalLen);
00930     }
00931     //RSSI
00932     ptr = mle_tlv_rssi_tlv(ptr, linkMargin);
00933     //Set Version
00934     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
00935 
00936     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
00937         tr_debug("Buffer overflow at message write");
00938     }
00939     timeout.retrans_max = 1;
00940     timeout.timeout_init = 6;
00941     timeout.timeout_max = 6;
00942 
00943     switch (scanMask & 0xc0) {
00944         case 0x80:
00945             timeout.delay = MLE_HALF_SECOND_MAX_DELAY;
00946             break;
00947         default:
00948             timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
00949             break;
00950     }
00951 
00952     //SET Destination address
00953     mle_service_set_msg_destination_address(bufId, dstAddress);
00954     mle_service_set_msg_timeout_parameters(bufId, &timeout);
00955     mle_service_send_message(bufId);
00956     return 0;
00957 }
00958 
00959 int thread_router_bootstrap_reset_child_info(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *child)
00960 {
00961     /* Cleanup occurs for /any/ link we lose to something that looks like a child address,
00962      * not just links that are /now/ our children.
00963      * Due to REED/partition transitions the address may not look like a current child address;
00964      * we could be holding a child entry for future repromotion to router with same ID.
00965      */
00966     if (thread_is_router_addr(child->mac16 ) || child->mac16  >= 0xfffe) {
00967         return -1;
00968     }
00969     tr_debug("Child free %x", child->mac16 );
00970     thread_dynamic_storage_child_info_clear(cur->id, child);
00971 
00972     /* As we are losing a link to a child address, we can assume that if we have an IP neighbour cache
00973      * mapping to that address, it is no longer valid. We must have been their parent, and they must be
00974      * finding a new parent, and hence a new 16-bit address. (Losing a link to a router address would not
00975      * invalidate our IP->16-bit mapping.)
00976      */
00977     protocol_6lowpan_release_short_link_address_from_neighcache(cur, child->mac16 );
00978 
00979     // If Child's RLOC16 appears in the Network Data send the RLOC16 to the Leader
00980     if (thread_network_data_services_registered(&cur->thread_info->networkDataStorage, child->mac16 )) {
00981         tr_debug("Remove references to Child's RLOC16 from the Network Data");
00982         thread_management_client_network_data_unregister(cur->id, child->mac16 );
00983     }
00984 
00985     // Clear all (sleepy) child registrations to multicast groups
00986     thread_child_mcast_entries_remove(cur, child->mac64 );
00987 
00988     return 0;
00989 }
00990 
00991 void thread_router_bootstrap_child_information_clear(protocol_interface_info_entry_t *cur)
00992 {
00993     /* make sure that the child info (from previous partition if any)
00994         is cleared if no router address is got from leader */
00995 
00996     if (!cur->thread_info) {
00997         return;
00998     }
00999 
01000     // Remove mle neighbour entries for children in previous partition
01001     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
01002 
01003     ns_list_foreach_safe(mac_neighbor_table_entry_t, table_entry, mac_table_list) {
01004         if (table_entry->mac16 < 0xfffe && !thread_is_router_addr(table_entry->mac16)) {
01005             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), table_entry);
01006         }
01007     }
01008 }
01009 static void thread_router_bootstrap_invalid_child_information_clear(protocol_interface_info_entry_t *cur, uint16_t router_rloc)
01010 {
01011 
01012     tr_debug("Thread Short address changed old: %x new: %x", cur->thread_info->routerShortAddress, router_rloc);
01013 
01014     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
01015 
01016     // scrub neighbours with child addresses that are not ours
01017     ns_list_foreach_safe(mac_neighbor_table_entry_t, table_entry, mac_table_list) {
01018         if (table_entry->mac16 < 0xfffe &&
01019                 !thread_is_router_addr(table_entry->mac16) &&
01020                 thread_router_addr_from_addr(table_entry->mac16) != router_rloc) {
01021             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), table_entry);
01022         }
01023     }
01024 }
01025 
01026 static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9])
01027 {
01028     uint8_t ml16[16];
01029     protocol_interface_info_entry_t *cur;
01030     uint8_t parent_router_id = FAST_ROUTE_NO_ROUTE;
01031 
01032     cur = protocol_stack_interface_info_get_by_id(interface_id);
01033     tr_debug("RouterID CB");
01034     if (!cur) {
01035         return;
01036     }
01037     if (!cur->thread_info->routerIdRequested) {
01038         return;
01039     }
01040     cur->thread_info->routerIdRequested = false;
01041 
01042     if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER ||
01043             cur->thread_info->leader_private_data) {
01044         // Test api can cause these states or some out of sync operation.
01045         tr_warn("Router address for non-REED");
01046         return;
01047     }
01048 
01049     if (status < 0) {
01050         thread_bootstrap_router_id_get_fail(cur);
01051         return;
01052     }
01053 
01054     uint8_t routeId = *router_mask_ptr++;
01055 
01056     if (cur->thread_info->thread_endnode_parent) {
01057         parent_router_id = cur->thread_info->thread_endnode_parent->router_id;
01058     }
01059 
01060     thread_router_bootstrap_invalid_child_information_clear(cur, router_rloc);
01061 
01062     // Release network data from old address
01063     cur->thread_info->localServerDataBase.release_old_address = true;
01064 
01065     //ADD New ML16
01066     // This should be used thread_bootstrap_update_ml16_address(cur, router_rloc);
01067     thread_clean_old_16_bit_address_based_addresses(cur);
01068     mac_helper_mac16_address_set(cur, router_rloc);
01069     cur->thread_info->routerShortAddress = router_rloc;
01070     memcpy(ml16, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01071     memcpy(&ml16[8], ADDR_SHORT_ADR_SUFFIC, 6);
01072     common_write_16_bit(router_rloc, &ml16[14]);
01073 
01074     cur->global_address_available = true;
01075     //Register UL16
01076     if_address_entry_t *def_address = addr_add(cur, ml16, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true);
01077     if (!def_address) {
01078         return;
01079     }
01080 
01081     //  /* XXX Is short_src_adr ever reset? Is it undefined if info not in msg? */
01082     tr_debug("Route seq %d Router mask: %s", routeId, trace_array(router_mask_ptr, 8));
01083     cur->thread_info->routing.router_id_sequence_valid = false;
01084     if (parent_router_id != FAST_ROUTE_NO_ROUTE) {
01085         thread_routing_force_next_hop(cur, routeId, router_mask_ptr, parent_router_id);
01086     } else {
01087         tr_warn("No parent information available, no initial route set.");
01088         thread_routing_update_id_set(cur, routeId, router_mask_ptr);
01089     }
01090     thread_bootstrap_attached_active_router(cur);
01091 
01092 }
01093 
01094 void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t *cur, uint8_t status)
01095 {
01096     int router_id_req_status;
01097     tr_debug("Router ID Request");
01098     if (cur->thread_info->routerIdRequested) {
01099         tr_warn("Router ID already requested");
01100         return;
01101     }
01102 
01103     router_id_req_status = thread_management_client_router_id_get(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_cb, status);
01104     tr_debug("RouterIDReq COAP ID=%d", router_id_req_status);
01105     if (router_id_req_status > 0) {
01106         cur->thread_info->routerIdRequested = true;
01107     }
01108 }
01109 
01110 static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, thread_pending_child_id_req_t *child_req, struct mac_neighbor_table_entry *neigh_info)
01111 {
01112     uint16_t len = 12 + 4; //Leader data and short address
01113     uint8_t *ptr;
01114     bool fullList = false;
01115     uint64_t pending_timestamp;
01116     struct link_configuration *linkConfiguration;
01117     linkConfiguration = thread_joiner_application_get_config(cur->id);
01118     if (!linkConfiguration) {
01119         return -1;
01120     }
01121 
01122     if (thread_neighbor_class_request_full_data_setup(&cur->thread_info->neighbor_class, neigh_info->index )) {
01123         fullList = true;
01124     }
01125 
01126     if (child_req->shortAddressReq) {
01127         //Short Address
01128         len += 4;
01129     }
01130 
01131     if (child_req->networkDataReq) {
01132         len += 2 + thread_network_data_tlv_size(cur, fullList);
01133     }
01134 
01135     if (child_req->routeReq) {
01136         len += thread_route_option_size(cur);
01137     }
01138     if (child_req->request_active_config || child_req->active_timestamp != linkConfiguration->timestamp) {
01139         len += thread_active_operational_dataset_size(cur);
01140     }
01141 
01142     //always put active timestamp
01143     len += 10;
01144     len += thread_pending_timestamp_tlv_size(cur);
01145     pending_timestamp = thread_joiner_application_pending_config_timestamp_get(cur->id);
01146     if (pending_timestamp && pending_timestamp != child_req->pending_timestamp) {
01147         len += thread_pending_operational_dataset_size(cur);
01148     }
01149 
01150     mle_message_timeout_params_t timeout;
01151     uint16_t bufId = mle_service_msg_allocate(cur->id, len, false, MLE_COMMAND_CHILD_ID_RESPONSE);
01152     if (bufId == 0) {
01153         return -1;
01154     }
01155     uint32_t keySequence;
01156     thread_management_get_current_keysequence(cur->id, &keySequence);
01157     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
01158 
01159     tr_debug("Send MLE Child ID response");
01160 
01161     ptr = mle_service_get_data_pointer(bufId);
01162 
01163     ptr = thread_leader_data_tlv_write(ptr, cur);
01164 
01165     ptr = mle_general_write_source_address(ptr, cur);
01166 
01167     if (child_req->shortAddressReq) {
01168         ptr = mle_tlv_write_short_address(ptr, neigh_info->mac16 );
01169     }
01170 
01171     if (child_req->routeReq) {
01172         ptr = thread_route_option_write(cur, ptr);
01173     }
01174 
01175     if (child_req->networkDataReq) {
01176         ptr = thread_network_data_tlv_write(cur, ptr, fullList);
01177     }
01178 
01179     if (child_req->active_timestamp != linkConfiguration->timestamp) {
01180         ptr = thread_active_operational_dataset_write(cur, ptr);
01181     }
01182 
01183     //always write active timestamp
01184     ptr = thread_active_timestamp_write(cur, ptr);
01185     if (pending_timestamp > 0 && pending_timestamp != child_req->pending_timestamp) {
01186         ptr = thread_pending_operational_dataset_write(cur, ptr);
01187     }
01188 
01189     ptr = thread_pending_timestamp_write(cur, ptr);
01190 
01191 
01192     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
01193         tr_debug("Buffer overflow at message write");
01194     }
01195     timeout.retrans_max = 0;
01196     timeout.timeout_init = 0;
01197     timeout.timeout_max = 0;
01198     timeout.delay = MLE_NO_DELAY;
01199     mle_service_set_msg_destination_address(bufId, dstAddress);
01200     mle_service_set_msg_timeout_parameters(bufId, &timeout);
01201     mle_service_send_message(bufId);
01202     return 0;
01203 
01204 
01205 }
01206 
01207 int thread_router_bootstrap_child_max_timeout_get(protocol_interface_info_entry_t *cur, uint32_t *max_child_timeout)
01208 {
01209     uint16_t router_address = thread_info(cur)->routerShortAddress;
01210     uint32_t max_timeout = 0;
01211     if (router_address >= 0xfffe) {
01212         router_address = mac_helper_mac16_address_get(cur);
01213     }
01214     if (router_address & THREAD_CHILD_MASK) {
01215         return -1; //I am child
01216     }
01217     if (router_address >= 0xfffe) {
01218         return -1;
01219     }
01220     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
01221 
01222     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
01223         if (thread_router_addr_from_addr(cur_entry->mac16) == router_address &&
01224                 !cur_entry->ffd_device && cur_entry->lifetime > max_timeout) {
01225             max_timeout = cur_entry->lifetime;
01226         }
01227     }
01228     *max_child_timeout = max_timeout;
01229     return 0;
01230 }
01231 
01232 uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur)
01233 {
01234     uint16_t child_count = 0;
01235     uint16_t router_address = thread_info(cur)->routerShortAddress;
01236     if (router_address >= 0xfffe) {
01237         router_address = mac_helper_mac16_address_get(cur);
01238     }
01239     if (router_address & THREAD_CHILD_MASK) {
01240         return 0; //I am child
01241     }
01242     if (router_address >= 0xfffe) {
01243         return 0;
01244     }
01245     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
01246 
01247     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
01248         if (thread_router_addr_from_addr(cur_entry->mac16) == router_address) {
01249             child_count++;
01250         }
01251     }
01252     return child_count;
01253 }
01254 
01255 static uint16_t thread_router_bootstrap_child_address_generate(protocol_interface_info_entry_t *cur)
01256 {
01257     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
01258 
01259     if (thread_router_bootstrap_child_count_get(cur) >= cur->thread_info->maxChildCount) {
01260         tr_info("Maximum count %d reached", cur->thread_info->maxChildCount);
01261         return 0xfffe;
01262     }
01263 
01264     bool address_allocated = false;
01265     for (uint16_t i = 0; i < cur->thread_info->maxChildCount; i++) {
01266         address_allocated = false;
01267         cur->thread_info->lastAllocatedChildAddress = (cur->thread_info->lastAllocatedChildAddress % THREAD_MAX_CHILD_ID_COUNT) + 1;
01268         ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
01269             if ((cur_entry->mac16 & THREAD_CHILD_MASK) == cur->thread_info->lastAllocatedChildAddress) {
01270                 address_allocated = true;
01271                 break;
01272             }
01273         }
01274         if (!address_allocated) {
01275             break;
01276         }
01277     }
01278     if (address_allocated) {
01279         // all possible addresses already allocated
01280         return 0xfffe;
01281     }
01282     return ((mac_helper_mac16_address_get(cur) & THREAD_ROUTER_MASK) | cur->thread_info->lastAllocatedChildAddress);
01283 }
01284 
01285 static bool thread_child_id_request(protocol_interface_info_entry_t *cur, struct mac_neighbor_table_entry *entry_temp)
01286 {
01287     //Remove All Short address links from router
01288     if (entry_temp->mac16  < 0xfffe) {
01289         protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16 );
01290     }
01291 
01292     //allocate child address if current is router, 0xffff or not our child
01293     if (!thread_addr_is_child(mac_helper_mac16_address_get(cur), entry_temp->mac16 )) {
01294         entry_temp->mac16  = thread_router_bootstrap_child_address_generate(cur);
01295     }
01296 
01297     if (entry_temp->mac16  >= 0xfffe) {
01298         return false;
01299     }
01300 
01301     // Store this child info to the NVM
01302     thread_dynamic_storage_child_info_store(cur, entry_temp);
01303     //}
01304     return true;
01305 }
01306 
01307 void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *cur)
01308 {
01309     thread_pending_child_id_req_t *req;
01310     bool new_neigbour = false;
01311 
01312     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
01313         if (!cur->thread_info->routerIdRequested) {
01314             tr_info("Upgrade REED to Router");
01315             thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST);
01316         }
01317         return;
01318     }
01319     req = thread_child_id_request_entry_get_from_the_list(cur);
01320 
01321     if (!req) {
01322         tr_debug("Child Id Req pending list empty");
01323         return;
01324     }
01325 
01326     if (cur->thread_info->thread_attached_state != THREAD_STATE_CONNECTED_ROUTER) {
01327         // We are not router can not process
01328         goto free_request;
01329     }
01330 
01331     uint8_t ll64[16];
01332     //set LL64 destination address
01333     memcpy(ll64, ADDR_LINK_LOCAL_PREFIX, 8);
01334     memcpy(&ll64[8], req->euid64, 8);
01335     ll64[8] ^= 2;
01336     //Allocate entry
01337     mac_neighbor_table_entry_t *entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), ll64, true, &new_neigbour);
01338 
01339     if (!entry_temp) {
01340         //Send link reject
01341         thread_link_reject_send(cur, ll64);
01342         goto free_request;
01343     }
01344 
01345     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , req->linkMargin, new_neigbour);
01346     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
01347 
01348     // If mac frame couter is less than previous we need to leave the old one
01349 
01350     //Update or set neigh info
01351     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, req->timeout);
01352     mle_mode_parse_to_mac_entry(entry_temp, req->mode);
01353     thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index , req->mode);
01354     entry_temp->connected_device  = 1;
01355     mle_service_frame_counter_entry_add(cur->id, entry_temp->index , req->mleFrameCounter);
01356 
01357     if (req->shortAddressReq) {
01358         if (!thread_child_id_request(cur, entry_temp)) {
01359             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01360             thread_link_reject_send(cur, ll64);
01361             goto free_request;
01362         }
01363     }
01364     if (new_neigbour) {
01365         mlme_device_descriptor_t device_desc;
01366         mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 , req->frameCounter, false);
01367         mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , req->keyId, new_neigbour);
01368     } else {
01369         // in get response handler this will update the short address from MLE table
01370         mlme_get_t get_req;
01371         get_req.attr = macDeviceTable;
01372         get_req.attr_index = entry_temp->index ;
01373         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
01374     }
01375 
01376     //Register MLEID if RRFD device
01377     if (!entry_temp->ffd_device ) {
01378         uint8_t tempIPv6Address[16];
01379         memcpy(tempIPv6Address, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8);
01380         memcpy(&tempIPv6Address[8], req->eiid, 8);
01381 
01382         thread_neighbor_class_add_mleid(&cur->thread_info->neighbor_class, entry_temp->index , req->eiid);
01383 
01384         tr_debug("Register %s", trace_ipv6(tempIPv6Address));
01385         //Register GP --> 16
01386         thread_nd_address_registration(cur, tempIPv6Address, entry_temp->mac16 , cur->mac_parameters->pan_id, entry_temp->mac64 , NULL);
01387     }
01388 
01389     mle_attach_child_id_response_build(cur, ll64, req, entry_temp);
01390 
01391 free_request:
01392     ns_dyn_mem_free(req);
01393     thread_bootstrap_child_id_request(cur);
01394 }
01395 
01396 static void thread_address_registration_tlv_parse(uint8_t *ptr, uint16_t data_length, protocol_interface_info_entry_t *cur, uint16_t mac16, uint8_t *mac64)
01397 {
01398     lowpan_context_t *ctx;
01399     uint8_t tempIPv6Address[16];
01400     uint8_t ctxId;
01401     bool new_neighbour_created;
01402     thread_child_mcast_entries_remove(cur, mac64);
01403     while (data_length) {
01404         //Read
01405         ctxId = *ptr++;
01406         if (ctxId & 0x80) {
01407             ctxId &= 0x0f;
01408             ctx = lowpan_contex_get_by_id(&cur->lowpan_contexts, ctxId);
01409             if (ctx) {
01410                 memcpy(tempIPv6Address, ctx->prefix, 8);
01411                 memcpy(&tempIPv6Address[8], ptr, 8);
01412                 tr_debug("Register %s", trace_ipv6(tempIPv6Address));
01413                 //Register GP --> 16
01414                 int retVal = thread_nd_address_registration(cur, tempIPv6Address, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
01415                 thread_bootstrap_address_registration(cur, tempIPv6Address, mac64, new_neighbour_created, retVal == -2);
01416                 (void) retVal;
01417             } else {
01418                 tr_debug("No Context %u", ctxId);
01419             }
01420             ptr += 8;
01421             data_length -= 9;
01422         } else {
01423             tr_debug("Register %s", trace_ipv6(ptr));
01424 
01425             if (addr_is_ipv6_multicast(ptr)) {
01426                 // Register multicast address (link-local & higher)
01427                 if (addr_ipv6_multicast_scope(ptr) >= IPV6_SCOPE_LINK_LOCAL) {
01428                     addr_add_group(cur, ptr);
01429                     if (thread_child_mcast_entry_get(cur, ptr, mac64)) {
01430                         tr_debug("Added sleepy multicast registration entry.");
01431                     }
01432                 }
01433             } else {
01434                 //Register GP --> 16
01435                 int retVal = thread_nd_address_registration(cur, ptr, mac16, cur->mac_parameters->pan_id, mac64, &new_neighbour_created);
01436                 thread_bootstrap_address_registration(cur, ptr, mac64, new_neighbour_created, retVal == -2);
01437                 (void) retVal;
01438             }
01439 
01440             ptr += 16;
01441             data_length -= 17;
01442         }
01443     }
01444 }
01445 
01446 void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
01447 {
01448     (void) interface_id;
01449     thread_leader_data_t leaderData;
01450     mac_neighbor_table_entry_t *entry_temp;
01451     bool rssiTLV;
01452     bool leaderDataReceived;
01453     protocol_interface_info_entry_t *cur = mle_msg->interface_ptr;
01454 
01455     //TLV REQUSTED
01456     if (mle_tlv_type_requested(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length)) {
01457         rssiTLV = true;
01458     } else {
01459         rssiTLV = false;
01460     }
01461 
01462     if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
01463         leaderDataReceived = true;
01464     } else {
01465         leaderDataReceived = false;
01466     }
01467 
01468 
01469     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
01470     tr_debug("Thread MLE REED Handler");
01471     switch (mle_msg->message_type) {
01472         case MLE_COMMAND_PARENT_REQUEST: {
01473             uint8_t scanMask, mode;
01474             uint16_t version;
01475             mle_tlv_info_t challengeTlv;
01476             tr_info("Recv MLE Parent Request");
01477 
01478             if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
01479                 // If own attach is ongoing, do not process parent request
01480                 return;
01481             }
01482 
01483             if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) {
01484                 tr_debug("Wrong key mode %u ", security_headers->KeyIdMode);
01485                 return;
01486             }
01487 
01488             if (!thread_router_bootstrap_routing_allowed(cur)) {
01489                 tr_debug("R bit is off in security policy; drop packet");
01490                 return;
01491             }
01492 
01493             // check if security policy prevents sending of parent response
01494             if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
01495                 tr_debug("Security policy prevents parent response; drop packet");
01496                 return;
01497             }
01498 
01499             if (thread_am_reed(cur)) {
01500                 // If we are in REED mode and receive PARENT_REQ from our parent, don't send response.
01501                 if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
01502                     tr_debug("Drop PARENT_REQ from own parent");
01503                     return;
01504                 }
01505             }
01506 
01507             // parent request received
01508             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01509             if (entry_temp) {
01510                 //Set MAC modes
01511                 mle_mode_parse_to_mac_entry(entry_temp, (MLE_FFD_DEV | MLE_RX_ON_IDLE));
01512                 thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index , MLE_THREAD_REQ_FULL_DATA_SET);
01513                 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
01514                 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
01515             }
01516             if (!entry_temp) {
01517                 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01518                     tr_debug("NO Mode");
01519                     return;
01520                 }
01521 
01522                 // New child trying to attach check if we have room
01523                 if (mle_service_interface_tx_queue_size(cur->id) > THREAD_MAX_PARALLEL_MLE_PARENT_REQUEST) {
01524                     tr_info("Drop MLE message: too many simultaneous MLE messages");
01525                     return;
01526                 }
01527 
01528                 if (mle_class_free_entry_count_get(cur) < 1) {
01529                     tr_info("Drop MLE message: no space left in the MLE table");
01530                     return;
01531                 }
01532 
01533                 if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && mle_class_rfd_entry_count_get(cur) >= THREAD_MAX_MTD_CHILDREN) {
01534                     tr_info("Drop MLE message: maximum MTD child count reached.");
01535                     return;
01536                 }
01537 
01538                 if (!(mode & MLE_RX_ON_IDLE) && mle_class_sleepy_entry_count_get(cur) >= THREAD_MAX_SED_CHILDREN) {
01539                     tr_info("Drop MLE message: maximum SED child count reached.");
01540                     return;
01541                 }
01542 
01543                 if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER &&
01544                         thread_router_bootstrap_child_count_get(cur) >= cur->thread_info->maxChildCount) {
01545                     tr_info("Drop MLE message: maximum Child count reached (%d)", cur->thread_info->maxChildCount);
01546                     return;
01547                 }
01548             }
01549 
01550             if (thread_route_ready_to_leader(cur) != 0) {
01551                 tr_debug("Leader Path infinite");
01552                 return;
01553             }
01554 
01555             /**
01556                  * MLE attached First packet Mandatory TLV:s are validated at this function
01557                  * - MLE_TYPE_SCAN_MASK
01558                  * - MLE_TYPE_CHALLENGE
01559                  * - MLE_TYPE_VERSION
01560                  */
01561             //Validate Mask
01562             if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_SCAN_MASK, mle_msg->data_ptr, mle_msg->data_length, &scanMask)) {
01563                 tr_debug("NO Scan mask");
01564                 return;
01565             }
01566 
01567             if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01568                 tr_debug("NO Mode");
01569                 return;
01570             }
01571 
01572             if (!thread_scan_mask_validation(cur, scanMask)) {
01573                 tr_debug("Not my type");
01574                 return;
01575             }
01576 
01577             if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED &&
01578                     31 < thread_routing_count_active_routers(&cur->thread_info->routing)) {
01579                 tr_info("No possibility to upgrade to router");
01580                 return;
01581             }
01582 
01583             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) {
01584                 tr_debug("NO version");
01585                 return;
01586             }
01587 
01588             //Read Challenge for Build Response
01589             if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) {
01590                 tr_debug("No challenge");
01591                 return;
01592             }
01593 
01594             if (thread_attach_parent_response_build(cur, mle_msg->packet_src_address, challengeTlv.dataPtr, challengeTlv.tlvLen, linkMargin, scanMask, mode) == 0) {
01595                 tr_debug("Send MLE Parent response");
01596             }
01597             break;
01598         }
01599 
01600         case MLE_COMMAND_CHILD_ID_REQUEST:
01601             tr_info("Recv MLE Child ID Request from %s", trace_ipv6(mle_msg->packet_src_address));
01602             if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
01603                 // If own attach is ongoing, do not process child ID req
01604                 return;
01605             }
01606 
01607             if (!thread_router_bootstrap_routing_allowed(cur)) {
01608                 tr_debug("R bit is off in security policy; drop packet");
01609                 return;
01610             }
01611 
01612             // check if security policy prevents sending of child id response
01613             if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
01614                 tr_debug("Security policy prevents child id response; drop packet");
01615                 return;
01616             }
01617 
01618             if (thread_am_reed(cur)) {
01619                 // If we are in REED mode and receive child ID request from our parent, call connection error.
01620                 if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
01621                     tr_debug("Child ID req from own parent -> connection error");
01622                     entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01623                     if (entry_temp) {
01624                         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01625                     }
01626                     thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
01627                     return;
01628                 }
01629             }
01630 
01631             if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) {
01632                 tr_debug("Wrong key mode %u ", security_headers->KeyIdMode);
01633                 return;
01634             } else {
01635                 thread_pending_child_id_req_t *id_req;
01636                 uint8_t tlvType;
01637                 mle_tlv_info_t tlvRequest, addressRegisteredTlv;
01638                 uint8_t *t_ptr;
01639 
01640                 uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
01641 
01642                 if (messageId == 0) {
01643                     tr_debug("No matching challenge");
01644                     return;
01645                 }
01646 
01647                 /* Perform key synchronization */
01648                 thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
01649 
01650                 //Free Response
01651                 mle_service_msg_free(messageId);
01652 
01653                 mle_msg->packet_src_address[8]  ^= 2;
01654                 id_req = thread_child_id_request_entry_get(cur, (mle_msg->packet_src_address + 8));
01655                 mle_msg->packet_src_address[8]  ^= 2;
01656 
01657                 if (!id_req) {
01658                     tr_debug("No room for child id req");
01659                     return;
01660                 }
01661 
01662                 /**
01663                      * MLE attached Tree packet Mandatory TLV:s are validated at this function
01664                      * - MLE_TYPE_TIMEOUT
01665                      * - MLE_TYPE_MODE
01666                      * - MLE_TYPE_LL_FRAME_COUNTER
01667                      * - MLE_TYPE_TLV_REQUEST
01668                      * - MLE_TYPE_VERSION
01669                      * Optional:
01670                      * - MLE_TYPE_ADDRESS_REGISTRATION
01671                      * - MLE_TYPE_MLE_FRAME_COUNTER
01672                      */
01673 
01674                 if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &id_req->timeout)) ||
01675                         (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &id_req->mode)) ||
01676                         (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &id_req->version)) ||
01677                         (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &id_req->frameCounter)) ||
01678                         (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlvRequest))) {
01679                     thread_child_id_request_entry_remove(cur, id_req);
01680                     tr_debug("Illegal child id req");
01681                     return;
01682                 }
01683                 //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
01684                 if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &id_req->mleFrameCounter)) {
01685                     id_req->mleFrameCounter = id_req->frameCounter;
01686                 }
01687 
01688                 t_ptr = tlvRequest.dataPtr;
01689 
01690                 for (uint8_t i = 0; i < tlvRequest.tlvLen; i++) {
01691                     tlvType = *t_ptr++;
01692                     if (tlvType == MLE_TYPE_ADDRESS16) {
01693                         id_req->shortAddressReq = true;
01694                     } else if (tlvType == MLE_TYPE_NETWORK_DATA) {
01695                         id_req->networkDataReq = true;
01696                     } else if (tlvType == MLE_TYPE_ROUTE) {
01697                         id_req->routeReq = true;
01698                     }
01699                 }
01700                 if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
01701                     uint8_t context;
01702                     t_ptr = addressRegisteredTlv.dataPtr;
01703                     context = *t_ptr++;
01704                     if (context & 0x80) {
01705                         context &= 0x0f;
01706                         if (addressRegisteredTlv.tlvLen == 9 && (context == 0)) {
01707                             memcpy(id_req->eiid, t_ptr, 8);
01708                         }
01709                     } else {
01710                         t_ptr += 8;
01711                         memcpy(id_req->eiid, t_ptr, 8);
01712                     }
01713                 }
01714 
01715                 if (!(id_req->mode & MLE_FFD_DEV) && addressRegisteredTlv.tlvLen == 0) {
01716                     tr_debug("No address registration TLV in MTD child id request");
01717                     thread_child_id_request_entry_remove(cur, id_req);
01718                     return;
01719                 }
01720 
01721                 id_req->keyId = security_headers->KeyIndex;
01722                 id_req->keySeq = common_read_32_bit(security_headers->Keysource);
01723                 id_req->linkMargin = linkMargin;
01724 
01725                 id_req->active_timestamp = 0;
01726                 id_req->request_active_config = false;
01727                 if (!mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &id_req->active_timestamp)) {
01728                     id_req->request_active_config = true;
01729                 }
01730                 if (!mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &id_req->pending_timestamp)) {
01731                     id_req->pending_timestamp = 0;
01732                 }
01733 
01734                 //Push Event to queue
01735                 if (thread_bootstrap_child_id_request(cur) != 0) {
01736                     thread_child_id_request_entry_remove(cur, id_req);
01737                 }
01738 
01739                 break;
01740             }
01741 
01742         case MLE_COMMAND_REQUEST: {
01743             uint16_t shortAddress, version;
01744             mle_tlv_info_t addressRegisteredTlv, requestTlv, challengeTlv;
01745             uint8_t response_type = MLE_COMMAND_ACCEPT_AND_REQUEST;
01746             //Router attachment
01747             tr_info("Recv Router Link request");
01748 
01749             if (!thread_attach_active_router(cur)) {
01750                 return; //Do respond until we are reed
01751             }
01752 
01753             if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) {
01754                 return;
01755             }
01756             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) {
01757                 return;
01758             }
01759             if (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
01760                 /**
01761                  * This cuold cause problem if any dummy coder add this to message
01762                  * Validate is it REED or End device message link synch Request
01763                  * - MLE_TYPE_SRC_ADDRESS
01764                  * - MLE_TYPE_VERSION
01765                  * - MLE_TYPE_CHALLENGE
01766                  */
01767                 if (mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
01768                     //Correct TLV's lets response
01769                     if (!thread_is_router_addr(shortAddress)) {
01770                         if (leaderDataReceived && thread_partition_match(cur, &leaderData)) {
01771                             //REED or end device send response
01772                             thread_router_accept_to_endevice(cur, mle_msg, challengeTlv.dataPtr, challengeTlv.tlvLen);
01773                         } else {
01774                             tr_debug("Drop Link Request from REED/ED in a different partition.");
01775                             // Do nothing... ignore.
01776                         }
01777                     }
01778                 }
01779                 return;
01780             }
01781 
01782             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01783 
01784             if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
01785 
01786                 /**
01787                  * MLE Router Synch mandatory options are
01788                  * - MLE_TYPE_VERSION
01789                  * - MLE_TYPE_CHALLENGE
01790                  * - MLE_TYPE_TLV_REQUEST
01791                  *
01792                  */
01793 
01794                 if (entry_temp && entry_temp->connected_device ) {
01795                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
01796                     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
01797                     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
01798                     thread_router_synch_accept_request_build(cur, mle_msg, entry_temp->mac16 , challengeTlv.dataPtr, challengeTlv.tlvLen, requestTlv.dataPtr, requestTlv.tlvLen);
01799                 }
01800             }
01801             bool update_mac_mib = false;
01802             /**
01803              * MLE attached First packet Mandatory TLV:s are validated at this function
01804              * - MLE_TYPE_SRC_ADDRESS
01805              * - MLE_TYPE_CHALLENGE
01806              * - MLE_TYPE_LEADER_DATA
01807              * - MLE_TYPE_VERSION
01808              * - MLE_TYPE_TLV_REQUEST
01809              */
01810 
01811             //Read Leader Data and verify connectivity
01812             if (!leaderDataReceived) {
01813                 return;
01814             }
01815 
01816             //validate partition id
01817             if (!thread_partition_match(cur, &leaderData)) {
01818                 tr_debug("Drop link request from wrong partition");
01819                 return;
01820             }
01821 
01822             if (entry_temp) {
01823                 /*remove from child list when becoming router*/
01824                 // Was this previously our child? If yes, update.
01825                 if ((entry_temp->mac16  & THREAD_CHILD_MASK) && thread_router_addr_from_addr(entry_temp->mac16 ) == cur->thread_info->routerShortAddress) {
01826                     thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
01827                     protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->mac16 );
01828                 }
01829                 update_mac_mib = true;
01830                 entry_temp->mac16  = shortAddress; // short address refreshed
01831 
01832                 if (thread_is_router_addr(shortAddress)) {
01833                     // Set full data as REED/Router needs full data (SED will not make links)
01834                     thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index , true);
01835                 }
01836 
01837                 if (entry_temp->connected_device ) {
01838                     if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
01839                         if (!entry_temp->ffd_device ) {
01840                             thread_address_registration_tlv_parse(addressRegisteredTlv.dataPtr, addressRegisteredTlv.tlvLen, cur, entry_temp->mac16 , entry_temp->mac64 );
01841                         }
01842                     }
01843 
01844                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
01845                     thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
01846                     thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
01847                     if (!mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex) &&  update_mac_mib) {
01848                         //GET
01849                         mlme_get_t get_req;
01850                         get_req.attr = macDeviceTable;
01851                         get_req.attr_index = entry_temp->index ;
01852                         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
01853                     }
01854                     response_type = MLE_COMMAND_ACCEPT;
01855                 }
01856                 response_type = MLE_COMMAND_ACCEPT;
01857             }
01858 
01859 
01860             bool accept_link = false;
01861             if (entry_temp) {
01862                 // We know already so we can accept
01863                 accept_link = true;
01864             } else if (addr_is_ipv6_multicast(mle_msg->packet_dst_address)) {
01865                 if (thread_bootstrap_link_create_check(cur, shortAddress) &&
01866                         thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
01867                     // Multicast and we can respond to message
01868                     accept_link = true;
01869                 }
01870             } else if (thread_bootstrap_link_create_check(cur, shortAddress)) {
01871                 // Unicast request and we should make link
01872                 accept_link = true;
01873             }
01874 
01875             if (accept_link) {
01876                 if (!thread_is_router_addr(shortAddress)) {
01877                     response_type = MLE_COMMAND_ACCEPT;
01878                 }
01879                 thread_router_accept_request_build(cur, mle_msg, shortAddress, challengeTlv.dataPtr, challengeTlv.tlvLen, response_type, rssiTLV, linkMargin);
01880             }
01881 
01882             break;
01883         }
01884 
01885         case MLE_COMMAND_ACCEPT_AND_REQUEST: {
01886             uint8_t linkMarginfronNeigh;
01887             uint16_t version, shortAddress;
01888             uint32_t llFrameCounter;
01889             mle_tlv_info_t requestTlv, challengeTlv;
01890             bool createNew, new_entry;
01891             tr_info("Recv Router Accept & Request");
01892             uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
01893 
01894             if (messageId == 0) {
01895                 tr_debug("No matching challenge");
01896                 return;
01897             }
01898 
01899             if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) {
01900                 //Free Response only if it is unicast
01901                 mle_service_msg_free(messageId);
01902             }
01903 
01904             if ((!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) ||
01905                     (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
01906                     (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) ||
01907                     (!mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) ||
01908                     (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
01909                     (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
01910                 thread_link_reject_send(cur, mle_msg->packet_src_address);
01911                 return;
01912             }
01913 
01914             /* Call to determine whether or not we should create a new link */
01915             createNew = thread_bootstrap_link_create_check(cur, shortAddress);
01916 
01917             //Send Response
01918 
01919             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, createNew, &new_entry);
01920             if (entry_temp) {
01921 
01922                 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, new_entry);
01923                 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
01924                 if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
01925                     thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
01926                 }
01927 
01928                 entry_temp->mac16  = shortAddress;
01929                 mlme_device_descriptor_t device_desc;
01930                 mac_helper_device_description_write(cur, &device_desc, entry_temp->mac64 , entry_temp->mac16 , llFrameCounter, false);
01931                 mac_helper_devicetable_set(&device_desc, cur, entry_temp->index , security_headers->KeyIndex, new_entry);
01932 
01933                 uint32_t link_lifetime;
01934                 if (new_entry) {
01935                     link_lifetime = THREAD_DEFAULT_LINK_LIFETIME;
01936 
01937                 } else {
01938                     link_lifetime = entry_temp->link_lifetime ;
01939                 }
01940 
01941                 mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, link_lifetime);
01942 
01943                 if (thread_is_router_addr(shortAddress)) {
01944                     entry_temp->connected_device  = 1;
01945                 }
01946 
01947                 thread_neighbor_class_request_full_data_setup_set(&cur->thread_info->neighbor_class, entry_temp->index , true);
01948 
01949                 thread_routing_update_link_margin(cur, entry_temp->mac16 , linkMargin, linkMarginfronNeigh);
01950                 //Read Source address and Challenge
01951                 mac_data_poll_protocol_poll_mode_decrement(cur);
01952                 thread_router_accept_request_build(cur, mle_msg, entry_temp->mac16 , challengeTlv.dataPtr, challengeTlv.tlvLen, MLE_COMMAND_ACCEPT, rssiTLV, linkMargin);
01953 
01954                 blacklist_update(mle_msg->packet_src_address, true);
01955             } else {
01956                 thread_link_reject_send(cur, mle_msg->packet_src_address);
01957             }
01958 
01959             break;
01960         }
01961 
01962         case MLE_COMMAND_CHILD_UPDATE_REQUEST:
01963             tr_info("Recv Router Child Update request");
01964             {
01965                 uint8_t mode;
01966                 uint8_t status;
01967                 uint32_t timeout = 0;
01968                 uint64_t active_timestamp = 0;
01969                 uint64_t pending_timestamp = 0;
01970                 mle_tlv_info_t addressRegisterTlv = {MLE_TYPE_SRC_ADDRESS, 0, 0};
01971                 mle_tlv_info_t challengeTlv = {MLE_TYPE_SRC_ADDRESS, 0, 0};
01972                 mle_tlv_info_t tlv_req = {MLE_TYPE_SRC_ADDRESS, 0, 0};
01973                 entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
01974 
01975                 if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status)) {
01976                     if (1 == status && thread_check_is_this_my_parent(cur, entry_temp)) {
01977                         tr_debug("Parent has removed REED");
01978                         mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), entry_temp);
01979                         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
01980                     }
01981                     return;
01982                 }
01983 
01984                 mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
01985 
01986                 if (!entry_temp) {
01987                     tr_debug("Not Neighbor anymore");
01988                     thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
01989                     return;
01990                 }
01991 
01992                 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01993                     tr_debug("No Mode");
01994                     return;
01995                 }
01996 
01997                 //Keep alive updated
01998                 thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
01999                 thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
02000                 mle_mode_parse_to_mac_entry(entry_temp, mode);
02001                 thread_neighbor_class_mode_parse_to_entry(&cur->thread_info->neighbor_class, entry_temp->index , mode);
02002 
02003                 addressRegisterTlv.tlvType = MLE_TYPE_UNASSIGNED;
02004                 mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisterTlv);
02005                 mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp);
02006                 mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp);
02007 
02008                 mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
02009 
02010                 if (addressRegisterTlv.tlvType == MLE_TYPE_ADDRESS_REGISTRATION &&
02011                         !entry_temp->ffd_device ) {
02012                     tr_debug("Register child address");
02013                     thread_address_registration_tlv_parse(addressRegisterTlv.dataPtr, addressRegisterTlv.tlvLen, cur, entry_temp->mac16 , entry_temp->mac64 );
02014                 }
02015 
02016                 if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
02017 
02018                     tr_debug("Setting child timeout, value=%"PRIu32, timeout);
02019                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, timeout);
02020                 } else {
02021                     mac_neighbor_table_neighbor_refresh(mac_neighbor_info(cur), entry_temp, entry_temp->link_lifetime );
02022                 }
02023 
02024                 if (!leaderDataReceived) {
02025                     tr_debug("Child synch req");
02026                 }
02027 
02028                 tr_debug("Keep-Alive -->Respond Child");
02029                 //Response
02030                 thread_child_update_response(cur, mle_msg->packet_src_address, mode, entry_temp->mac16 , timeout, &addressRegisterTlv, &tlv_req, &challengeTlv, active_timestamp, pending_timestamp);
02031 
02032             }
02033             break;
02034 
02035         case MLE_COMMAND_UPDATE:
02036             tr_info("Recv Router Update");
02037             break;
02038 
02039         case MLE_COMMAND_UPDATE_REQUEST:
02040             tr_info("Recv Router update Request");
02041             break;
02042 
02043         case MLE_COMMAND_DATA_REQUEST: {
02044             mle_tlv_info_t requestTlv;
02045             tr_info("Recv Router Data Request");
02046 
02047             entry_temp = mac_neighbor_entry_get_by_ll64(mac_neighbor_info(cur), mle_msg->packet_src_address, false, NULL);
02048             if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
02049                 return;
02050             }
02051 
02052             uint8_t mode = mle_mode_write_from_mac_entry(entry_temp);
02053             /* check if thread neighbor class is not initialized */
02054             if ((thread_neighbor_entry_linkmargin_get(&cur->thread_info->neighbor_class, entry_temp->index ) == 0) &&
02055                     (thread_neighbor_last_communication_time_get(&cur->thread_info->neighbor_class, entry_temp->index ) == 0)) {
02056                 /*
02057                  * Thread neighbor class is not yet initialized and we receive data_request from such child.
02058                  * Always send full network data in this case
02059                  */
02060                 mode |= MLE_THREAD_REQ_FULL_DATA_SET | MLE_THREAD_SECURED_DATA_REQUEST;
02061             } else {
02062                 mode |= thread_neighbor_class_mode_write_from_entry(&cur->thread_info->neighbor_class, entry_temp->index );
02063             }
02064 
02065             thread_neighbor_class_update_link(&cur->thread_info->neighbor_class, entry_temp->index , linkMargin, false);
02066             thread_neighbor_last_communication_time_update(&cur->thread_info->neighbor_class, entry_temp->index );
02067             mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, mode);
02068         }
02069         break;
02070         default:
02071             tr_warn("Recv Router UNKNOWN message %d", mle_msg->message_type);
02072             break;
02073 
02074     }
02075 }
02076 
02077 static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info_entry_t *cur)
02078 {
02079     uint8_t req_tlv[3];
02080     mle_message_timeout_params_t timeout;
02081     uint32_t keySequence;
02082     uint16_t buf_id = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
02083     if (buf_id == 0) {
02084         return -1;
02085     }
02086     thread_management_get_current_keysequence(cur->id, &keySequence);
02087     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
02088     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_ROUTERS);
02089     req_tlv[0] = MLE_TYPE_ADDRESS16;
02090     req_tlv[1] = MLE_TYPE_ROUTE;
02091     uint8_t *ptr = mle_service_get_data_pointer(buf_id);
02092     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
02093     ptr = mle_tlv_req_tlv(ptr, req_tlv, 2);
02094     if (mle_service_update_length_by_ptr(buf_id, ptr) != 0) {
02095         tr_debug("Buffer overflow at message write");
02096     }
02097 
02098     // timeout set to two seconds, no retries
02099     timeout.retrans_max = 1;
02100     timeout.timeout_init = 2;
02101     timeout.timeout_max = 3;
02102     timeout.delay = MLE_NO_DELAY;
02103 
02104     mle_service_set_packet_callback(buf_id, thread_device_synch_timeout);
02105     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
02106     mle_service_send_message(buf_id);
02107     return 0;
02108 }
02109 
02110 static int8_t thread_router_synch_new_router(protocol_interface_info_entry_t *cur, const uint8_t *destAddress)
02111 {
02112     mle_message_timeout_params_t timeout;
02113     uint32_t keySequence;
02114     if (thread_info(cur)) {
02115         if (!thread_info(cur)->thread_leader_data) {
02116             return -1;
02117         }
02118     }
02119 
02120     uint16_t bufId = mle_service_msg_allocate(cur->id, 64, true, MLE_COMMAND_REQUEST);
02121 
02122     if (bufId == 0) {
02123         return -1;
02124     }
02125     uint8_t req_tlv = MLE_TYPE_RSSI;
02126 
02127     thread_management_get_current_keysequence(cur->id, &keySequence);
02128     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
02129 
02130     mle_service_set_msg_destination_address(bufId, destAddress);
02131 
02132 
02133     uint8_t *ptr = mle_service_get_data_pointer(bufId);
02134     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
02135     ptr = thread_leader_data_tlv_write(ptr, cur);
02136     ptr = mle_general_write_source_address(ptr, cur);
02137     ptr = mle_tlv_req_tlv(ptr, &req_tlv, 1);
02138 
02139     if (!addr_is_ipv6_multicast(destAddress)) {
02140         timeout.retrans_max = 2;
02141         timeout.timeout_init = 2;
02142         timeout.timeout_max = 3;
02143         timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
02144     } else {
02145         // Multicasts need transaction timer
02146         timeout.retrans_max = 1;
02147         timeout.timeout_init = 2;
02148         timeout.timeout_max = 3;
02149         timeout.delay = 0;
02150     }
02151     mle_service_set_packet_callback(bufId, thread_link_request_timeout);
02152     mle_service_set_msg_timeout_parameters(bufId, &timeout);
02153 
02154     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
02155         tr_debug("Buffer overflow at message write");
02156     }
02157 
02158 
02159     mle_service_send_message(bufId);
02160     return 0;
02161 }
02162 
02163 int thread_router_bootstrap_link_synch_start(protocol_interface_info_entry_t *cur)
02164 {
02165     //Send Link Request for
02166     if (thread_router_bootstrap_synch_request_send(cur) == 0) {
02167         //SET Router synch receiver handler
02168         mle_service_interface_receiver_handler_update(cur->id, thread_router_synch_receive_cb);
02169         cur->nwk_bootstrap_state = ER_MLE_SYNCH;
02170         return 0;
02171     }
02172     return -1;
02173 }
02174 #ifdef HAVE_THREAD_V2
02175 
02176 static bool thread_router_bootstrap_is_version_high_for_routing(uint8_t version_threshold, uint8_t thread_ver)
02177 {
02178 
02179     if (thread_ver >= version_threshold + 3) {
02180         return true;
02181     }
02182 
02183     return false;
02184 }
02185 
02186 static void thread_router_bootstrap_pbbr_aloc_generate(struct protocol_interface_info_entry *cur)
02187 {
02188     // Check if network data changed or bbr info and send proactive an if needed
02189     uint8_t bbr_anycast_addr[16];
02190     uint8_t bbr_rloc_addr[16];
02191 
02192     thread_addr_write_mesh_local_16(bbr_anycast_addr, 0xfc38, cur->thread_info);
02193     addr_delete_matching(cur, bbr_anycast_addr, 128, ADDR_SOURCE_THREAD_ALOC);
02194 
02195     if (0 != thread_common_primary_bbr_get(cur, bbr_rloc_addr, NULL, NULL, NULL)) {
02196         // Primary BBR not present
02197         return;
02198     }
02199     if (!addr_get_entry(cur, bbr_rloc_addr)) {
02200         // Not our address
02201         return;
02202     }
02203     tr_debug("generate primary BBR anycast address %s", trace_ipv6(bbr_anycast_addr));
02204     addr_add(cur, bbr_anycast_addr, 64, ADDR_SOURCE_THREAD_ALOC, 0xffffffff, 0, true);
02205     return;
02206 }
02207 
02208 static bool thread_router_bootstrap_is_reed_upgrade_allowed(protocol_interface_info_entry_t *cur)
02209 {
02210     link_configuration_s *link_conf_ptr = thread_management_configuration_get(cur->id);
02211 
02212     if (!link_conf_ptr) {
02213         return true;
02214     }
02215 
02216     if (thread_info(cur)->version < THREAD_VERSION_1_2) {
02217         return true;
02218     }
02219 
02220     // VR check
02221     if (!(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED)) {
02222         uint8_t vr_threshold = link_conf_ptr->securityPolicyExt & THREAD_SECURITY_POLICY_VR_VALUE;
02223         if (!thread_router_bootstrap_is_version_high_for_routing(vr_threshold, cur->thread_info->version)) {
02224             return false;
02225         }
02226     }
02227 
02228     if (!(link_conf_ptr->securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED)) {
02229         // ccm network
02230         if (link_conf_ptr->securityPolicyExt & THREAD_SECURITY_POLICY_NCR_DISABLED) {
02231             // NCR bit '1' Non-CCM Routers disabled
02232             if (!thread_info(cur)->ccm_credentials_ptr) {
02233                 // Device does not have domain certificate
02234                 return false;
02235             }
02236         }
02237     }
02238 
02239     return true;
02240 }
02241 #else
02242 #define thread_router_bootstrap_pbbr_aloc_generate(cur)
02243 #endif
02244 
02245 
02246 bool thread_router_bootstrap_router_downgrade(protocol_interface_info_entry_t *cur)
02247 {
02248     uint8_t activeRouterCount;
02249     uint8_t goodLinks;
02250 
02251     if (cur->thread_info->thread_attached_state != THREAD_STATE_CONNECTED_ROUTER) {
02252         return false;
02253     }
02254 
02255     // if we are commissioner border router we have registered our address and cant upgrade or downgrade
02256     if (cur->thread_info->registered_commissioner.commissioner_valid &&
02257             addr_get_entry(cur, cur->thread_info->registered_commissioner.border_router_address)) {
02258         return false;
02259     }
02260 
02261     // spec: Not be the Leader
02262     if (cur->thread_info->leader_private_data) {
02263         if (!thread_router_bootstrap_routing_allowed(cur)) {
02264             tr_debug("Cannot be leader anymore");
02265             // Settings have changed, cannot be leader anymore
02266             thread_bootstrap_reset_restart(cur->id);
02267         }
02268         // Leader can not downgrade
02269         return false;
02270     }
02271 
02272     if (!thread_router_bootstrap_routing_allowed(cur)) {
02273         return true;
02274     }
02275 
02276     //spec: If the number of active Routers on the network exceeds ROUTER_DOWNGRADE_THRESHOLD
02277     activeRouterCount = thread_routing_count_active_routers(&cur->thread_info->routing);
02278     if (activeRouterCount <= cur->thread_info->routerSelectParameters.routerDowngradeThresHold) {
02279         return false;
02280     }
02281 
02282     uint_fast8_t asGood;
02283     goodLinks = thread_routing_count_neighbours_for_downgrade(&cur->thread_info->routing, &asGood);
02284 
02285     //spec: Have at least MIN_DOWNGRADE_NEIGHBORS neighbors in set M.
02286     if (goodLinks < MIN_DOWNGRADE_NEIGHBORS) {
02287         return false;
02288     }
02289 
02290     //spec: Have at least one neighbor that has as good or better quality links to all Routers in M.
02291     if (asGood == 0) {
02292         return false;
02293     }
02294 
02295     //spec: Not be the sole Border Router for a particular Provisioning Domain
02296     if (!ns_list_is_empty(&cur->thread_info->localServerDataBase.prefix_list)) {
02297         return false;
02298     }
02299 
02300     uint16_t child_count = thread_router_bootstrap_child_count_get(cur);
02301     //Cant downgrade if child count is larger than 3 times exceed routers
02302     if (child_count > (3 * (activeRouterCount - cur->thread_info->routerSelectParameters.routerDowngradeThresHold))) {
02303         return false;
02304     }
02305     tr_info("Reed downgrade:ChildCount %u Active Routers %u good links %u downgrade threshold %u", child_count, activeRouterCount, goodLinks, cur->thread_info->routerSelectParameters.routerDowngradeThresHold);
02306 
02307     return true;
02308 }
02309 
02310 bool thread_router_bootstrap_reed_upgrade(protocol_interface_info_entry_t *cur)
02311 {
02312     uint8_t activeRouterCount;
02313 
02314     if (!thread_router_bootstrap_routing_allowed(cur)) {
02315         return false;
02316     }
02317 
02318     if (!thread_router_bootstrap_is_reed_upgrade_allowed(cur)) {
02319         return false;
02320     }
02321 
02322     if (thread_am_router(cur)) {
02323         return false;
02324     }
02325 
02326     // if we are commissioner border router we have registered our address and cant upgrade or downgrade
02327     if (cur->thread_info->registered_commissioner.commissioner_valid &&
02328             addr_get_entry(cur, cur->thread_info->registered_commissioner.border_router_address)) {
02329         return false;
02330     }
02331 
02332     if (!cur->thread_info->routing.router_id_sequence_valid) {
02333         // In case routing information is not up-to-date yet...
02334         return false;
02335     }
02336 
02337     activeRouterCount = thread_routing_count_active_routers(&cur->thread_info->routing);
02338 
02339     if (activeRouterCount >= cur->thread_info->routerSelectParameters.routerUpgradeThresHold) {
02340         return false;
02341     }
02342     tr_info("Reed Upgrade:Active Routers %u upgrade threshold %u", activeRouterCount, cur->thread_info->routerSelectParameters.routerUpgradeThresHold);
02343 
02344     return true;
02345 }
02346 
02347 void thread_router_bootstrap_child_id_reject(protocol_interface_info_entry_t *cur)
02348 {
02349     thread_pending_child_id_req_t *req;
02350     req = thread_child_id_request_entry_get_from_the_list(cur);
02351     while (req) {
02352         tr_debug("Remove entry from list");
02353         //Remove entry from list
02354         mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), req->euid64, ADDR_802_15_4_LONG );
02355         if (neighbor) {
02356             mac_neighbor_table_neighbor_remove(mac_neighbor_info(cur), neighbor);
02357         }
02358 
02359         ns_dyn_mem_free(req);
02360         req = thread_child_id_request_entry_get_from_the_list(cur);
02361     }
02362 }
02363 
02364 void thread_router_bootstrap_active_router_attach(protocol_interface_info_entry_t *cur)
02365 {
02366     uint8_t *parent_mac_addr = NULL;
02367     arm_nwk_6lowpan_thread_test_print_routing_database(cur->id);
02368     uint16_t address16 = mac_helper_mac16_address_get(cur);
02369     cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER;
02370 
02371     if (cur->thread_info->thread_leader_data->leaderRouterId == address16 &&
02372             !cur->thread_info->leader_private_data) {
02373         // Error we are set up as leader but no private data
02374         tr_error("Leader setup error");
02375     }
02376     cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
02377     thread_routing_activate(&cur->thread_info->routing);
02378     thread_router_synch_new_router(cur, ADDR_LINK_LOCAL_ALL_ROUTERS);
02379     thread_bootstrap_ready(cur);
02380     thread_bootstrap_network_prefixes_process(cur);
02381     thread_nd_service_activate(cur->id);
02382     thread_router_bootstrap_mle_advertise(cur);
02383     if (cur->thread_info->thread_endnode_parent) {
02384         parent_mac_addr = cur->thread_info->thread_endnode_parent->mac64;
02385     }
02386     thread_nvm_store_link_info_write(parent_mac_addr, mac_helper_mac16_address_get(cur));
02387 }
02388 
02389 static int thread_validate_own_routeid_from_new_mask(const uint8_t *master_router_id_mask, uint8_t router_id)
02390 {
02391     int ret_val = -1;
02392     if (bit_test(master_router_id_mask, router_id)) {
02393         ret_val = 0;
02394     }
02395     return ret_val;
02396 }
02397 
02398 int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, struct mac_neighbor_table_entry *entry)
02399 {
02400     (void) route_len;
02401 
02402     uint8_t route_id_seq;
02403     const uint8_t *router_id_mask, *route_data;
02404 
02405     route_id_seq = *route_tlv++;
02406     router_id_mask = route_tlv;
02407     route_tlv += 8;
02408     route_data = route_tlv;
02409     uint16_t mac16 = mac_helper_mac16_address_get(cur);
02410 
02411     if (!thread_is_router_addr(entry->mac16 )) {
02412         // Received route tlv from non router ignore
02413         tr_info("drop route Processing from end device %x", entry->mac16 );
02414         return 0;
02415     }
02416 
02417     if (thread_i_am_router(cur)) {
02418         thread_routing_info_t *routing = &cur->thread_info->routing;
02419         if (routing->router_id_sequence_valid && common_serial_number_greater_8(route_id_seq, routing->router_id_sequence)) {
02420             thread_routing_leader_connection_validate(cur->thread_info, routing->networkFragmentationTimer);
02421             routing->networkFragmentationTimer = 0;
02422             if (thread_validate_own_routeid_from_new_mask(router_id_mask, thread_router_id_from_addr(mac16)) != 0) {
02423                 tr_debug("RouterID not valid any More");
02424                 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_KICK, NULL);
02425                 return 0;
02426             }
02427         }
02428     } else if (!thread_info(cur)->thread_endnode_parent ||
02429                thread_info(cur)->thread_endnode_parent->shortAddress != entry->mac16 ) {
02430         return 0;
02431     }
02432 
02433     /* XXX Is short_src_adr ever reset? Is it undefined if info not in msg? */
02434     /* Don't add routing link if MLE link is NOT bi-directional (i.e. we can only hear) */
02435     if (entry->connected_device ) {
02436         thread_routing_add_link(cur, entry->mac16 , linkMargin, route_id_seq, router_id_mask, route_data, false);
02437     }
02438 
02439     return 0;
02440 }
02441 
02442 
02443 static void thread_bootstrap_client_router_id_release_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9])
02444 {
02445     protocol_interface_info_entry_t *cur;
02446     (void) status;
02447     (void)router_mask_ptr;
02448     (void)router_rloc;
02449     cur = protocol_stack_interface_info_get_by_id(interface_id);
02450     tr_debug("RouterID ReleaseCB");
02451     if (!cur) {
02452         return;
02453     }
02454 
02455     if (!cur->thread_info->releaseRouterId) {
02456         return;
02457     }
02458     cur->thread_info->releaseRouterId = false;
02459 
02460     thread_bootstrap_router_id_release_ready(cur);
02461     return;
02462 
02463 }
02464 static uint32_t thread_reed_timeout_calculate(thread_router_select_t *routerSelect)
02465 {
02466     return randLIB_get_random_in_range(routerSelect->reedAdvertisementInterval, (routerSelect->reedAdvertisementInterval) + (routerSelect->reedAdvertisementJitterInterval));
02467 }
02468 
02469 
02470 static int thread_reed_advertise(protocol_interface_info_entry_t *cur)
02471 {
02472     uint32_t keySequence;
02473     struct link_configuration *linkConfiguration;
02474     linkConfiguration = thread_joiner_application_get_config(cur->id);
02475     if (!linkConfiguration) {
02476         return -1;
02477     }
02478 
02479     if (!thread_info(cur)) {
02480         return -1;
02481     }
02482 
02483     // FED not allowed to send advertisements
02484     if (thread_info(cur)->thread_device_mode == THREAD_DEVICE_MODE_FULL_END_DEVICE) {
02485         return -1;
02486     }
02487 
02488     uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT);
02489     if (bufId == 0) {
02490         return -1;
02491     }
02492 
02493     tr_debug("MLE REED ADVERTISEMENT STARTED");
02494     thread_management_get_current_keysequence(cur->id, &keySequence);
02495     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
02496 
02497     uint8_t *ptr = mle_service_get_data_pointer(bufId);
02498 
02499     /*Add Leader Data & Source Address TLVs */
02500     ptr = thread_leader_data_tlv_write(ptr, cur);
02501     ptr = mle_general_write_source_address(ptr, cur);
02502     if (mle_service_update_length_by_ptr(bufId, ptr) != 0) {
02503         tr_debug("Buffer overflow at message write");
02504     }
02505 
02506     mle_service_set_msg_destination_address(bufId, ADDR_LINK_LOCAL_ALL_NODES);
02507     mle_service_send_message(bufId);
02508     return 0;
02509 }
02510 
02511 static void thread_reed_advertisements_cb(void *arg)
02512 {
02513     if (!arg) {
02514         return;
02515     }
02516     protocol_interface_info_entry_t *cur = arg;
02517 
02518     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = NULL;
02519 
02520     if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
02521         /* Own attach is ongoing, try to send advertisement after few seconds */
02522         cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb, 2 * 1000, cur);
02523         return;
02524     }
02525 
02526     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED &&
02527             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) {
02528         thread_reed_advertise(cur);
02529         thread_router_bootstrap_child_information_clear(cur);
02530         cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb, thread_reed_timeout_calculate(&cur->thread_info->routerSelectParameters) * 1000, cur);
02531     }
02532 }
02533 
02534 void thread_router_bootstrap_reed_advertisements_start(protocol_interface_info_entry_t *cur)
02535 {
02536     uint32_t timeout = THREAD_REED_ADVERTISEMENT_DELAY;
02537     if (!cur) {
02538         return;
02539     }
02540     eventOS_timeout_cancel(cur->thread_info->routerSelectParameters.reedAdvertisementTimeout);
02541     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = NULL;
02542 
02543     cur->thread_info->reedJitterTimer = thread_router_bootstrap_random_upgrade_jitter();
02544 
02545     if (!thread_is_connected(cur)) {
02546         return;
02547     }
02548     if (cur->thread_info->releaseRouterId  ||
02549             thread_router_bootstrap_child_count_get(cur) == 0) {
02550         // If we dont have any children or are are downgrading send REED advertisement immediately
02551         timeout = 1;
02552     }
02553     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb, timeout, cur);
02554 }
02555 
02556 void thread_router_bootstrap_reed_merge_advertisement(protocol_interface_info_entry_t *cur)
02557 {
02558     if (cur->thread_info->reedMergeAdvTimer > 1) {
02559         return;
02560     }
02561     thread_reed_advertise(cur);
02562     // 120s second timer reinitialised before next merge advertisement
02563     cur->thread_info->reedMergeAdvTimer = THREAD_REED_MERGE_ADVERTISEMENT_INTERVAL;
02564 
02565 }
02566 void thread_router_bootstrap_router_id_release(protocol_interface_info_entry_t *cur)
02567 {
02568     tr_debug("Router ID Release");
02569     if (thread_management_client_router_id_release(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_release_cb) == 0) {
02570         // Release message sent succesfully
02571         cur->thread_info->routerShortAddress = 0xfffe;
02572         cur->thread_info->releaseRouterId = true;
02573     }
02574 }
02575 
02576 uint32_t thread_router_bootstrap_random_upgrade_jitter()
02577 {
02578     if (thread_router_selection_jitter <= 2) {
02579         return 1;
02580     }
02581     return randLIB_get_random_in_range(2, thread_router_selection_jitter);
02582 }
02583 
02584 void thread_router_bootstrap_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
02585 {
02586     thread_info_t *thread_info = cur->thread_info;
02587 
02588     if (thread_am_host(cur)) {
02589         return;
02590     }
02591 
02592     //Do we have a childs and we are REED state
02593     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && thread_router_bootstrap_child_count_get(cur)) {
02594         tr_debug("Trig quick router ID request");
02595         thread_bootstrap_attched_upgrade_reed(cur);
02596         return;
02597     }
02598 
02599     if (thread_info->reedJitterTimer > ticks) {
02600         // Reed status is checked every random jitter values
02601         thread_info->reedJitterTimer -= ticks;
02602     } else {
02603         thread_info->reedJitterTimer = thread_router_bootstrap_random_upgrade_jitter();
02604         if (thread_router_bootstrap_reed_upgrade(cur)) {
02605             //Check UpGrade possibility
02606             tr_debug("REED Upgrade to router");
02607             thread_bootstrap_attched_upgrade_reed(cur);
02608         }
02609         if (thread_router_bootstrap_router_downgrade(cur)) {
02610             tr_debug("Router downgrade to REED");
02611             thread_bootstrap_attached_downgrade_router(cur);
02612         }
02613     }
02614 
02615     if (cur->thread_info->reedMergeAdvTimer > ticks) {
02616         cur->thread_info->reedMergeAdvTimer -= ticks;
02617     } else {
02618         cur->thread_info->reedMergeAdvTimer = 0;
02619     }
02620 
02621     if (!thread_info->leader_private_data && thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
02622         // Non leader router checks
02623         if (thread_info->routing.activated) {
02624             if (thread_info->routing.networkFragmentationTimer++ >= thread_info->routing.networkIdTimeout) {
02625                 tr_debug("Leader Connection Lost");
02626                 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_REATTACH, NULL);
02627             }
02628         } else {
02629             tr_debug("Routing Disabled?");
02630         }
02631     }
02632 
02633     if (thread_info->proactive_an_timer) {
02634         if (thread_info->proactive_an_timer > ticks) {
02635             thread_info->proactive_an_timer -= ticks;
02636         } else {
02637             thread_send_proactive_an(cur);
02638             thread_info->proactive_an_timer = 0;
02639         }
02640     }
02641 
02642     thread_leader_service_timer(cur, ticks);
02643     return;
02644 }
02645 
02646 void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, struct mac_neighbor_table_entry *entry_temp, uint16_t shortAddress)
02647 {
02648     if (entry_temp) {
02649 
02650         if (thread_is_router_addr(shortAddress)) {
02651             entry_temp->link_lifetime  = THREAD_DEFAULT_LINK_LIFETIME;
02652             entry_temp->link_lifetime ++;
02653         }
02654 
02655         if (thread_is_router_addr(shortAddress)) {
02656             //Update MAC Security PIB table by get & set Operation
02657             mlme_get_t get_req;
02658             get_req.attr = macDeviceTable;
02659             get_req.attr_index = entry_temp->index ;
02660             cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
02661             entry_temp->lifetime  = entry_temp->link_lifetime ;
02662         }
02663     } else {
02664         //
02665         if (!thread_attach_active_router(cur)) {
02666             // We are not router
02667             return;
02668         }
02669         if (!thread_is_router_addr(shortAddress)) {
02670             // Reed advertisement
02671             return;
02672         }
02673         if (thread_bootstrap_link_create_check(cur, shortAddress) &&
02674                 thread_bootstrap_link_create_allowed(cur, shortAddress, src_address)) {
02675             //Challenge new router neighbor
02676             tr_debug("Synch new neighbor");
02677             thread_router_synch_new_router(cur, src_address);
02678         }
02679     }
02680 }
02681 static void thread_router_bootstrap_dhcp_server_any_cast_address_update(protocol_interface_info_entry_t *cur, uint16_t anycastAddress)
02682 {
02683     uint8_t ipv6_address[16];
02684 
02685     thread_addr_write_mesh_local_16(ipv6_address, anycastAddress, cur->thread_info);
02686     tr_debug("generate DHCP anycast address %s", trace_ipv6(ipv6_address));
02687     addr_add(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC, 0xffffffff, 0, true);
02688 }
02689 
02690 static void thread_bootstrap_dhcp_anycast_address_generate(protocol_interface_info_entry_t *cur)
02691 {
02692     uint8_t ipv6_address[16];
02693     thread_addr_write_mesh_local_16(ipv6_address, 0xfc00, cur->thread_info);
02694     addr_delete_matching(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC);
02695 
02696     ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &cur->thread_info->networkDataStorage.localPrefixList) {
02697         // Go through all prefixes
02698         ns_list_foreach(thread_network_server_data_entry_t, curBorderRouter, &curPrefix->borderRouterList) {
02699             if (curBorderRouter->P_dhcp &&
02700                     curBorderRouter->routerID == cur->mac_parameters->mac_short_address) {
02701                 // We host this dhcp service we must add anycast address
02702                 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) {
02703                     // Search what is the context id for this prefix
02704                     uint16_t anycastAddress = 0xfc00;
02705                     anycastAddress |= curRoute->cid;
02706                     thread_router_bootstrap_dhcp_server_any_cast_address_update(cur, anycastAddress);
02707                 }
02708             }
02709         }
02710     }
02711 }
02712 
02713 static void thread_bootstrap_service_anycast_address_generate(protocol_interface_info_entry_t *cur)
02714 {
02715     uint8_t ipv6_address[16];
02716 
02717     // Delete old address
02718     thread_addr_write_mesh_local_16(ipv6_address, 0xfc10, cur->thread_info);
02719     addr_delete_matching(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC);
02720 
02721     ns_list_foreach(thread_network_data_service_cache_entry_t, curService, &cur->thread_info->networkDataStorage.service_list) {
02722         // Go through all prefixes
02723         ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) {
02724             if (curServiceServer->router_id == cur->mac_parameters->mac_short_address) {
02725                 // We host this service we must add anycast address
02726                 // Search what is the context id for this prefix
02727                 thread_addr_write_mesh_local_16(ipv6_address, 0xfc10 | curService->S_id, cur->thread_info);
02728                 tr_debug("generate Service anycast address %s", trace_ipv6(ipv6_address));
02729                 addr_add(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC/*?*/, 0xffffffff, 0, true);
02730             }
02731         }
02732     }
02733 }
02734 
02735 
02736 static void thread_router_bootstrap_commissioner_aloc_generate(protocol_interface_info_entry_t *cur)
02737 {
02738     uint8_t commissioner_anycast[16];
02739 
02740     // Delete old address
02741     thread_addr_write_mesh_local_16(commissioner_anycast, 0xfc30 + (cur->thread_info->registered_commissioner.session_id % 8), cur->thread_info);
02742     addr_delete_matching(cur, commissioner_anycast, 125, ADDR_SOURCE_THREAD_ALOC);
02743 
02744     if (!cur->thread_info->registered_commissioner.commissioner_valid) {
02745         // No commissioner available
02746         return;
02747     }
02748 
02749     if (!addr_get_entry(cur, cur->thread_info->registered_commissioner.border_router_address)) {
02750         // Not our address
02751         return;
02752     }
02753     // Add commissioning border router address
02754     tr_debug("generate commissioner anycast address %s", trace_ipv6(commissioner_anycast));
02755     addr_add(cur, commissioner_anycast, 64, ADDR_SOURCE_THREAD_ALOC, 0xffffffff, 0, true);
02756 }
02757 
02758 void thread_router_bootstrap_anycast_address_register(protocol_interface_info_entry_t *cur)
02759 {
02760     uint8_t leader_anycast_address[16];
02761 
02762     tr_debug("Register anycast address:");
02763 
02764     // Generate leader ALOC address
02765     thread_addr_write_mesh_local_16(leader_anycast_address, 0xfc00, cur->thread_info);
02766 
02767     if (cur->thread_info->leader_private_data) {
02768         tr_debug("Register leader anycast address: %s", trace_ipv6(leader_anycast_address));
02769         addr_add(cur, leader_anycast_address, 128, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0, true);
02770     } else {
02771         // Delete Leader ALOC if ml prefix was changed address Source is the defining rule
02772         addr_delete_matching(cur, leader_anycast_address, 128, ADDR_SOURCE_UNKNOWN);
02773 
02774     }
02775     thread_bootstrap_dhcp_anycast_address_generate(cur);
02776     thread_bootstrap_service_anycast_address_generate(cur);
02777     thread_router_bootstrap_commissioner_aloc_generate(cur);
02778     thread_router_bootstrap_pbbr_aloc_generate(cur);
02779 }
02780 
02781 static int thread_router_bootstrap_network_data_propagation(protocol_interface_info_entry_t *cur, uint8_t *childUnicastAddress, bool fullList)
02782 {
02783     uint8_t *payload_ptr;
02784     uint16_t payload_size = 16 + 4 + 20 + 4; //Version 4 bytes and Source address 4 bytes
02785     struct link_configuration *linkConfiguration;
02786     linkConfiguration = thread_joiner_application_get_config(cur->id);
02787     if (!linkConfiguration) {
02788         return -1;
02789     }
02790 
02791     if (!thread_info(cur)) {
02792         return -1;
02793     }
02794 
02795     payload_size += 2 + thread_network_data_tlv_size(cur, fullList);
02796     payload_size += thread_pending_timestamp_tlv_size(cur);
02797 
02798     mle_message_timeout_params_t timeout;
02799     uint16_t buf_id = mle_service_msg_allocate(cur->id, payload_size, false, MLE_COMMAND_DATA_RESPONSE);
02800     if (buf_id == 0) {
02801         return -1;
02802     }
02803 
02804     tr_debug("Send MLE data response network data changed");
02805     payload_ptr = mle_service_get_data_pointer(buf_id);
02806     uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(buf_id);
02807 
02808     /* Send to ULA16 of DATA_REQUEST originator. */
02809     /* Current_gp_prefix should have ULA prefix in */
02810     if (childUnicastAddress) {
02811         memcpy(address_ptr, childUnicastAddress, 16);
02812     } else {
02813         memcpy(address_ptr, ADDR_LINK_LOCAL_ALL_NODES, 16);
02814     }
02815 
02816     /*Add Leader Data & Network Data */
02817     payload_ptr = thread_leader_data_tlv_write(payload_ptr, cur);
02818     payload_ptr = thread_network_data_tlv_write(cur, payload_ptr, fullList);
02819 
02820     payload_ptr = thread_active_timestamp_write(cur, payload_ptr);
02821     payload_ptr = thread_pending_timestamp_write(cur, payload_ptr);
02822     payload_ptr = mle_general_write_source_address(payload_ptr, cur);
02823 
02824     if (mle_service_update_length_by_ptr(buf_id, payload_ptr) != 0) {
02825         tr_debug("Buffer overflow at message write");
02826     }
02827     timeout.retrans_max = 0;
02828     timeout.timeout_init = 0;
02829     timeout.timeout_max = 0;
02830     timeout.delay = MLE_HALF_SECOND_MAX_DELAY;
02831     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
02832     //Set Security
02833     uint32_t keySequence;
02834     thread_management_get_current_keysequence(cur->id, &keySequence);
02835     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
02836 
02837     mle_service_send_message(buf_id);
02838     return 0;
02839 
02840 }
02841 
02842 static void thread_router_bootstrap_network_data_push_to_sleep_child(protocol_interface_info_entry_t *cur, bool stableDataUpdate)
02843 {
02844     uint8_t childLinkLocalAddress[16];
02845     mac_neighbor_table_list_t *mac_table_list = &mac_neighbor_info(cur)->neighbour_list;
02846 
02847     memcpy(childLinkLocalAddress, ADDR_LINK_LOCAL_PREFIX, 8);
02848     ns_list_foreach(mac_neighbor_table_entry_t, cur_entry, mac_table_list) {
02849         if (!cur_entry->rx_on_idle) {
02850             memcpy(&childLinkLocalAddress[8], cur_entry->mac64, 8);
02851             childLinkLocalAddress[8] ^= 2;
02852             if (thread_neighbor_class_request_full_data_setup(&cur->thread_info->neighbor_class, cur_entry->index)) {
02853                 thread_router_bootstrap_network_data_propagation(cur, childLinkLocalAddress, true);
02854             } else {
02855                 if (stableDataUpdate) {
02856                     thread_router_bootstrap_network_data_propagation(cur, childLinkLocalAddress, false);
02857                 }
02858             }
02859         }
02860     }
02861 }
02862 
02863 void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur)
02864 {
02865     if (!thread_i_am_router(cur)) {
02866         return;
02867     }
02868     tr_debug("Propagate New Network Data");
02869     thread_router_bootstrap_network_data_propagation(cur, NULL, true);
02870     thread_router_bootstrap_network_data_push_to_sleep_child(cur, cur->thread_info->networkDataStorage.stableUpdatePushed);
02871 }
02872 
02873 bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur)
02874 {
02875     link_configuration_s *link_conf_ptr = thread_management_configuration_get(cur->id);
02876 
02877     if (!link_conf_ptr) {
02878         return true;
02879     }
02880 
02881     return !(thread_info(cur)->version < THREAD_VERSION_1_2 && !(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED));
02882 }
02883 
02884 void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur)
02885 {
02886     thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY;
02887 }
02888 
02889 void thread_router_bootstrap_delay_reed_jitter(int8_t interface_id, uint16_t delay)
02890 {
02891     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
02892     if (!cur) {
02893         return;
02894     }
02895     if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER) {
02896         return;
02897     }
02898     // delay reed jitter timer to allow for settings changes to distribute
02899     thread_info(cur)->reedJitterTimer += delay;
02900     return;
02901 }
02902 
02903 #endif /* HAVE_THREAD_ROUTER */