takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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