Knight KE / Mbed OS Game_Master
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-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
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 "thread_management_if.h"
00070 #include "Common_Protocols/ipv6.h"
00071 #include "Common_Protocols/icmpv6.h"
00072 #include "Common_Protocols/icmpv6_radv.h"
00073 #include "MLE/mle.h"
00074 #include "MLE/mle_tlv.h"
00075 #include "thread_config.h"
00076 #include "multicast_api.h"
00077 #include "Service_Libs/nd_proxy/nd_proxy.h"
00078 #include "Service_Libs/mle_service/mle_service_api.h"
00079 #include "Service_Libs/blacklist/blacklist.h"
00080 #include "thread_dhcpv6_client.h"
00081 #include "6LoWPAN/MAC/mac_helper.h"
00082 #include "mac_api.h"
00083 #include "6LoWPAN/MAC/mac_data_poll.h"
00084 #include "thread_border_router_api.h"
00085 #include "Core/include/address.h"
00086 
00087 #ifdef HAVE_THREAD_ROUTER
00088 
00089 #define TRACE_GROUP "trbs"
00090 
00091 static bool thread_rfd_device(uint8_t mode);
00092 static uint8_t *thread_tlv_add(protocol_interface_info_entry_t *cur, uint8_t *ptr, uint8_t tlv_type, uint8_t mode);
00093 
00094 static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf);
00095 
00096 static void thread_bootstrap_client_router_id_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9]);
00097 static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers);
00098 static void thread_bootstrap_client_router_id_release_cb(int8_t interface_id, int8_t status, uint16_t router_rloc, const uint8_t router_mask_ptr[9]);
00099 
00100 static int thread_router_synch_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t *tlvReq, uint8_t tlvReqLen);
00101 static int thread_router_accept_to_endevice(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint8_t *challenge, uint8_t chalLen);
00102 static int thread_router_accept_request_build(protocol_interface_info_entry_t *cur, mle_message_t *mle_msg, uint16_t shortAddress, uint8_t *challenge, uint8_t chalLen, uint8_t type, bool rssi_tlv, uint8_t rssi);
00103 static int thread_child_update_response(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t mode, uint16_t short_address, uint32_t timeout, mle_tlv_info_t *addressRegisterTlv,mle_tlv_info_t *tlvReq, mle_tlv_info_t *challengeTlv, uint64_t active_timestamp, uint64_t pending_timestamp);
00104 static int mle_build_and_send_data_response_msg(protocol_interface_info_entry_t *cur, uint8_t *dst_address, uint8_t *data_ptr, uint16_t data_len, mle_tlv_info_t *request_tlv, uint8_t mode);
00105 static int thread_attach_parent_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress, uint8_t *challenge, uint16_t chalLen, uint8_t linkMargin, uint8_t scanMask, uint8_t mode);
00106 static int mle_attach_child_id_response_build(protocol_interface_info_entry_t *cur, uint8_t *dstAddress,thread_pending_child_id_req_t *child_req,mle_neigh_table_entry_t *neigh_info);
00107 
00108 static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info_entry_t *cur);
00109 static bool thread_child_id_request(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp);
00110 
00111 static bool thread_rfd_device(uint8_t mode)
00112 {
00113     if ((mode & MLE_DEV_MASK) != MLE_RFD_DEV) {
00114         return false;
00115     }
00116     return true;
00117 }
00118 
00119 static bool thread_router_parent_address_check(protocol_interface_info_entry_t *cur, uint8_t *source_addr)
00120 {
00121     if (thread_info(cur)->thread_endnode_parent &&
00122             addr_iid_matches_eui64(source_addr + 8, thread_info(cur)->thread_endnode_parent->mac64)) {
00123         return true;
00124     }
00125 
00126     return false;
00127 }
00128 
00129 static void thread_send_proactive_an(protocol_interface_info_entry_t *cur)
00130 {
00131     ns_list_foreach(if_address_entry_t, e, &cur->ip_addresses) {
00132         if (e->source == ADDR_SOURCE_DHCP || e->source == ADDR_SOURCE_SLAAC) {
00133             uint8_t br_ml_addr[16];
00134             ns_list_foreach(thread_network_data_prefix_cache_entry_t, prefix, &cur->thread_info->networkDataStorage.localPrefixList) {
00135                 uint8_t prefixBytesLen = prefixBits_to_bytes(prefix->servicesPrefixLen);
00136 
00137                 if (memcmp(e->address, prefix->servicesPrefix, prefixBytesLen) != 0) {
00138                     continue;
00139                 }
00140 
00141                 ns_list_foreach(thread_network_server_data_entry_t, br, &prefix->borderRouterList) {
00142                     if (br->routerID == 0xfffe) {
00143                         continue;
00144                     }
00145 
00146                     uint16_t rloc16 = mac_helper_mac16_address_get(cur);
00147 
00148                     thread_addr_write_mesh_local_16(br_ml_addr, br->routerID, cur->thread_info);
00149                     tr_debug("Sending proactive AN to border router: %s", trace_ipv6(br_ml_addr));
00150                     thread_management_client_proactive_an(cur->id, e->address , rloc16, cur->iid_slaac, br_ml_addr);
00151                 }
00152             }
00153         }
00154     }
00155 }
00156 
00157 int thread_router_bootstrap_mle_advertise(protocol_interface_info_entry_t *cur)
00158 {
00159     /* How was this 40 calculated? Seems to be more than enough, at least.
00160      * MODE = 2+1, SRC_ADDR = 2+2, LINK = 2+1+4*neighbours, ROUTE = 2+MLE_ROUTE_MIN_OPTION_LEN+routers
00161      * Total = 10 + neighbours * 4
00162      */
00163     uint16_t neig_cache_size = 40 + 3;
00164     uint8_t *ptr;
00165 
00166     if (!cur) {
00167         return -1;
00168     }
00169 
00170     if (!thread_is_connected(cur)) {
00171         return -1;
00172     }
00173 
00174     if (thread_i_am_router(cur)) {
00175         neig_cache_size += thread_route_option_size(cur);
00176         neig_cache_size += thread_leader_data_tlv_size(cur);
00177     }
00178 
00179     uint16_t buf_id = mle_service_msg_allocate(cur->id, neig_cache_size, false, MLE_COMMAND_ADVERTISEMENT);
00180     if (buf_id == 0) {
00181         return -1;
00182     }
00183 
00184     uint32_t keySequence;
00185     if (thread_management_get_current_keysequence(cur->id, &keySequence) == 0) {
00186         mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
00187     }
00188 
00189     //SET Destination address
00190     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_NODES);
00191 
00192     ptr = mle_service_get_data_pointer(buf_id);
00193     ptr = mle_general_write_source_address(ptr, cur);
00194     if (thread_i_am_router(cur)) {
00195         ptr = thread_route_option_write(cur, ptr);
00196     } else {
00197         *ptr++ = MLE_TYPE_ROUTE;
00198          *ptr++ = 0;
00199     }
00200 
00201     ptr = thread_leader_data_tlv_write(ptr, cur);
00202 
00203     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
00204         tr_debug("Buffer overflow at message write");
00205     }
00206 
00207     tr_debug("Send MLE Secured Advertisement");
00208     return mle_service_send_message(buf_id);
00209 
00210 }
00211 
00212 static void clone_multicast_to_unicast(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *mle_entry, buffer_t *buf)
00213 {
00214     link_configuration_s *linkConfiguration = thread_joiner_application_get_config(cur->id);
00215     if (!linkConfiguration) {
00216         return;
00217     }
00218 
00219     buffer_t *new_buf = buffer_clone(buf);
00220     if ((new_buf->info  & B_DIR_MASK) == B_DIR_UP) {
00221         buffer_data_pointer(new_buf)[IPV6_HDROFF_HOP_LIMIT] = --new_buf->options .hop_limit ;
00222     }
00223 
00224     new_buf->info  = (buffer_info_t) (B_DIR_DOWN | B_TO_IPV6_TXRX | B_FROM_IPV6_FWD);
00225     uint8_t next_hop[16];
00226     memcpy(next_hop, ADDR_LINK_LOCAL_PREFIX, 8);
00227     memcpy(&next_hop[8], mle_entry->mac64, 8);
00228     next_hop[8] ^= 2;
00229 
00230     ipv6_buffer_route_to(new_buf, next_hop, cur);
00231     protocol_push(new_buf);
00232     tr_debug("Cloned %s to %s", tr_ipv6(buf->dst_sa .address ), tr_ipv6(next_hop));
00233 }
00234 
00235 static void mle_multicast_push_to_sleep_child(protocol_interface_info_entry_t *cur, buffer_t *buf)
00236 {
00237     mle_neigh_table_list_t *mle_neigh_list = mle_class_active_list_get(cur->id);
00238     if (!mle_neigh_list) {
00239         return;
00240     }
00241     ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_neigh_list) {
00242         if (cur_entry->threadNeighbor) {
00243             if (!(cur_entry->mode & MLE_RX_ON_IDLE)) {
00244                 clone_multicast_to_unicast(cur, cur_entry, buf);
00245             }
00246         }
00247     }
00248 }
00249 
00250 static void thread_multicast_forward_to_child(protocol_interface_info_entry_t *cur, buffer_t *buffer)
00251 {
00252     mle_multicast_push_to_sleep_child(cur, buffer);
00253 }
00254 
00255 static void thread_registered_mcast_forward_to_child(protocol_interface_info_entry_t *cur, buffer_t *buffer)
00256 {
00257     thread_registered_mcast_addr_t *addr = thread_registered_mcast_addr_entry_find(cur, buffer->dst_sa .address );
00258 
00259     if (addr) {
00260         tr_debug("Forwarding to registered multicast address: %s", trace_ipv6(addr->address));
00261 
00262         ns_list_foreach(thread_mcast_child_t, child, &addr->children) {
00263             mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, child->mac64, ADDR_802_15_4_LONG );
00264             if (mle_entry && mle_entry->threadNeighbor && !(mle_entry->mode & MLE_RX_ON_IDLE)) {
00265                 clone_multicast_to_unicast(cur, mle_entry, buffer);
00266             }
00267         }
00268     }
00269 }
00270 
00271 void thread_router_bootstrap_multicast_forwarder_enable(protocol_interface_info_entry_t *cur, buffer_t *buf)
00272 {
00273     //tr_debug("Considering forward %s (%s)", tr_ipv6(buf->dst_sa.address), (buf->info & B_DIR_MASK) == B_DIR_UP ? "up" : "down");
00274     if (addr_ipv6_multicast_scope(buf->dst_sa .address ) <= IPV6_SCOPE_INTERFACE_LOCAL) {
00275         return;
00276     }
00277 
00278     // Safe guard: do NOT forward received link-local
00279     // multicast packets to our sleepy children
00280     if ((buf->info  & B_DIR_MASK) == B_DIR_UP &&
00281         addr_ipv6_multicast_scope(buf->dst_sa .address ) <= IPV6_SCOPE_LINK_LOCAL) {
00282         tr_debug("Received link-local multicast; return...");
00283         return;
00284     }
00285 
00286     uint8_t addr[16];
00287     thread_bootstrap_all_nodes_address_generate(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_LINK_LOCAL);
00288     if (addr_ipv6_equal(buf->dst_sa .address , addr)) {
00289         thread_multicast_forward_to_child(cur, buf);
00290         return;
00291     }
00292     thread_bootstrap_all_nodes_address_generate(addr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, IPV6_SCOPE_REALM_LOCAL);
00293     if (addr_ipv6_equal(buf->dst_sa .address , addr)) {
00294         thread_multicast_forward_to_child(cur, buf);
00295         return;
00296     }
00297     thread_registered_mcast_forward_to_child(cur, buf);
00298 }
00299 
00300 static void thread_router_synch_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
00301 {
00302     thread_leader_data_t leaderData;
00303     uint8_t linkMarginfronNeigh;
00304     uint16_t version, shortAddress, address16;
00305     uint32_t llFrameCounter;
00306     mle_tlv_info_t routing;
00307     mle_neigh_table_entry_t *entry_temp;
00308     tr_debug("Thread MLE message router sync");
00309     //State machine What packet shuold accept in this case
00310     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00311     if (!cur) {
00312         return;
00313     }
00314 
00315     /* Check that message is from link-local scope */
00316     if(!addr_is_ipv6_link_local(mle_msg->packet_src_address)) {
00317         return;
00318     }
00319 
00320     if (!thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
00321         return;
00322     }
00323 
00324     //Validate ready TLV for router Synch
00325     if ((!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
00326             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_ADDRESS16, mle_msg->data_ptr, mle_msg->data_length, &address16)) ||
00327             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
00328             (!mle_tlv_read_tlv(MLE_TYPE_ROUTE, mle_msg->data_ptr, mle_msg->data_length, &routing)) ||
00329             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
00330         return ;
00331     }
00332 
00333     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
00334 
00335     switch (mle_msg->message_type) {
00336         case MLE_COMMAND_ACCEPT: {
00337             tr_info("Accept (ROUTER handler)");
00338             uint32_t mleFrameCounter;
00339             bool new_neigbour;
00340             uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
00341 
00342             if (messageId == 0) {
00343                 tr_debug("No matching challenge");
00344                 return;
00345             }
00346             /*Link accept command has an optional MLE Frame counter TLV, if this is not present use link layer frame counter TLV
00347              * as MLE frame counter TLV*/
00348             if(!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &mleFrameCounter)) {
00349                 mleFrameCounter = llFrameCounter;
00350             }
00351 
00352             if (!thread_is_router_addr(address16)){
00353                 return;
00354             }
00355             //Allocate neighbor entry
00356 
00357             entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, true, &new_neigbour);
00358             if (!entry_temp) {
00359                 return;
00360             }
00361 
00362             //Free Response
00363             mle_service_msg_free(messageId);
00364             entry_temp->threadNeighbor = true;
00365             entry_temp->short_adr = shortAddress;
00366             //when allocating neighbour entry, use MLE Frame counter if present to validate further advertisements from the neighbour
00367             entry_temp->mle_frame_counter = mleFrameCounter;
00368             if (entry_temp->timeout_rx) {
00369                 mle_entry_timeout_refresh(entry_temp);
00370             } else {
00371                 mle_tlv_info_t mle_tlv_info;
00372                 uint32_t timeout_tlv;
00373                 if (mle_tlv_option_discover(mle_msg->data_ptr, mle_msg->data_length, MLE_TYPE_TIMEOUT, &mle_tlv_info) > 0) {
00374                     timeout_tlv = common_read_32_bit(mle_tlv_info.dataPtr);
00375                     mle_entry_timeout_update(entry_temp, timeout_tlv);
00376                 } else {
00377                     mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
00378                 }
00379             }
00380 
00381             if (thread_is_router_addr(shortAddress)) {
00382                 entry_temp->handshakeReady = 1;
00383             }
00384 
00385             entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
00386 
00387             if (mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) {
00388                 thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
00389             }
00390 
00391             mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, 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, mle_neigh_table_entry_t *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->short_adr) || child->short_adr >= 0xfffe) {
00960         return -1;
00961     }
00962     tr_debug("Child free %x", child->short_adr);
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->short_adr);
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->short_adr)) {
00974         tr_debug("Remove references to Child's RLOC16 from the Network Data");
00975         thread_management_client_network_data_unregister(cur->id, child->short_adr);
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     mle_neigh_table_list_t *entry_list = mle_class_active_list_get(cur->id);
00995     if (!entry_list) {
00996         return;
00997     }
00998     ns_list_foreach_safe(mle_neigh_table_entry_t, table_entry, entry_list) {
00999         if (table_entry->short_adr < 0xfffe && !thread_is_router_addr(table_entry->short_adr)) {
01000             mle_class_remove_entry(cur->id, table_entry);
01001         }
01002     }
01003 }
01004 static void thread_router_bootstrap_invalid_child_information_clear(protocol_interface_info_entry_t *cur, uint16_t router_rloc)
01005 {
01006 
01007     tr_debug("Thread Short address changed old: %x new: %x", cur->thread_info->routerShortAddress, router_rloc);
01008 
01009     mle_neigh_table_list_t *entry_list = mle_class_active_list_get(cur->id);
01010     if (!entry_list) {
01011         return;
01012     }
01013 
01014     // scrub neighbours with child addresses that are not ours
01015     ns_list_foreach_safe(mle_neigh_table_entry_t, table_entry, entry_list) {
01016         if (table_entry->short_adr < 0xfffe &&
01017                 !thread_is_router_addr(table_entry->short_adr) &&
01018                 thread_router_addr_from_addr(table_entry->short_adr) != router_rloc) {
01019             mle_class_remove_entry(cur->id, table_entry);
01020         }
01021     }
01022 }
01023 
01024 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])
01025 {
01026     uint8_t ml16[16];
01027     protocol_interface_info_entry_t *cur;
01028     uint8_t parent_router_id = FAST_ROUTE_NO_ROUTE;
01029 
01030     cur = protocol_stack_interface_info_get_by_id(interface_id);
01031     tr_debug("RouterID CB");
01032     if (!cur) {
01033         return;
01034     }
01035     if (!cur->thread_info->routerIdReqCoapID) {
01036         return;
01037     }
01038     cur->thread_info->routerIdReqCoapID = 0;
01039 
01040     if (cur->thread_info->thread_device_mode != THREAD_DEVICE_MODE_ROUTER ||
01041         cur->thread_info->leader_private_data ) {
01042         // Test api can cause these states or some out of sync operation.
01043         tr_warn("Router address for non-REED");
01044         return;
01045     }
01046 
01047     if (status < 0) {
01048         thread_bootstrap_router_id_get_fail(cur);
01049         return;
01050     }
01051 
01052     uint8_t routeId = *router_mask_ptr++;
01053 
01054     if(cur->thread_info->thread_endnode_parent) {
01055         parent_router_id = cur->thread_info->thread_endnode_parent->router_id;
01056     }
01057 
01058     thread_router_bootstrap_invalid_child_information_clear(cur,router_rloc);
01059 
01060     // Release network data from old address
01061     cur->thread_info->localServerDataBase.release_old_address = true;
01062 
01063     //ADD New ML16
01064     // This should be used thread_bootstrap_update_ml16_address(cur, router_rloc);
01065     thread_clean_old_16_bit_address_based_addresses(cur);
01066     mac_helper_mac16_address_set(cur, router_rloc);
01067     cur->thread_info->routerShortAddress = router_rloc;
01068     memcpy(ml16, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01069     memcpy(&ml16[8], ADDR_SHORT_ADR_SUFFIC , 6);
01070     common_write_16_bit(router_rloc, &ml16[14]);
01071 
01072     cur->global_address_available = true;
01073     //Register UL16
01074     if_address_entry_t *def_address = addr_add(cur, ml16, 64, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0xffffffff, true);
01075     if (!def_address) {
01076         return;
01077     }
01078 
01079     //  /* XXX Is short_src_adr ever reset? Is it undefined if info not in msg? */
01080     tr_debug("Route seq %d Router mask: %s", routeId, trace_array(router_mask_ptr, 8));
01081     cur->thread_info->routing.router_id_sequence_valid = false;
01082     if (parent_router_id != FAST_ROUTE_NO_ROUTE) {
01083         thread_routing_force_next_hop(cur, routeId, router_mask_ptr, parent_router_id);
01084     } else {
01085         tr_warn("No parent information available, no initial route set.");
01086         thread_routing_update_id_set(cur, routeId, router_mask_ptr);
01087     }
01088     thread_bootstrap_attached_active_router(cur);
01089 
01090 }
01091 
01092 void thread_router_bootstrap_router_id_request(protocol_interface_info_entry_t *cur, uint8_t status)
01093 {
01094     int router_id_req_status;
01095     tr_debug("Router ID Request");
01096     if (cur->thread_info->routerIdReqCoapID) {
01097         tr_warn("Router ID already requested");
01098         return;
01099     }
01100 
01101     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);
01102     tr_debug("Coap address req, ID=%d", router_id_req_status);
01103     if (router_id_req_status > 0) {
01104         cur->thread_info->routerIdReqCoapID = (uint16_t)router_id_req_status;
01105     }
01106 }
01107 
01108 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,mle_neigh_table_entry_t *neigh_info)
01109 {
01110     uint16_t len = 12 + 4; //Leader data and short address
01111     uint8_t *ptr;
01112     bool fullList = false;
01113     uint64_t pending_timestamp;
01114     struct link_configuration *linkConfiguration;
01115     linkConfiguration = thread_joiner_application_get_config(cur->id);
01116     if (!linkConfiguration) {
01117         return -1;
01118     }
01119 
01120     if (neigh_info->mode & MLE_THREAD_REQ_FULL_DATA_SET) {
01121         fullList = true;
01122     }
01123 
01124     if (child_req->shortAddressReq) {
01125         //Short Address
01126         len += 4;
01127     }
01128 
01129     if (child_req->networkDataReq) {
01130         len += 2 + thread_network_data_tlv_size(cur, fullList);
01131     }
01132 
01133     if (child_req->routeReq) {
01134         len += thread_route_option_size(cur);
01135     }
01136     if (child_req->request_active_config || child_req->active_timestamp != linkConfiguration->timestamp) {
01137         len += thread_active_operational_dataset_size(cur);
01138     }
01139 
01140     //always put active timestamp
01141     len += 10;
01142     len += thread_pending_timestamp_tlv_size(cur);
01143     pending_timestamp = thread_joiner_application_pending_config_timestamp_get(cur->id);
01144     if (pending_timestamp && pending_timestamp != child_req->pending_timestamp) {
01145         len += thread_pending_operational_dataset_size(cur);
01146     }
01147 
01148     mle_message_timeout_params_t timeout;
01149     uint16_t bufId = mle_service_msg_allocate(cur->id, len , false, MLE_COMMAND_CHILD_ID_RESPONSE);
01150     if (bufId == 0) {
01151         return -1;
01152     }
01153     uint32_t keySequence;
01154     thread_management_get_current_keysequence(cur->id, &keySequence);
01155     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
01156 
01157     tr_debug("Send MLE Child ID response");
01158 
01159     ptr = mle_service_get_data_pointer(bufId);
01160 
01161     ptr = thread_leader_data_tlv_write(ptr, cur);
01162 
01163     ptr = mle_general_write_source_address(ptr, cur);
01164 
01165     if (child_req->shortAddressReq) {
01166         ptr = mle_tlv_write_short_address(ptr, neigh_info->short_adr);
01167     }
01168 
01169     if (child_req->routeReq) {
01170         ptr = thread_route_option_write(cur, ptr);
01171     }
01172 
01173     if (child_req->networkDataReq) {
01174         ptr = thread_network_data_tlv_write(cur, ptr, fullList);
01175     }
01176 
01177     if (child_req->active_timestamp != linkConfiguration->timestamp) {
01178         ptr = thread_active_operational_dataset_write(cur, ptr);
01179     }
01180 
01181     //always write active timestamp
01182     ptr = thread_active_timestamp_write(cur,ptr);
01183     if (pending_timestamp > 0 && pending_timestamp != child_req->pending_timestamp) {
01184         ptr = thread_pending_operational_dataset_write(cur, ptr);
01185     }
01186 
01187     ptr = thread_pending_timestamp_write(cur,ptr);
01188 
01189 
01190     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
01191         tr_debug("Buffer overflow at message write");
01192     }
01193     timeout.retrans_max = 0;
01194     timeout.timeout_init = 0;
01195     timeout.timeout_max = 0;
01196     timeout.delay = MLE_NO_DELAY;
01197     mle_service_set_msg_destination_address(bufId, dstAddress);
01198     mle_service_set_msg_timeout_parameters(bufId, &timeout);
01199     mle_service_send_message(bufId);
01200     return 0;
01201 
01202 
01203 }
01204 uint16_t thread_router_bootstrap_child_count_get(protocol_interface_info_entry_t *cur)
01205 {
01206     uint16_t child_count = 0;
01207     uint16_t router_address = thread_info(cur)->routerShortAddress;
01208     if (router_address >= 0xfffe) {
01209         router_address = mac_helper_mac16_address_get(cur);
01210     }
01211     if (router_address & THREAD_CHILD_MASK) {
01212         return 0; //I am child
01213     }
01214     if (router_address >= 0xfffe) {
01215         return 0;
01216     }
01217     mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
01218     if (!mle_table) {
01219         return -1;
01220     }
01221     ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
01222         if (thread_router_addr_from_addr(cur_entry->short_adr) == router_address) {
01223             child_count++;
01224         }
01225     }
01226     return child_count;
01227 }
01228 
01229 static uint16_t thread_router_bootstrap_child_address_generate(protocol_interface_info_entry_t *cur)
01230 {
01231     mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
01232     if (!mle_table) {
01233         return -1;
01234     }
01235 
01236     if (thread_router_bootstrap_child_count_get(cur) >= cur->thread_info->maxChildCount) {
01237         tr_info("Maximum count %d reached", cur->thread_info->maxChildCount);
01238         return 0xffff;
01239     }
01240 
01241     bool address_allocated = false;
01242     for (uint16_t i = 0; i < cur->thread_info->maxChildCount; i++) {
01243         address_allocated = false;
01244         cur->thread_info->lastAllocatedChildAddress = (cur->thread_info->lastAllocatedChildAddress % THREAD_MAX_CHILD_ID_COUNT) + 1;
01245         ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
01246             if ( (cur_entry->short_adr & THREAD_CHILD_MASK) == cur->thread_info->lastAllocatedChildAddress) {
01247                 address_allocated = true;
01248                 break;
01249             }
01250         }
01251         if (!address_allocated){
01252             break;
01253         }
01254     }
01255     if (address_allocated){
01256         // all possible addresses already allocated
01257         return 0xffff;
01258     }
01259     return ((mac_helper_mac16_address_get(cur) & THREAD_ROUTER_MASK) | cur->thread_info->lastAllocatedChildAddress);
01260 }
01261 
01262 static bool thread_child_id_request(protocol_interface_info_entry_t *cur, mle_neigh_table_entry_t *entry_temp)
01263 {
01264         //Remove All Short address links from router
01265         if (entry_temp->short_adr != 0xffff) {
01266             protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
01267         }
01268 
01269         //allocate child address if current is router, 0xffff or not our child
01270         if (!thread_addr_is_child(mac_helper_mac16_address_get(cur), entry_temp->short_adr)) {
01271             entry_temp->short_adr = thread_router_bootstrap_child_address_generate(cur);
01272         }
01273 
01274         if (entry_temp->short_adr == 0xffff) {
01275             return false;
01276         }
01277 
01278         // Store this child info to the NVM
01279         thread_dynamic_storage_child_info_store(cur->id, entry_temp);
01280     //}
01281     return true;
01282 }
01283 
01284 void thread_router_bootstrap_child_id_handler(protocol_interface_info_entry_t *cur)
01285 {
01286     thread_pending_child_id_req_t *req;
01287     bool new_neigbour = false;
01288 
01289     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED) {
01290         if (!cur->thread_info->routerIdReqCoapID) {
01291             tr_info("Upgrade REED to Router");
01292             thread_router_bootstrap_router_id_request(cur, THREAD_COAP_STATUS_TLV_HAVE_CHILD_ID_REQUEST);
01293         }
01294         return;
01295     }
01296     req = thread_child_id_request_entry_get_from_the_list(cur);
01297 
01298     if (!req) {
01299         tr_debug("Child Id Req pending list empty");
01300         return;
01301     }
01302 
01303     if (cur->thread_info->thread_attached_state != THREAD_STATE_CONNECTED_ROUTER) {
01304         // We are not router can not process
01305         goto free_request;
01306     }
01307 
01308     uint8_t ll64[16];
01309     //set LL64 destination address
01310     memcpy(ll64, ADDR_LINK_LOCAL_PREFIX , 8);
01311     memcpy(&ll64[8], req->euid64 , 8);
01312     ll64[8] ^= 2;
01313     //Allocate entry
01314     mle_neigh_table_entry_t *entry_temp = mle_class_get_entry_by_ll64(cur->id, req->linkMargin, ll64, true, &new_neigbour);
01315 
01316     if (!entry_temp) {
01317         //Send link reject
01318         thread_link_reject_send(cur, ll64);
01319         goto free_request;
01320     }
01321 
01322     // If mac frame couter is less than previous we need to leave the old one
01323 
01324     //Update or set neigh info
01325     entry_temp->holdTime = 90;
01326 
01327     mle_entry_timeout_update(entry_temp, req->timeout);
01328     entry_temp->mode = req->mode;
01329     entry_temp->threadNeighbor = true;
01330     entry_temp->handshakeReady = 1;
01331     entry_temp->mle_frame_counter = req->mleFrameCounter;
01332 
01333     if (req->shortAddressReq) {
01334         if (!thread_child_id_request(cur, entry_temp)) {
01335             mle_class_remove_entry(cur->id, entry_temp);
01336             thread_link_reject_send(cur, ll64);
01337             goto free_request;
01338         }
01339     }
01340     if (new_neigbour) {
01341         mac_helper_devicetable_set(entry_temp, cur, req->frameCounter, req->keyId, new_neigbour);
01342     } else {
01343         // in get response handler this will update the short address from MLE table
01344         mlme_get_t get_req;
01345         get_req.attr = macDeviceTable;
01346         get_req.attr_index = entry_temp->attribute_index;
01347         cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
01348     }
01349 
01350     //Register MLEID if RRFD device
01351     if ((entry_temp->mode & MLE_DEV_MASK) == MLE_RFD_DEV) {
01352         uint8_t tempIPv6Address[16];
01353         memcpy(tempIPv6Address, thread_info(cur)->threadPrivatePrefixInfo.ulaPrefix, 8);
01354         memcpy(&tempIPv6Address[8], req->eiid, 8);
01355         memcpy(&entry_temp->mlEid, req->eiid, 8);
01356 
01357         tr_debug("Register %s", trace_ipv6(tempIPv6Address));
01358         //Register GP --> 16
01359         thread_nd_address_registration(cur, tempIPv6Address, entry_temp->short_adr, cur->mac_parameters->pan_id, entry_temp->mac64);
01360     }
01361 
01362     mle_attach_child_id_response_build(cur,ll64,req, entry_temp);
01363 
01364     free_request:
01365     ns_dyn_mem_free(req);
01366     thread_bootstrap_child_id_request(cur);
01367 }
01368 
01369 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)
01370 {
01371     lowpan_context_t *ctx;
01372     uint8_t tempIPv6Address[16];
01373     uint8_t ctxId;
01374 
01375     while (data_length) {
01376         //Read
01377         ctxId = *ptr++;
01378         if (ctxId & 0x80) {
01379             ctxId &= 0x0f;
01380             ctx = lowpan_contex_get_by_id(&cur->lowpan_contexts, ctxId);
01381             if (ctx) {
01382                 memcpy(tempIPv6Address, ctx->prefix, 8);
01383                 memcpy(&tempIPv6Address[8], ptr, 8);
01384                 tr_debug("Register %s", trace_ipv6(tempIPv6Address));
01385                 //Register GP --> 16
01386                 thread_nd_address_registration(cur, tempIPv6Address, mac16, cur->mac_parameters->pan_id, mac64);
01387                 thread_extension_address_registration(cur, tempIPv6Address, mac64);
01388             } else {
01389                 tr_debug("No Context %u", ctxId);
01390             }
01391             ptr += 8;
01392             data_length -= 9;
01393         } else {
01394             tr_debug("Register %s", trace_ipv6(ptr));
01395 
01396             if (addr_is_ipv6_multicast(ptr)) {
01397                 // Register multicast address (higher scope than link-local)
01398                 if (addr_ipv6_multicast_scope(ptr) > IPV6_SCOPE_LINK_LOCAL) {
01399                     addr_add_group(cur, ptr);
01400                     if (thread_child_mcast_entry_get(cur, ptr, mac64)) {
01401                         tr_debug("Added sleepy multicast registration entry.");
01402                     }
01403                 }
01404             } else {
01405                 //Register GP --> 16
01406                 thread_nd_address_registration(cur, ptr, mac16, cur->mac_parameters->pan_id, mac64);
01407                 thread_extension_address_registration(cur, ptr, mac64);
01408             }
01409 
01410             ptr += 16;
01411             data_length -= 17;
01412         }
01413     }
01414 }
01415 
01416 void thread_router_bootstrap_mle_receive_cb(int8_t interface_id, mle_message_t *mle_msg, mle_security_header_t *security_headers)
01417 {
01418     thread_leader_data_t leaderData;
01419     mle_neigh_table_entry_t *entry_temp;
01420     bool rssiTLV;
01421     bool leaderDataReceived;
01422     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01423     if (!cur) {
01424         return;
01425     }
01426 
01427     //TLV REQUSTED
01428     if (mle_tlv_type_requested(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length)) {
01429         rssiTLV = true;
01430     } else {
01431         rssiTLV = false;
01432     }
01433 
01434     if (thread_leader_data_parse(mle_msg->data_ptr, mle_msg->data_length, &leaderData)) {
01435         leaderDataReceived = true;
01436     } else {
01437         leaderDataReceived = false;
01438     }
01439 
01440 
01441     uint8_t linkMargin = thread_compute_link_margin(mle_msg->dbm);
01442     tr_debug("Thread MLE REED Handler");
01443     switch (mle_msg->message_type) {
01444             case MLE_COMMAND_PARENT_REQUEST: {
01445                 uint8_t scanMask, mode;
01446                 uint16_t version;
01447                 mle_tlv_info_t challengeTlv;
01448                 tr_info("Recv MLE Parent Request");
01449 
01450                 if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
01451                     // If own attach is ongoing, do not process parent request
01452                     return;
01453                 }
01454 
01455                 if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) {
01456                     tr_debug("Wrong key mode %u ", security_headers->KeyIdMode);
01457                     return;
01458                 }
01459 
01460                 if (!thread_router_bootstrap_routing_allowed(cur)) {
01461                     tr_debug("R bit is off in security policy; drop packet");
01462                     return;
01463                 }
01464 
01465                 if (thread_am_reed(cur)) {
01466                     // If we are in REED mode and receive PARENT_REQ from our parent, don't send response.
01467                     if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
01468                         tr_debug("Drop PARENT_REQ from own parent");
01469                         return;
01470                     }
01471                 }
01472 
01473                 // parent request received
01474                 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
01475                 if (entry_temp) {
01476                     entry_temp->mode = (MLE_FFD_DEV | MLE_RX_ON_IDLE | MLE_THREAD_REQ_FULL_DATA_SET);
01477                 }
01478                 if(!entry_temp) {
01479                     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01480                         tr_debug("NO Mode");
01481                         return;
01482                     }
01483 
01484                     // New child trying to attach check if we have room
01485                     if (mle_service_interface_tx_queue_size(cur->id) > THREAD_MAX_PARALLEL_MLE_PARENT_REQUEST) {
01486                         tr_info("Drop MLE message: too many simultaneous MLE messages");
01487                         return;
01488                     }
01489 
01490                     if (mle_class_free_entry_count_get(cur->id) < 1) {
01491                         tr_info("Drop MLE message: no space left in the MLE table");
01492                         return;
01493                     }
01494 
01495                     if ((mode & MLE_DEV_MASK) == MLE_RFD_DEV && mle_class_rfd_entry_count_get(cur->id) >= THREAD_MAX_MTD_CHILDREN) {
01496                         tr_info("Drop MLE message: maximum MTD child count reached.");
01497                         return;
01498                     }
01499 
01500                     if (!(mode & MLE_RX_ON_IDLE) && mle_class_sleepy_entry_count_get(cur->id) >= THREAD_MAX_SED_CHILDREN) {
01501                         tr_info("Drop MLE message: maximum SED child count reached.");
01502                         return;
01503                     }
01504 
01505                     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER &&
01506                             thread_router_bootstrap_child_count_get(cur) >= cur->thread_info->maxChildCount) {
01507                         tr_info("Drop MLE message: maximum Child count reached (%d)", cur->thread_info->maxChildCount);
01508                         return;
01509                     }
01510                 }
01511 
01512                 if (thread_route_ready_to_leader(cur) != 0) {
01513                     tr_debug("Leader Path infinite");
01514                     return;
01515                 }
01516 
01517                 /**
01518                      * MLE attached First packet Mandatory TLV:s are validated at this function
01519                      * - MLE_TYPE_SCAN_MASK
01520                      * - MLE_TYPE_CHALLENGE
01521                      * - MLE_TYPE_VERSION
01522                      */
01523                 //Validate Mask
01524                 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_SCAN_MASK, mle_msg->data_ptr, mle_msg->data_length, &scanMask)) {
01525                     tr_debug("NO Scan mask");
01526                     return;
01527                 }
01528 
01529                 if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01530                     tr_debug("NO Mode");
01531                     return;
01532                 }
01533 
01534                 if (!thread_scan_mask_validation(cur, scanMask)) {
01535                     tr_debug("Not my type");
01536                     return;
01537                 }
01538 
01539                 if(cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED &&
01540                    31 < thread_routing_count_active_routers(&cur->thread_info->routing)) {
01541                     tr_info("No possibility to upgrade to router");
01542                     return;
01543                 }
01544 
01545                 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) {
01546                     tr_debug("NO version");
01547                     return;
01548                 }
01549 
01550                 //Read Challenge for Build Response
01551                 if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) {
01552                     tr_debug("No challenge");
01553                     return;
01554                 }
01555 
01556                 if (thread_attach_parent_response_build(cur, mle_msg->packet_src_address, challengeTlv.dataPtr, challengeTlv.tlvLen, linkMargin, scanMask, mode) == 0) {
01557                     tr_debug("Send MLE Parent response");
01558                 }
01559                 break;
01560             }
01561 
01562             case MLE_COMMAND_CHILD_ID_REQUEST:
01563                 tr_info("Recv MLE Child ID Request from %s", trace_ipv6(mle_msg->packet_src_address));
01564                 if (cur->nwk_bootstrap_state != ER_BOOTSRAP_DONE && cur->nwk_bootstrap_state != ER_MLE_ATTACH_READY) {
01565                     // If own attach is ongoing, do not process child ID req
01566                     return;
01567                 }
01568 
01569                 if (!thread_router_bootstrap_routing_allowed(cur)) {
01570                     tr_debug("R bit is off in security policy; drop packet");
01571                     return;
01572                 }
01573 
01574                 // If we are in REED mode and receive child IR request from our parent, call connection error.
01575                 if (thread_am_reed(cur)) {
01576                     if (thread_router_parent_address_check(cur, mle_msg->packet_src_address)) {
01577                         tr_debug("Child ID req from own parent -> connection error");
01578                         thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
01579                         return;
01580                     }
01581                 }
01582 
01583                 if (security_headers->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX) {
01584                     tr_debug("Wrong key mode %u ", security_headers->KeyIdMode);
01585                     return;
01586                 } else {
01587                     thread_pending_child_id_req_t *id_req;
01588                     uint8_t tlvType;
01589                     mle_tlv_info_t tlvRequest, addressRegisteredTlv;
01590                     uint8_t *t_ptr;
01591 
01592                     uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
01593 
01594                     if (messageId == 0) {
01595                         tr_debug("No matching challenge");
01596                         return;
01597                     }
01598 
01599                     /* Perform key synchronization */
01600                     thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
01601 
01602                     //Free Response
01603                     mle_service_msg_free(messageId);
01604 
01605                     mle_msg->packet_src_address[8]  ^= 2;
01606                     id_req = thread_child_id_request_entry_get(cur, (mle_msg->packet_src_address + 8));
01607                     mle_msg->packet_src_address[8]  ^= 2;
01608 
01609                     if (!id_req) {
01610                         tr_debug("No room for child id req");
01611                         return;
01612                     }
01613 
01614                     /**
01615                          * MLE attached Tree packet Mandatory TLV:s are validated at this function
01616                          * - MLE_TYPE_TIMEOUT
01617                          * - MLE_TYPE_MODE
01618                          * - MLE_TYPE_LL_FRAME_COUNTER
01619                          * - MLE_TYPE_TLV_REQUEST
01620                          * - MLE_TYPE_VERSION
01621                          * Optional:
01622                          * - MLE_TYPE_ADDRESS_REGISTRATION
01623                          * - MLE_TYPE_MLE_FRAME_COUNTER
01624                          */
01625 
01626                     if ((!mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &id_req->timeout)) ||
01627                             (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &id_req->mode)) ||
01628                             (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &id_req->version)) ||
01629                             (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &id_req->frameCounter)) ||
01630                             (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlvRequest))) {
01631                         thread_child_id_request_entry_remove(cur, id_req);
01632                         tr_debug("Illegal child id req");
01633                         return;
01634                     }
01635                     //If MLE MLE_TYPE_MLE_FRAME_COUNTER TLV is present then use it for validating further messages else use link layer frame counter
01636                     if (!mle_tlv_read_32_bit_tlv(MLE_TYPE_MLE_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &id_req->mleFrameCounter)) {
01637                         id_req->mleFrameCounter = id_req->frameCounter;
01638                     }
01639 
01640                     t_ptr = tlvRequest.dataPtr;
01641 
01642                     for (uint8_t i = 0; i < tlvRequest.tlvLen; i++) {
01643                         tlvType = *t_ptr++;
01644                         if (tlvType == MLE_TYPE_ADDRESS16) {
01645                             id_req->shortAddressReq = true;
01646                         } else if (tlvType == MLE_TYPE_NETWORK_DATA) {
01647                             id_req->networkDataReq = true;
01648                         } else if (tlvType == MLE_TYPE_ROUTE) {
01649                             id_req->routeReq = true;
01650                         }
01651                     }
01652                     if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
01653                         uint8_t context;
01654                         t_ptr = addressRegisteredTlv.dataPtr;
01655                         context = *t_ptr++;
01656                         if (context & 0x80) {
01657                             context &= 0x0f;
01658                             if (addressRegisteredTlv.tlvLen == 9 && (context == 0)) {
01659                                 memcpy(id_req->eiid, t_ptr, 8);
01660                             }
01661                         } else {
01662                             t_ptr += 8;
01663                             memcpy(id_req->eiid, t_ptr, 8);
01664                         }
01665                     }
01666 
01667 
01668                     id_req->keyId = security_headers->KeyIndex;
01669                     id_req->keySeq = common_read_32_bit(security_headers->Keysource);
01670                     id_req->linkMargin = linkMargin;
01671 
01672                     id_req->active_timestamp = 0;
01673                     id_req->request_active_config = false;
01674                     if (!mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &id_req->active_timestamp)) {
01675                         id_req->request_active_config = true;
01676                     }
01677                     if (!mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &id_req->pending_timestamp)) {
01678                         id_req->pending_timestamp = 0;
01679                     }
01680 
01681                     //Push Event to queue
01682                     if (thread_bootstrap_child_id_request(cur) != 0) {
01683                         thread_child_id_request_entry_remove(cur, id_req);
01684                     }
01685 
01686                     break;
01687                 }
01688 
01689             case MLE_COMMAND_REQUEST:{
01690                 uint16_t shortAddress, version;
01691                 mle_tlv_info_t addressRegisteredTlv, requestTlv, challengeTlv;
01692                 uint8_t response_type = MLE_COMMAND_ACCEPT_AND_REQUEST;
01693                 //Router attachment
01694                 tr_info("Recv Router Link request");
01695 
01696                 if (!thread_attach_active_router(cur)) {
01697                     return; //Do respond until we are reed
01698                 }
01699 
01700                 if (!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) {
01701                     return;
01702                 }
01703                 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) {
01704                     return;
01705                 }
01706                 if (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
01707                     /**
01708                      * This cuold cause problem if any dummy coder add this to message
01709                      * Validate is it REED or End device message link synch Request
01710                      * - MLE_TYPE_SRC_ADDRESS
01711                      * - MLE_TYPE_VERSION
01712                      * - MLE_TYPE_CHALLENGE
01713                      */
01714                     if (mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
01715                         //Correct TLV's lets response
01716                         if (!thread_is_router_addr(shortAddress)) {
01717                             if (leaderDataReceived && thread_info(cur)->thread_leader_data->partitionId == leaderData.partitionId) {
01718                                 //REED or end device send response
01719                                 thread_router_accept_to_endevice(cur, mle_msg, challengeTlv.dataPtr, challengeTlv.tlvLen);
01720                             } else {
01721                                 tr_debug("Drop Link Request from REED/ED in a different partition.");
01722                                 // Do nothing... ignore.
01723                             }
01724                         }
01725                     }
01726                     return;
01727                 }
01728 
01729                 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
01730 
01731                 if (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress)) {
01732 
01733                     /**
01734                      * MLE Router Synch mandatory options are
01735                      * - MLE_TYPE_VERSION
01736                      * - MLE_TYPE_CHALLENGE
01737                      * - MLE_TYPE_TLV_REQUEST
01738                      *
01739                      */
01740 
01741                     if (entry_temp && entry_temp->handshakeReady) {
01742                         mle_entry_timeout_refresh(entry_temp);
01743                         thread_router_synch_accept_request_build(cur, mle_msg, entry_temp->short_adr, challengeTlv.dataPtr, challengeTlv.tlvLen, requestTlv.dataPtr, requestTlv.tlvLen);
01744                     }
01745                 }
01746                 bool update_mac_mib = false;
01747                 /**
01748                  * MLE attached First packet Mandatory TLV:s are validated at this function
01749                  * - MLE_TYPE_SRC_ADDRESS
01750                  * - MLE_TYPE_CHALLENGE
01751                  * - MLE_TYPE_LEADER_DATA
01752                  * - MLE_TYPE_VERSION
01753                  * - MLE_TYPE_TLV_REQUEST
01754                  */
01755 
01756                 //Read Leader Data and verify connectivity
01757                 if (!leaderDataReceived) {
01758                     return;
01759                 }
01760 
01761                 //validate partition id
01762                 if (thread_info(cur)->thread_leader_data->partitionId != leaderData.partitionId) {
01763                     tr_debug("Drop link request from wrong partition");
01764                     return;
01765                 }
01766 
01767                 if (entry_temp) {
01768                     /*remove from child list when becoming router*/
01769                     // Was this previously our child? If yes, update.
01770                     if ((entry_temp->short_adr & THREAD_CHILD_MASK) && thread_router_addr_from_addr(entry_temp->short_adr) == cur->thread_info->routerShortAddress) {
01771                         thread_dynamic_storage_child_info_clear(cur->id, entry_temp);
01772                         protocol_6lowpan_release_short_link_address_from_neighcache(cur, entry_temp->short_adr);
01773                     }
01774                     update_mac_mib = true;
01775                     entry_temp->short_adr = shortAddress; // short address refreshed
01776 
01777                     if (entry_temp->handshakeReady) {
01778                         if (mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisteredTlv)) {
01779                             if (thread_rfd_device(entry_temp->mode)) {
01780                                 thread_address_registration_tlv_parse(addressRegisteredTlv.dataPtr, addressRegisteredTlv.tlvLen, cur, entry_temp->short_adr, entry_temp->mac64);
01781                             }
01782                         }
01783 
01784                         mle_entry_timeout_refresh(entry_temp);
01785                         if (!mle_neigh_entry_frame_counter_update(entry_temp, mle_msg->data_ptr, mle_msg->data_length, cur, security_headers->KeyIndex) &&  update_mac_mib) {
01786                             //GET
01787                             mlme_get_t get_req;
01788                             get_req.attr = macDeviceTable;
01789                             get_req.attr_index = entry_temp->attribute_index;
01790                             cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
01791                         }
01792                         response_type = MLE_COMMAND_ACCEPT;
01793                     }
01794                     response_type = MLE_COMMAND_ACCEPT;
01795                 }
01796 
01797 
01798                 bool accept_link = false;
01799                 if (entry_temp) {
01800                     // We know already so we can accept
01801                     accept_link = true;
01802                 } else if (addr_is_ipv6_multicast(mle_msg->packet_dst_address)) {
01803                     if (thread_bootstrap_link_create_check(cur, shortAddress) &&
01804                         thread_bootstrap_link_create_allowed(cur, shortAddress, mle_msg->packet_src_address)) {
01805                         // Multicast and we can respond to message
01806                         accept_link = true;
01807                     }
01808                 } else if ( thread_bootstrap_link_create_check(cur, shortAddress) ) {
01809                     // Unicast request and we should make link
01810                     accept_link = true;
01811                 }
01812 
01813                 if (accept_link) {
01814                     if (!thread_is_router_addr(shortAddress)) {
01815                         response_type = MLE_COMMAND_ACCEPT;
01816                     }
01817                     thread_router_accept_request_build(cur, mle_msg, shortAddress, challengeTlv.dataPtr, challengeTlv.tlvLen, response_type, rssiTLV, linkMargin);
01818                 }
01819 
01820                 break;
01821             }
01822 
01823             case MLE_COMMAND_ACCEPT_AND_REQUEST: {
01824                 uint8_t linkMarginfronNeigh;
01825                 uint16_t version, shortAddress;
01826                 uint32_t llFrameCounter;
01827                 mle_tlv_info_t requestTlv, challengeTlv;
01828                 bool createNew, new_entry;
01829                 tr_info("Recv Router Accept & Request");
01830                 uint16_t messageId = mle_tlv_validate_response(mle_msg->data_ptr, mle_msg->data_length);
01831 
01832                 if (messageId == 0) {
01833                     tr_debug("No matching challenge");
01834                     return;
01835                 }
01836 
01837                 if (!addr_is_ipv6_multicast(mle_service_get_msg_destination_address_pointer(messageId))) {
01838                     //Free Response only if it is unicast
01839                     mle_service_msg_free(messageId);
01840                 }
01841 
01842                 if ((!mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv)) ||
01843                         (!mle_tlv_read_16_bit_tlv(MLE_TYPE_VERSION, mle_msg->data_ptr, mle_msg->data_length, &version)) ||
01844                         (!mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) ||
01845                         (!mle_tlv_read_8_bit_tlv(MLE_TYPE_RSSI, mle_msg->data_ptr, mle_msg->data_length, &linkMarginfronNeigh)) ||
01846                         (!mle_tlv_read_32_bit_tlv(MLE_TYPE_LL_FRAME_COUNTER, mle_msg->data_ptr, mle_msg->data_length, &llFrameCounter)) ||
01847                         (!mle_tlv_read_16_bit_tlv(MLE_TYPE_SRC_ADDRESS, mle_msg->data_ptr, mle_msg->data_length, &shortAddress))) {
01848                     thread_link_reject_send(cur, mle_msg->packet_src_address);
01849                     return;
01850                 }
01851 
01852                 /* Call to determine whether or not we should create a new link */
01853                 createNew = thread_bootstrap_link_create_check(cur, shortAddress);
01854 
01855                 //Send Response
01856                 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, createNew, &new_entry);
01857                 if (entry_temp) {
01858 
01859                     if (security_headers->KeyIdMode == MAC_KEY_ID_MODE_SRC4_IDX) {
01860                         thread_management_key_synch_req(cur->id, common_read_32_bit(security_headers->Keysource));
01861                     }
01862 
01863                     entry_temp->threadNeighbor = true;
01864                     entry_temp->short_adr = shortAddress;
01865                     mac_helper_devicetable_set(entry_temp, cur, llFrameCounter, security_headers->KeyIndex, new_entry);
01866                     if (entry_temp->timeout_rx) {
01867                         mle_entry_timeout_refresh(entry_temp);
01868                     } else {
01869                         mle_entry_timeout_update(entry_temp, THREAD_DEFAULT_LINK_LIFETIME);
01870                     }
01871 
01872                     if (thread_is_router_addr(shortAddress)) {
01873                         entry_temp->handshakeReady = 1;
01874                     }
01875 
01876                     entry_temp->mode |= MLE_THREAD_REQ_FULL_DATA_SET;
01877 
01878                     thread_routing_update_link_margin(cur, entry_temp->short_adr, linkMargin, linkMarginfronNeigh);
01879                     //Read Source address and Challenge
01880                     mac_data_poll_protocol_poll_mode_decrement(cur);
01881                     thread_router_accept_request_build(cur, mle_msg, entry_temp->short_adr, challengeTlv.dataPtr, challengeTlv.tlvLen, MLE_COMMAND_ACCEPT, rssiTLV, linkMargin);
01882 
01883                     blacklist_update(mle_msg->packet_src_address, true);
01884                 } else {
01885                     thread_link_reject_send(cur, mle_msg->packet_src_address);
01886                 }
01887 
01888                 break;
01889             }
01890 
01891             case MLE_COMMAND_CHILD_UPDATE_REQUEST:
01892                 tr_info("Recv Router Child Update request");
01893                 {
01894                     uint8_t mode;
01895                     uint8_t status;
01896                     uint32_t timeout = 0;
01897                     uint64_t active_timestamp = 0;
01898                     uint64_t pending_timestamp = 0;
01899                     mle_tlv_info_t addressRegisterTlv = {0};
01900                     mle_tlv_info_t challengeTlv = {0};
01901                     mle_tlv_info_t tlv_req = {0};
01902                     entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
01903 
01904                     if (mle_tlv_read_8_bit_tlv(MLE_TYPE_STATUS, mle_msg->data_ptr, mle_msg->data_length, &status)) {
01905                         if (1 == status && thread_check_is_this_my_parent(cur, entry_temp)) {
01906                             tr_debug("parent has removed REED");
01907                             thread_bootstrap_connection_error(cur->id, CON_PARENT_CONNECT_DOWN, NULL);
01908                         }
01909                         return;
01910                     }
01911 
01912                     mle_tlv_read_tlv(MLE_TYPE_CHALLENGE, mle_msg->data_ptr, mle_msg->data_length, &challengeTlv);
01913 
01914                     if (!entry_temp) {
01915                         tr_debug("Not Neighbor anymore");
01916                         thread_host_bootstrap_child_update_negative_response(cur, mle_msg->packet_src_address, &challengeTlv);
01917                         return;
01918                     }
01919 
01920                     if (!mle_tlv_read_8_bit_tlv(MLE_TYPE_MODE, mle_msg->data_ptr, mle_msg->data_length, &mode)) {
01921                         tr_debug("No Mode");
01922                         return;
01923                     }
01924 
01925                     //Keep alive updated
01926                     entry_temp->ttl = entry_temp->timeout_rx;
01927                     entry_temp->last_contact_time = protocol_core_monotonic_time;
01928                     entry_temp->mode = mode;
01929 
01930                     addressRegisterTlv.tlvType = MLE_TYPE_UNASSIGNED;
01931                     mle_tlv_read_tlv(MLE_TYPE_ADDRESS_REGISTRATION, mle_msg->data_ptr, mle_msg->data_length, &addressRegisterTlv);
01932                     mle_tlv_read_64_bit_tlv(MLE_TYPE_ACTIVE_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &active_timestamp);
01933                     mle_tlv_read_64_bit_tlv(MLE_TYPE_PENDING_TIMESTAMP, mle_msg->data_ptr, mle_msg->data_length, &pending_timestamp);
01934 
01935                     mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &tlv_req);
01936 
01937                     if (addressRegisterTlv.tlvType == MLE_TYPE_ADDRESS_REGISTRATION &&
01938                         thread_rfd_device(entry_temp->mode)) {
01939 
01940                         tr_debug("Register child address");
01941                         thread_address_registration_tlv_parse(addressRegisterTlv.dataPtr, addressRegisterTlv.tlvLen, cur, entry_temp->short_adr, entry_temp->mac64);
01942                     }
01943 
01944                     if (mle_tlv_read_32_bit_tlv(MLE_TYPE_TIMEOUT, mle_msg->data_ptr, mle_msg->data_length, &timeout)) {
01945 
01946                         tr_debug("Setting child timeout, value=%"PRIu32, timeout);
01947                         entry_temp->holdTime = 90;
01948                         mle_entry_timeout_update(entry_temp, timeout);
01949                     }
01950                     if (!leaderDataReceived) {
01951                         tr_debug("Child synch req");
01952                     }
01953 
01954                     tr_debug("Keep-Alive -->Respond Child");
01955                     //Response
01956                     thread_child_update_response(cur, mle_msg->packet_src_address, mode, entry_temp->short_adr, timeout, &addressRegisterTlv, &tlv_req, &challengeTlv, active_timestamp, pending_timestamp);
01957 
01958                 }
01959                 break;
01960 
01961             case MLE_COMMAND_UPDATE:
01962                 tr_info("Recv Router Update");
01963                 break;
01964 
01965             case MLE_COMMAND_UPDATE_REQUEST:
01966                 tr_info("Recv Router update Request");
01967                 break;
01968 
01969             case MLE_COMMAND_DATA_REQUEST: {
01970                 mle_tlv_info_t requestTlv;
01971                 tr_info("Recv Router Data Request");
01972                 entry_temp = mle_class_get_entry_by_ll64(cur->id, linkMargin, mle_msg->packet_src_address, false, NULL);
01973                 if (!entry_temp || !mle_tlv_read_tlv(MLE_TYPE_TLV_REQUEST, mle_msg->data_ptr, mle_msg->data_length, &requestTlv)) {
01974                     return;
01975                 }
01976                 mle_build_and_send_data_response_msg(cur, mle_msg->packet_src_address, mle_msg->data_ptr, mle_msg->data_length, &requestTlv, entry_temp->mode);
01977             }
01978             break;
01979             default:
01980                 tr_warn("Recv Router UNKNOWN message %d", mle_msg->message_type);
01981                 break;
01982 
01983         }
01984 }
01985 
01986 static int8_t thread_router_bootstrap_synch_request_send(protocol_interface_info_entry_t *cur)
01987 {
01988     uint8_t req_tlv[3];
01989     mle_message_timeout_params_t timeout;
01990     uint32_t keySequence;
01991     uint16_t buf_id = mle_service_msg_allocate(cur->id, 32, true, MLE_COMMAND_REQUEST);
01992     if (buf_id == 0) {
01993         return -1;
01994     }
01995     thread_management_get_current_keysequence(cur->id, &keySequence);
01996     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
01997     mle_service_set_msg_destination_address(buf_id, ADDR_LINK_LOCAL_ALL_ROUTERS);
01998     req_tlv[0] = MLE_TYPE_ADDRESS16;
01999     req_tlv[1] = MLE_TYPE_ROUTE;
02000     uint8_t *ptr = mle_service_get_data_pointer(buf_id);
02001     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
02002     ptr = mle_tlv_req_tlv(ptr, req_tlv, 2);
02003     if (mle_service_update_length_by_ptr(buf_id,ptr)!= 0) {
02004         tr_debug("Buffer overflow at message write");
02005     }
02006 
02007     timeout.retrans_max = THREAD_REQUEST_MAX_RETRY_CNT;
02008     timeout.timeout_init = 1;
02009     timeout.timeout_max = 3;
02010     timeout.delay = MLE_NO_DELAY;
02011 
02012     mle_service_set_packet_callback(buf_id, thread_device_synch_timeout);
02013     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
02014     mle_service_send_message(buf_id);
02015     return 0;
02016 }
02017 
02018 static int8_t thread_router_synch_new_router(protocol_interface_info_entry_t *cur, const uint8_t *destAddress)
02019 {
02020     mle_message_timeout_params_t timeout;
02021     uint32_t keySequence;
02022     if (thread_info(cur)) {
02023         if (!thread_info(cur)->thread_leader_data) {
02024             return -1;
02025         }
02026     }
02027 
02028     uint16_t bufId = mle_service_msg_allocate(cur->id, 64, true, MLE_COMMAND_REQUEST);
02029 
02030     if (bufId == 0) {
02031         return -1;
02032     }
02033     uint8_t req_tlv = MLE_TYPE_RSSI;
02034 
02035     thread_management_get_current_keysequence(cur->id, &keySequence);
02036     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
02037 
02038     mle_service_set_msg_destination_address(bufId, destAddress);
02039 
02040 
02041     uint8_t *ptr = mle_service_get_data_pointer(bufId);
02042     ptr = mle_tlv_write_version(ptr, cur->thread_info->version);
02043     ptr = thread_leader_data_tlv_write(ptr, cur);
02044     ptr = mle_general_write_source_address(ptr, cur);
02045     ptr = mle_tlv_req_tlv(ptr, &req_tlv, 1);
02046 
02047     if (!addr_is_ipv6_multicast(destAddress)) {
02048         timeout.retrans_max = 2;
02049         timeout.timeout_init = 2;
02050         timeout.timeout_max = 3;
02051         timeout.delay = MLE_STANDARD_RESPONSE_DELAY;
02052     } else {
02053         // Multicasts need transaction timer
02054         timeout.retrans_max = 1;
02055         timeout.timeout_init = 2;
02056         timeout.timeout_max = 3;
02057         timeout.delay = 0;
02058     }
02059     mle_service_set_packet_callback(bufId, thread_link_request_timeout);
02060     mle_service_set_msg_timeout_parameters(bufId, &timeout);
02061 
02062     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
02063         tr_debug("Buffer overflow at message write");
02064     }
02065 
02066 
02067     mle_service_send_message(bufId);
02068     return 0;
02069 }
02070 
02071 int thread_router_bootstrap_link_synch_start(protocol_interface_info_entry_t *cur)
02072 {
02073     //Send Link Request for
02074     if (thread_router_bootstrap_synch_request_send(cur) == 0) {
02075         //SET Router synch receiver handler
02076         mle_service_interface_receiver_handler_update(cur->id, thread_router_synch_receive_cb);
02077         cur->nwk_bootstrap_state = ER_MLE_SYNCH;
02078         return 0;
02079     }
02080     return -1;
02081 }
02082 
02083 bool thread_router_bootstrap_router_downgrade(protocol_interface_info_entry_t *cur)
02084 {
02085     uint8_t activeRouterCount;
02086     uint8_t goodLinks;
02087 
02088     if (cur->thread_info->thread_attached_state != THREAD_STATE_CONNECTED_ROUTER) {
02089         return false;
02090     }
02091 
02092     // if we are commissioner border router we have registered our address and cant upgrade or downgrade
02093     if (cur->thread_info->registered_commissioner.commissioner_valid &&
02094             addr_get_entry(cur,cur->thread_info->registered_commissioner.border_router_address) ) {
02095         return false;
02096     }
02097 
02098     // spec: Not be the Leader
02099     if (cur->thread_info->leader_private_data) {
02100         if (!thread_router_bootstrap_routing_allowed(cur)) {
02101             tr_debug("Cannot be leader anymore");
02102             // Settings have changed, cannot be leader anymore
02103             thread_bootstrap_reset_restart(cur->id);
02104         }
02105         // Leader can not downgrade
02106         return false;
02107     }
02108 
02109     if (!thread_router_bootstrap_routing_allowed(cur)) {
02110         return true;
02111     }
02112 
02113     //spec: If the number of active Routers on the network exceeds ROUTER_DOWNGRADE_THRESHOLD
02114     activeRouterCount = thread_routing_count_active_routers(&cur->thread_info->routing);
02115     if (activeRouterCount <= cur->thread_info->routerSelectParameters.routerDowngradeThresHold) {
02116         return false;
02117     }
02118 
02119     uint_fast8_t asGood;
02120     goodLinks = thread_routing_count_neighbours_for_downgrade(&cur->thread_info->routing, &asGood);
02121 
02122     //spec: Have at least MIN_DOWNGRADE_NEIGHBORS neighbors in set M.
02123     if (goodLinks < MIN_DOWNGRADE_NEIGHBORS) {
02124         return false;
02125     }
02126 
02127     //spec: Have at least one neighbor that has as good or better quality links to all Routers in M.
02128     if (asGood == 0) {
02129         return false;
02130     }
02131 
02132     //spec: Not be the sole Border Router for a particular Provisioning Domain
02133     if (!ns_list_is_empty(&cur->thread_info->localServerDataBase.prefix_list)) {
02134         return false;
02135     }
02136 
02137     uint16_t child_count = thread_router_bootstrap_child_count_get(cur);
02138     //Cant downgrade if child count is larger than 3 times exceed routers
02139     if (child_count > (3 * (activeRouterCount - cur->thread_info->routerSelectParameters.routerDowngradeThresHold))) {
02140         return false;
02141     }
02142     tr_info("Reed downgrade:ChildCount %u Active Routers %u good links %u downgrade threshold %u", child_count, activeRouterCount, goodLinks, cur->thread_info->routerSelectParameters.routerDowngradeThresHold);
02143 
02144     return true;
02145 }
02146 
02147 bool thread_router_bootstrap_reed_upgrade(protocol_interface_info_entry_t *cur)
02148 {
02149     uint8_t activeRouterCount;
02150 
02151     if (!thread_router_bootstrap_routing_allowed(cur)) {
02152         return false;
02153     }
02154 
02155     if (thread_am_router(cur)) {
02156         return false;
02157     }
02158 
02159     // if we are commissioner border router we have registered our address and cant upgrade or downgrade
02160     if (cur->thread_info->registered_commissioner.commissioner_valid &&
02161             addr_get_entry(cur,cur->thread_info->registered_commissioner.border_router_address) ) {
02162         return false;
02163     }
02164 
02165     if (!cur->thread_info->routing.router_id_sequence_valid) {
02166         // In case routing information is not up-to-date yet...
02167         return false;
02168     }
02169 
02170     activeRouterCount = thread_routing_count_active_routers(&cur->thread_info->routing);
02171 
02172     if (activeRouterCount >= cur->thread_info->routerSelectParameters.routerUpgradeThresHold) {
02173         return false;
02174     }
02175     tr_info("Reed Upgrade:Active Routers %u upgrade threshold %u", activeRouterCount, cur->thread_info->routerSelectParameters.routerUpgradeThresHold);
02176 
02177     return true;
02178 }
02179 
02180 void thread_router_bootstrap_child_id_reject(protocol_interface_info_entry_t *cur)
02181 {
02182     thread_pending_child_id_req_t *req;
02183     req = thread_child_id_request_entry_get_from_the_list(cur);
02184     while (req) {
02185         tr_debug("Remove entry from list");
02186         //Remove entry from list
02187         mle_class_remove_neighbour(cur->id, req->euid64, ADDR_802_15_4_LONG );
02188 
02189         ns_dyn_mem_free(req);
02190         req = thread_child_id_request_entry_get_from_the_list(cur);
02191     }
02192 }
02193 
02194 void thread_router_bootstrap_active_router_attach(protocol_interface_info_entry_t *cur)
02195 {
02196     uint8_t *parent_mac_addr = NULL;
02197     arm_nwk_6lowpan_thread_test_print_routing_database(cur->id);
02198     uint16_t address16 = mac_helper_mac16_address_get(cur);
02199     cur->thread_info->thread_attached_state = THREAD_STATE_CONNECTED_ROUTER;
02200 
02201     if (cur->thread_info->thread_leader_data->leaderRouterId == address16 &&
02202         !cur->thread_info->leader_private_data ) {
02203         // Error we are set up as leader but no private data
02204         tr_error("Leader setup error");
02205     }
02206     cur->lowpan_info |= INTERFACE_NWK_ROUTER_DEVICE;
02207     thread_routing_activate(&cur->thread_info->routing);
02208     thread_router_synch_new_router(cur, ADDR_LINK_LOCAL_ALL_ROUTERS);
02209     mle_class_mode_set(cur->id, MLE_CLASS_ROUTER);
02210     thread_bootstrap_ready(cur);
02211     thread_bootstrap_network_prefixes_process(cur);
02212     thread_nd_service_activate(cur->id);
02213     thread_router_bootstrap_mle_advertise(cur);
02214     if (cur->thread_info->thread_endnode_parent) {
02215         parent_mac_addr = cur->thread_info->thread_endnode_parent->mac64;
02216     }
02217     thread_nvm_store_link_info_write(parent_mac_addr, mac_helper_mac16_address_get(cur));
02218 }
02219 
02220 static int thread_validate_own_routeid_from_new_mask(const uint8_t *master_router_id_mask, uint8_t router_id)
02221 {
02222     int ret_val = -1;
02223     if (bit_test(master_router_id_mask, router_id)) {
02224         ret_val = 0;
02225     }
02226     return ret_val;
02227 }
02228 
02229 int thread_router_bootstrap_route_tlv_push(protocol_interface_info_entry_t *cur, uint8_t *route_tlv, uint8_t route_len, uint8_t linkMargin, mle_neigh_table_entry_t *entry)
02230 {
02231     (void) route_len;
02232 
02233     uint8_t route_id_seq;
02234     const uint8_t *router_id_mask, *route_data;
02235 
02236     route_id_seq = *route_tlv++;
02237     router_id_mask = route_tlv;
02238     route_tlv += 8;
02239     route_data = route_tlv;
02240     uint16_t mac16 = mac_helper_mac16_address_get(cur);
02241 
02242     if (!thread_is_router_addr(entry->short_adr)) {
02243         // Received route tlv from non router ignore
02244         tr_info("drop route Processing from end device %x", entry->short_adr);
02245         return 0;
02246     }
02247 
02248     if (thread_i_am_router(cur)) {
02249         thread_routing_info_t *routing = &cur->thread_info->routing;
02250         if (routing->router_id_sequence_valid && common_serial_number_greater_8(route_id_seq, routing->router_id_sequence)) {
02251             thread_routing_leader_connection_validate(cur->thread_info,routing->networkFragmentationTimer);
02252             routing->networkFragmentationTimer = 0;
02253             if (thread_validate_own_routeid_from_new_mask(router_id_mask, thread_router_id_from_addr(mac16)) != 0) {
02254 
02255                 tr_debug("RouterID not valid any More");
02256                 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_KICK, NULL);
02257                 return 0;
02258             }
02259         }
02260     } else if (!thread_info(cur)->thread_endnode_parent ||
02261                thread_info(cur)->thread_endnode_parent->shortAddress != entry->short_adr ) {
02262         return 0;
02263     }
02264 
02265     /* XXX Is short_src_adr ever reset? Is it undefined if info not in msg? */
02266     /* Don't add routing link if MLE link is NOT bi-directional (i.e. we can only hear) */
02267     if (entry->handshakeReady) {
02268         thread_routing_add_link(cur, entry->short_adr, linkMargin, route_id_seq, router_id_mask, route_data, false);
02269     }
02270 
02271     return 0;
02272 }
02273 
02274 
02275 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])
02276 {
02277     protocol_interface_info_entry_t *cur;
02278     (void) status;
02279     (void)router_mask_ptr;
02280     (void)router_rloc;
02281     cur = protocol_stack_interface_info_get_by_id(interface_id);
02282     tr_debug("RouterID ReleaseCB");
02283     if (!cur) {
02284         return;
02285     }
02286 
02287     if (!cur->thread_info->releaseRouterId) {
02288         return;
02289     }
02290     cur->thread_info->releaseRouterId = false;
02291 
02292     thread_bootstrap_router_id_release_ready(cur);
02293     return;
02294 
02295 }
02296 static uint32_t thread_reed_timeout_calculate(thread_router_select_t *routerSelect)
02297 {
02298     return randLIB_get_random_in_range(routerSelect->reedAdvertisementInterval,(routerSelect->reedAdvertisementInterval)+(routerSelect->reedAdvertisementJitterInterval));
02299 }
02300 
02301 
02302 static int thread_reed_advertise (protocol_interface_info_entry_t *cur)
02303 {
02304     uint32_t keySequence;
02305     tr_debug("MLE REED ADVERTISEMENT STARTED");
02306     struct link_configuration *linkConfiguration;
02307     linkConfiguration = thread_joiner_application_get_config(cur->id);
02308     if (!linkConfiguration) {
02309         return -1;
02310     }
02311 
02312     if (!thread_info(cur)) {
02313         return -1;
02314     }
02315 
02316     uint16_t bufId = mle_service_msg_allocate(cur->id, 16, false, MLE_COMMAND_ADVERTISEMENT);
02317     if (bufId == 0) {
02318         return -1;
02319     }
02320 
02321     thread_management_get_current_keysequence(cur->id, &keySequence);
02322     mle_service_msg_update_security_params(bufId, 5, 2, keySequence);
02323 
02324     uint8_t *ptr = mle_service_get_data_pointer(bufId);
02325 
02326     /*Add Leader Data & Source Address TLVs */
02327     ptr = thread_leader_data_tlv_write(ptr, cur);
02328     ptr = mle_general_write_source_address(ptr, cur);
02329     if (mle_service_update_length_by_ptr(bufId,ptr)!= 0) {
02330         tr_debug("Buffer overflow at message write");
02331     }
02332 
02333     mle_service_set_msg_destination_address(bufId, ADDR_LINK_LOCAL_ALL_NODES);
02334     mle_service_send_message(bufId);
02335     return 0;
02336 }
02337 
02338 static void thread_reed_advertisements_cb(void* arg)
02339 {
02340     if(!arg)
02341         return;
02342     protocol_interface_info_entry_t *cur = arg;
02343 
02344     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = NULL;
02345     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED &&
02346             cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER){
02347         thread_reed_advertise(cur);
02348         thread_router_bootstrap_child_information_clear(cur);
02349         cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb, thread_reed_timeout_calculate(&cur->thread_info->routerSelectParameters) * 1000, cur);
02350     }
02351 }
02352 
02353 void thread_router_bootstrap_reed_advertisements_start(protocol_interface_info_entry_t *cur)
02354 {
02355     uint32_t timeout = THREAD_REED_ADVERTISEMENT_DELAY;
02356     if(!cur)
02357         return;
02358     eventOS_timeout_cancel(cur->thread_info->routerSelectParameters.reedAdvertisementTimeout);
02359     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = NULL;
02360 
02361     cur->thread_info->reedJitterTimer = thread_router_bootstrap_random_upgrade_jitter();
02362 
02363     if (!thread_is_connected(cur)){
02364         return;
02365     }
02366     if (cur->thread_info->releaseRouterId  ||
02367             thread_router_bootstrap_child_count_get(cur) == 0) {
02368         // If we dont have any children or are are downgrading send REED advertisement immediately
02369         timeout = 1;
02370     }
02371     cur->thread_info->routerSelectParameters.reedAdvertisementTimeout = eventOS_timeout_ms(thread_reed_advertisements_cb,timeout, cur);
02372 }
02373 
02374 void thread_router_bootstrap_reed_merge_advertisement(protocol_interface_info_entry_t *cur)
02375 {
02376     if (cur->thread_info->reedMergeAdvTimer > 1) {
02377         return;
02378     }
02379     thread_reed_advertise(cur);
02380     // 120s second timer reinitialised before next merge advertisement
02381     cur->thread_info->reedMergeAdvTimer = THREAD_REED_MERGE_ADVERTISEMENT_INTERVAL;
02382 
02383 }
02384 void thread_router_bootstrap_router_id_release(protocol_interface_info_entry_t *cur)
02385 {
02386     tr_debug("Router ID Release");
02387     if (thread_management_client_router_id_release(cur->id, cur->mac, cur->thread_info->routerShortAddress, thread_bootstrap_client_router_id_release_cb) == 0) {
02388         // Release message sent succesfully
02389         cur->thread_info->routerShortAddress = 0xfffe;
02390         cur->thread_info->releaseRouterId = true;
02391     }
02392 }
02393 
02394 uint32_t thread_router_bootstrap_random_upgrade_jitter()
02395 {
02396    if (thread_router_selection_jitter <= 2) {
02397        return 1;
02398    }
02399     return randLIB_get_random_in_range(2,thread_router_selection_jitter);
02400 }
02401 
02402 void thread_router_bootstrap_timer(protocol_interface_info_entry_t *cur, uint32_t ticks)
02403 {
02404     thread_info_t *thread_info = cur->thread_info;
02405 
02406     if (thread_am_host(cur)) {
02407         return;
02408     }
02409 
02410     //Do we have a childs and we are REED state
02411     if (cur->thread_info->thread_attached_state == THREAD_STATE_CONNECTED && thread_router_bootstrap_child_count_get(cur)) {
02412         tr_debug("Trig quick router ID request");
02413         thread_bootstrap_attched_upgrade_reed(cur);
02414         return;
02415     }
02416 
02417     if (thread_info->reedJitterTimer > ticks) {
02418         // Reed status is checked every random jitter values
02419         thread_info->reedJitterTimer -= ticks;
02420     } else {
02421         thread_info->reedJitterTimer = thread_router_bootstrap_random_upgrade_jitter();
02422         if (thread_router_bootstrap_reed_upgrade(cur)) {
02423             //Check UpGrade possibility
02424             tr_debug("REED Upgrade to router");
02425             thread_bootstrap_attched_upgrade_reed(cur);
02426         }
02427         if (thread_router_bootstrap_router_downgrade(cur)) {
02428             tr_debug("Router downgrade to REED");
02429             thread_bootstrap_attached_downgrade_router(cur);
02430         }
02431     }
02432 
02433     if (cur->thread_info->reedMergeAdvTimer > ticks) {
02434         cur->thread_info->reedMergeAdvTimer -= ticks;
02435     } else {
02436         cur->thread_info->reedMergeAdvTimer = 0;
02437     }
02438 
02439     if (!thread_info->leader_private_data && thread_info->thread_attached_state == THREAD_STATE_CONNECTED_ROUTER) {
02440         // Non leader router checks
02441         if (thread_info->routing.activated) {
02442             if (thread_info->routing.networkFragmentationTimer++ >= thread_info->routing.networkIdTimeout) {
02443                 tr_debug("Leader Connection Lost");
02444                 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_REATTACH, NULL);
02445             }
02446         } else {
02447             tr_debug("Routing Disabled?");
02448         }
02449     }
02450 
02451     if (thread_info->proactive_an_timer) {
02452         if (thread_info->proactive_an_timer > ticks) {
02453             thread_info->proactive_an_timer -= ticks;
02454         } else {
02455             thread_send_proactive_an(cur);
02456             thread_info->proactive_an_timer = 0;
02457         }
02458     }
02459 
02460     thread_leader_service_timer(cur,ticks);
02461     return;
02462 }
02463 
02464 void thread_router_bootstrap_advertiment_analyze(protocol_interface_info_entry_t *cur, uint8_t *src_address, mle_neigh_table_entry_t *entry_temp, uint16_t shortAddress)
02465 {
02466     if (entry_temp) {
02467         entry_temp->threadNeighbor = true;
02468 
02469         if (entry_temp->timeout_rx == 0 || thread_is_router_addr(shortAddress)) {
02470             entry_temp->timeout_rx = THREAD_DEFAULT_LINK_LIFETIME / MLE_TIMER_TICKS_SECONDS;
02471             entry_temp->timeout_rx++;
02472         }
02473 
02474         if (thread_is_router_addr(shortAddress)) {
02475             //Update MAC Security PIB table by get & set Operation
02476             mlme_get_t get_req;
02477             get_req.attr = macDeviceTable;
02478             get_req.attr_index = entry_temp->attribute_index;
02479             cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
02480             entry_temp->ttl = entry_temp->timeout_rx;
02481         }
02482     } else {
02483         //
02484         if (!thread_attach_active_router(cur)) {
02485             // We are not router
02486             return;
02487         }
02488         if (!thread_is_router_addr(shortAddress)) {
02489             // Reed advertisement
02490             return;
02491         }
02492         if (thread_bootstrap_link_create_check(cur, shortAddress) &&
02493                 thread_bootstrap_link_create_allowed(cur, shortAddress, src_address)) {
02494             //Challenge new router neighbor
02495             tr_debug("Synch new neighbor");
02496             thread_router_synch_new_router(cur, src_address);
02497         }
02498     }
02499 }
02500 static void thread_router_bootstrap_dhcp_server_any_cast_address_update(protocol_interface_info_entry_t *cur, uint16_t anycastAddress)
02501 {
02502     uint8_t ipv6_address[16];
02503 
02504     thread_addr_write_mesh_local_16(ipv6_address, anycastAddress, cur->thread_info);
02505     tr_debug("generate DHCP anycast address %s", trace_ipv6(ipv6_address));
02506     addr_add(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC, 0xffffffff, 0, true);
02507 }
02508 
02509 static void thread_bootstrap_dhcp_anycast_address_generate(protocol_interface_info_entry_t *cur)
02510 {
02511     uint8_t ipv6_address[16];
02512     thread_addr_write_mesh_local_16(ipv6_address, 0xfc00, cur->thread_info);
02513     addr_delete_matching(cur,ipv6_address,124,ADDR_SOURCE_THREAD_ALOC);
02514 
02515     ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &cur->thread_info->networkDataStorage.localPrefixList) {
02516         // Go through all prefixes
02517         ns_list_foreach(thread_network_server_data_entry_t, curBorderRouter, &curPrefix->borderRouterList) {
02518             if (curBorderRouter->P_dhcp &&
02519                 curBorderRouter->routerID == cur->mac_parameters->mac_short_address) {
02520                 // We host this dhcp service we must add anycast address
02521                 ns_list_foreach(thread_network_data_context_entry_t, curRoute, &curPrefix->contextList) {
02522                     // Search what is the context id for this prefix
02523                     uint16_t anycastAddress = 0xfc00;
02524                     anycastAddress |= curRoute->cid;
02525                     thread_router_bootstrap_dhcp_server_any_cast_address_update(cur, anycastAddress);
02526                 }
02527             }
02528         }
02529     }
02530 }
02531 
02532 static void thread_bootstrap_service_anycast_address_generate(protocol_interface_info_entry_t *cur)
02533 {
02534     uint8_t ipv6_address[16];
02535 
02536     // Delete old address
02537     thread_addr_write_mesh_local_16(ipv6_address, 0xfc10, cur->thread_info);
02538     addr_delete_matching(cur,ipv6_address,124,ADDR_SOURCE_THREAD_ALOC);
02539 
02540     ns_list_foreach(thread_network_data_service_cache_entry_t, curService, &cur->thread_info->networkDataStorage.service_list) {
02541         // Go through all prefixes
02542         ns_list_foreach(thread_network_data_service_server_entry_t, curServiceServer, &curService->server_list) {
02543             if (curServiceServer->router_id == cur->mac_parameters->mac_short_address) {
02544                 // We host this service we must add anycast address
02545                 // Search what is the context id for this prefix
02546                 thread_addr_write_mesh_local_16(ipv6_address, 0xfc10 | curService->S_id, cur->thread_info);
02547                 tr_debug("generate Service anycast address %s", trace_ipv6(ipv6_address));
02548                 addr_add(cur, ipv6_address, 124, ADDR_SOURCE_THREAD_ALOC/*?*/, 0xffffffff, 0, true);
02549             }
02550         }
02551     }
02552 }
02553 
02554 
02555 static void thread_router_bootstrap_commissioner_aloc_generate(protocol_interface_info_entry_t *cur)
02556 {
02557     uint8_t commissioner_anycast[16];
02558 
02559     // Delete old address
02560     thread_addr_write_mesh_local_16(commissioner_anycast, 0xfc30 + (cur->thread_info->registered_commissioner.session_id % 8), cur->thread_info);
02561     addr_delete_matching(cur,commissioner_anycast,125,ADDR_SOURCE_THREAD_ALOC);
02562 
02563     if (!cur->thread_info->registered_commissioner.commissioner_valid) {
02564         // No commissioner available
02565         return;
02566     }
02567 
02568     if (!addr_get_entry(cur,cur->thread_info->registered_commissioner.border_router_address) ) {
02569         // Not our address
02570         return;
02571     }
02572     // Add commissioning border router address
02573     tr_debug("generate commissioner anycast address %s", trace_ipv6(commissioner_anycast));
02574     addr_add(cur,commissioner_anycast,64,ADDR_SOURCE_THREAD_ALOC,0xffffffff,0,true);
02575 }
02576 
02577 void thread_router_bootstrap_anycast_address_register(protocol_interface_info_entry_t *cur)
02578 {
02579     uint8_t leader_anycast_address[16];
02580 
02581     tr_debug("Register anycast address:");
02582 
02583     // Generate leader ALOC address
02584     thread_addr_write_mesh_local_16(leader_anycast_address, 0xfc00, cur->thread_info);
02585 
02586     if (cur->thread_info->leader_private_data) {
02587         tr_debug("Register leader anycast address: %s", trace_ipv6(leader_anycast_address));
02588         addr_add(cur, leader_anycast_address, 128, ADDR_SOURCE_UNKNOWN, 0xffffffff, 0, true);
02589     } else {
02590         // Delete Leader ALOC if ml prefix was changed address Source is the defining rule
02591         addr_delete_matching(cur,leader_anycast_address,128,ADDR_SOURCE_UNKNOWN);
02592 
02593     }
02594     thread_bootstrap_dhcp_anycast_address_generate(cur);
02595     thread_bootstrap_service_anycast_address_generate(cur);
02596     thread_router_bootstrap_commissioner_aloc_generate(cur);
02597     thread_extension_aloc_generate(cur);
02598 }
02599 
02600 static int thread_router_bootstrap_network_data_propagation(protocol_interface_info_entry_t *cur, uint8_t *childUnicastAddress, bool fullList)
02601 {
02602     uint8_t *payload_ptr;
02603     uint16_t payload_size = 16 + 4 + 20 + 4; //Version 4 bytes and Source address 4 bytes
02604     struct link_configuration *linkConfiguration;
02605     linkConfiguration = thread_joiner_application_get_config(cur->id);
02606     if (!linkConfiguration) {
02607         return -1;
02608     }
02609 
02610     if (!thread_info(cur)) {
02611         return -1;
02612     }
02613 
02614     payload_size += 2 + thread_network_data_tlv_size(cur, fullList);
02615     payload_size += thread_pending_timestamp_tlv_size(cur);
02616 
02617     mle_message_timeout_params_t timeout;
02618     uint16_t buf_id = mle_service_msg_allocate(cur->id, payload_size, false, MLE_COMMAND_DATA_RESPONSE);
02619     if (buf_id == 0) {
02620         return -1;
02621     }
02622 
02623     tr_debug("Send MLE data response network data changed");
02624     payload_ptr = mle_service_get_data_pointer(buf_id);
02625     uint8_t *address_ptr = mle_service_get_msg_destination_address_pointer(buf_id);
02626 
02627     /* Send to ULA16 of DATA_REQUEST originator. */
02628     /* Current_gp_prefix should have ULA prefix in */
02629     if (childUnicastAddress) {
02630         memcpy(address_ptr, childUnicastAddress, 16);
02631     } else {
02632         memcpy(address_ptr, ADDR_LINK_LOCAL_ALL_NODES, 16);
02633     }
02634 
02635     /*Add Leader Data & Network Data */
02636     payload_ptr = thread_leader_data_tlv_write(payload_ptr, cur);
02637     payload_ptr = thread_network_data_tlv_write(cur, payload_ptr, fullList);
02638 
02639     payload_ptr = thread_active_timestamp_write(cur, payload_ptr);
02640     payload_ptr = thread_pending_timestamp_write(cur, payload_ptr);
02641     payload_ptr = mle_general_write_source_address(payload_ptr, cur);
02642 
02643     if (mle_service_update_length_by_ptr(buf_id,payload_ptr)!= 0) {
02644         tr_debug("Buffer overflow at message write");
02645     }
02646     timeout.retrans_max = 0;
02647     timeout.timeout_init = 0;
02648     timeout.timeout_max = 0;
02649     timeout.delay = MLE_HALF_SECOND_MAX_DELAY;
02650     mle_service_set_msg_timeout_parameters(buf_id, &timeout);
02651     //Set Security
02652     uint32_t keySequence;
02653     thread_management_get_current_keysequence(cur->id, &keySequence);
02654     mle_service_msg_update_security_params(buf_id, 5, 2, keySequence);
02655 
02656     mle_service_send_message(buf_id);
02657     return 0;
02658 
02659 }
02660 
02661 static void thread_router_bootstrap_network_data_push_to_sleep_child(protocol_interface_info_entry_t *cur, bool stableDataUpdate)
02662 {
02663     uint8_t childLinkLocalAddress[16];
02664     mle_neigh_table_list_t *mle_table = mle_class_active_list_get(cur->id);
02665     memcpy(childLinkLocalAddress, ADDR_LINK_LOCAL_PREFIX, 8);
02666     ns_list_foreach(mle_neigh_table_entry_t, cur_entry, mle_table) {
02667         if (cur_entry->threadNeighbor) {
02668             if (!(cur_entry->mode & MLE_RX_ON_IDLE)) {
02669                 memcpy(&childLinkLocalAddress[8], cur_entry->mac64, 8);
02670                 childLinkLocalAddress[8] ^= 2;
02671                 if (cur_entry->mode & MLE_THREAD_REQ_FULL_DATA_SET) {
02672                     thread_router_bootstrap_network_data_propagation(cur, childLinkLocalAddress, true);
02673                 } else {
02674                     if (stableDataUpdate) {
02675                         thread_router_bootstrap_network_data_propagation(cur, childLinkLocalAddress, false);
02676                     }
02677                 }
02678             }
02679         }
02680     }
02681 }
02682 
02683 void thread_router_bootstrap_network_data_distribute(protocol_interface_info_entry_t *cur)
02684 {
02685     if (!thread_i_am_router(cur)) {
02686         return;
02687     }
02688     tr_debug("Propagate New Network Data");
02689     thread_router_bootstrap_network_data_propagation(cur, NULL, true);
02690     thread_router_bootstrap_network_data_push_to_sleep_child(cur, cur->thread_info->networkDataStorage.stableUpdatePushed);
02691 }
02692 
02693 bool thread_router_bootstrap_routing_allowed(struct protocol_interface_info_entry *cur)
02694 {
02695     link_configuration_s *link_conf_ptr = thread_management_configuration_get(cur->id);
02696 
02697     if (!link_conf_ptr) {
02698         return true;
02699     }
02700 
02701     return !(!thread_extension_version_check(cur->thread_info->version) && !(link_conf_ptr->securityPolicy & SECURITY_POLICY_ALL_ROUTERS_JOIN_ALLOWED));
02702 }
02703 
02704 void thread_router_bootstrap_address_change_notify_send(protocol_interface_info_entry_t *cur)
02705 {
02706     thread_info(cur)->proactive_an_timer = THREAD_PROACTIVE_AN_SEND_DELAY;
02707 }
02708 
02709 #endif /* HAVE_THREAD_ROUTER */