Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_management_if.c Source File

thread_management_if.c

00001 /*
00002  * Copyright (c) 2014-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: BSD-3-Clause
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holder nor the
00014  *    names of its contributors may be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #include "nsconfig.h"
00030 #include <string.h>
00031 #include "ns_types.h"
00032 #include "mlme.h"
00033 #include "NWK_INTERFACE/Include/protocol.h"
00034 #include "thread_management_if.h"
00035 #include <nsdynmemLIB.h>
00036 #include "eventOS_event.h"
00037 #include <ns_list.h>
00038 #include <net_thread_test.h>
00039 #include <net_ipv6_api.h>
00040 #include "ns_trace.h"
00041 #include "Core/include/ns_buffer.h"
00042 #include "common_functions.h"
00043 #include "6LoWPAN/Thread/thread_config.h"
00044 #include "6LoWPAN/Thread/thread_common.h"
00045 #include "6LoWPAN/Thread/thread_bootstrap.h"
00046 #include "6LoWPAN/Thread/thread_border_router_api_internal.h"
00047 #include "6LoWPAN/Thread/thread_routing.h"
00048 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00049 #include "6LoWPAN/Thread/thread_network_data_storage.h"
00050 #include "6LoWPAN/Thread/thread_leader_service.h"
00051 #include "6LoWPAN/Thread/thread_nd.h"
00052 #include "thread_diagnostic.h"
00053 #include "DHCPv6_client/dhcpv6_client_api.h"
00054 #include "6LoWPAN/Thread/thread_discovery.h"
00055 #include "6LoWPAN/Thread/thread_network_synch.h"
00056 #include "6LoWPAN/Thread/thread_management_internal.h"
00057 #include "6LoWPAN/Thread/thread_management_server.h"
00058 #include "6LoWPAN/Thread/thread_joiner_application.h"
00059 #include "6LoWPAN/Thread/thread_management_client.h"
00060 #include "6LoWPAN/Thread/thread_nvm_store.h"
00061 #include "6LoWPAN/Thread/thread_ccm.h"
00062 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00063 #include "6LoWPAN/Thread/thread_constants.h"
00064 #include "6LoWPAN/Thread/thread_bbr_api_internal.h"
00065 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00066 #include "Service_Libs/mle_service/mle_service_security.h"
00067 #include "RPL/rpl_control.h" // insanity - bootstraps shouldn't be doing each others' clean-up
00068 #include "MLE/mle.h"
00069 #include "MLE/mle_tlv.h"
00070 #include "thread_meshcop_lib.h"
00071 #include "thread_commissioning_if.h"
00072 #include "shalib.h"
00073 #include "Common_Protocols/icmpv6.h"
00074 #include "DHCPv6_Server/DHCPv6_server_service.h"
00075 #include "6LoWPAN/Thread/thread_dhcpv6_server.h"
00076 #include "Service_Libs/mle_service/mle_service_api.h"
00077 #include "Service_Libs/blacklist/blacklist.h"
00078 #include "6LoWPAN/MAC/mac_helper.h"
00079 #include "6LoWPAN/MAC/mac_pairwise_key.h"
00080 #include "6LoWPAN/MAC/mpx_api.h"
00081 #include "6LoWPAN/lowpan_adaptation_interface.h"
00082 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00083 #include "mac_common_defines.h"
00084 #include "mlme.h"
00085 #include "mac_api.h"
00086 
00087 #ifdef HAVE_THREAD
00088 #define TRACE_GROUP "thrm"
00089 
00090 static const uint8_t thread_discovery_key[16] = {0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66};
00091 static const uint8_t thread_discovery_extented_address[8] = {0x35, 0x06, 0xfe, 0xb8, 0x23, 0xd4, 0x87, 0x12};
00092 
00093 uint32_t thread_delay_timer_default = THREAD_DELAY_TIMER_DEFAULT_SECONDS;
00094 uint32_t thread_router_selection_jitter = THREAD_ROUTER_SELECTION_JITTER;
00095 uint16_t thread_joiner_port = THREAD_DEFAULT_JOINER_PORT;
00096 uint8_t thread_max_mcast_addr = THREAD_MCAST_ADDR_PER_MSG;
00097 
00098 /*
00099  * Prototypes
00100  */
00101 
00102 static void thread_discover_key_descriptor_set(struct mac_api_s *api, const uint8_t *key, uint8_t id, uint32_t key32_bit_src, uint8_t attribute_index)
00103 {
00104     mlme_set_t set_req;
00105     mlme_key_id_lookup_descriptor_t lookup_description;
00106     mlme_key_descriptor_entry_t key_description;
00107     mlme_key_device_descriptor_t dev_descriptor;
00108     if (key) {
00109         memset(lookup_description.LookupData, 0, 9);
00110         common_write_32_bit(key32_bit_src, lookup_description.LookupData);
00111         lookup_description.LookupData[4] = id;
00112         lookup_description.LookupDataSize = 0;
00113         memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
00114         memcpy(key_description.Key, key, 16);
00115         key_description.KeyIdLookupList = &lookup_description;
00116         key_description.KeyIdLookupListEntries = 1;
00117         dev_descriptor.Blacklisted = false;
00118         dev_descriptor.DeviceDescriptorHandle = attribute_index;
00119         dev_descriptor.UniqueDevice = true;
00120         key_description.KeyDeviceList = &dev_descriptor;
00121         key_description.KeyDeviceListEntries = 1;
00122 
00123     } else {
00124         memset(&key_description, 0, sizeof(mlme_key_descriptor_entry_t));
00125     }
00126     set_req.attr = macKeyTable;
00127     set_req.attr_index = 3; //Allwayd firth key
00128     set_req.value_pointer = &key_description;
00129     set_req.value_size = sizeof(mlme_key_descriptor_entry_t);
00130 
00131     api->mlme_req(api, MLME_SET, &set_req);
00132 }
00133 
00134 static void thread_discover_device_descriptor_set(struct mac_api_s *api, const uint8_t *device_extended_address, uint8_t attribute_index)
00135 {
00136     if (!api) {
00137         return;
00138     }
00139 
00140     mlme_device_descriptor_t device_desc;
00141     mlme_set_t set_req;
00142     device_desc.FrameCounter = 0;
00143     device_desc.Exempt = false;
00144     device_desc.ShortAddress = 0xffff;
00145     memcpy(device_desc.ExtAddress, device_extended_address, 8);
00146     device_desc.PANId = 0xffff;
00147 
00148 
00149     set_req.attr = macDeviceTable;
00150     set_req.attr_index = attribute_index;
00151     set_req.value_pointer = (void *)&device_desc;
00152     set_req.value_size = sizeof(mlme_device_descriptor_t);
00153     tr_debug("Register Discovery device descriptor");
00154     api->mlme_req(api, MLME_SET, &set_req);
00155 }
00156 
00157 static void thread_discover_security_material_update(protocol_interface_info_entry_t *cur, const mlme_security_t *security_params)
00158 {
00159     if (!security_params || !cur) {
00160         return;
00161     }
00162 
00163     if (security_params->SecurityLevel != SEC_ENC_MIC32 || security_params->KeyIdMode != MAC_KEY_ID_MODE_SRC4_IDX || security_params->KeyIndex != THREAD_DISCOVERY_SECURITY_KEY_INDEX) {
00164         return;
00165     }
00166     mac_description_storage_size_t buffer;
00167     if (common_read_32_bit(security_params->Keysource) != THREAD_DISCOVERY_SECURITY_KEY_SOURCE) {
00168         return;
00169     }
00170 
00171     if (!cur->mac_api || !cur->mac_api->mac_storage_sizes_get || cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
00172         return;
00173     }
00174     thread_discover_device_descriptor_set(cur->mac_api, thread_discovery_extented_address, buffer.device_decription_table_size - 1);
00175 }
00176 
00177 static void thread_security_trig_pending_key(protocol_interface_info_entry_t *cur)
00178 {
00179     if (cur->mac_parameters->mac_next_key_index) {
00180 
00181         //Call MAC Key Update
00182         uint8_t key_id = cur->mac_parameters->mac_next_key_index;
00183 
00184         mac_helper_security_key_swap_next_to_default(cur);
00185 
00186         if (mle_service_security_key_trig(cur->id, key_id)) {
00187             thread_security_update_from_mac(cur);
00188         }
00189     }
00190 }
00191 
00192 static void thread_mac_security_key_update_cb(protocol_interface_info_entry_t *cur, const mlme_security_t *security_params)
00193 {
00194     if (!cur->thread_info || !cur->mac_parameters) {
00195         return;
00196     }
00197     if (cur->mac_parameters->mac_next_key_index && (security_params->KeyIndex == cur->mac_parameters->mac_next_key_index)) {
00198         if (cur->thread_info->masterSecretMaterial.keySwitchGuardTimer == 0) {
00199             tr_debug("Trig Next Key");
00200             thread_security_trig_pending_key(cur);
00201         }
00202     } else {
00203         thread_discover_security_material_update(cur, security_params);
00204     }
00205 }
00206 
00207 int8_t thread_node_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
00208 {
00209     protocol_interface_info_entry_t *cur;
00210     uint8_t table_size = 4;
00211 
00212     cur = protocol_stack_interface_info_get_by_id(interface_id);
00213     if (!cur) {
00214         return -1;
00215     }
00216 
00217     //Read MAC device table sizes
00218     mac_description_storage_size_t buffer;
00219     if (!cur->mac_api || !cur->mac_api->mac_storage_sizes_get || cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
00220         return -1;
00221     }
00222 
00223     cur->configure_flags &= ~INTERFACE_BOOTSTRAP_DEFINED;
00224     mac_pairwise_key_interface_unregister(cur->id);
00225 
00226     if (buffer.key_description_table_size < 4) {
00227         tr_error("MAC key_description_table_size too short %d<4", buffer.key_description_table_size);
00228         return -1;
00229     }
00230 
00231     switch (bootstrap_mode) {
00232         case NET_6LOWPAN_HOST:
00233         case NET_6LOWPAN_SLEEPY_HOST:
00234             protocol_6lowpan_host_init(cur, bootstrap_mode == NET_6LOWPAN_SLEEPY_HOST);
00235             break;
00236 
00237         case NET_6LOWPAN_ROUTER:
00238             protocol_6lowpan_router_init(cur);
00239             table_size = buffer.key_description_table_size;
00240             break;
00241 
00242         default:
00243             return -3;
00244     }
00245 
00246     if (mac_pairwise_key_interface_register(cur->id, table_size, 4) < 0) {
00247         tr_error("MAC pairwise key in registration failed");
00248         return -1;
00249     }
00250 
00251     if (blacklist_init() != 0) {
00252         tr_debug("6LoWPAN MLE blacklist init failed.");
00253         return -1;
00254     }
00255 
00256     blacklist_params_set(
00257         THREAD_BLACKLIST_ENTRY_LIFETIME,
00258         THREAD_BLACKLIST_TIMER_MAX_TIMEOUT,
00259         THREAD_BLACKLIST_TIMER_TIMEOUT,
00260         THREAD_BLACKLIST_ENTRY_MAX_NBR,
00261         THREAD_BLACKLIST_PURGE_NBR,
00262         THREAD_BLACKLIST_PURGE_TIMER_TIMEOUT);
00263 
00264     if (thread_info_allocate_and_init(cur) < 0) {
00265         mac_pairwise_key_interface_unregister(cur->id);
00266         return -3;
00267     }
00268 
00269     if (thread_discovery_init(cur->id, cur, thread_info(cur)->version, bootstrap_mode == NET_6LOWPAN_ROUTER) != 0) {
00270         tr_error("Discovery init fail");
00271         mac_pairwise_key_interface_unregister(cur->id);
00272         return -3;
00273     }
00274 
00275     cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED;
00276     cur->lowpan_info |= INTERFACE_NWK_BOOTSRAP_MLE;
00277     rpl_control_remove_domain_from_interface(cur);
00278     //SET MAC key id mode 2 key and device
00279     thread_discover_key_descriptor_set(cur->mac_api, thread_discovery_key, THREAD_DISCOVERY_SECURITY_KEY_INDEX, THREAD_DISCOVERY_SECURITY_KEY_SOURCE, buffer.device_decription_table_size - 1);
00280 
00281     thread_discover_device_descriptor_set(cur->mac_api, thread_discovery_extented_address, buffer.device_decription_table_size - 1);
00282 
00283     cur->mac_security_key_usage_update_cb = thread_mac_security_key_update_cb;
00284     return 0;
00285 }
00286 
00287 
00288 void arm_thread_private_ula_prefix_set(protocol_interface_info_entry_t *cur, const uint8_t *ula_prefix)
00289 {
00290     //Define Local Thread
00291     memcpy(cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, ula_prefix, 8);
00292     cur->thread_info->threadPrivatePrefixInfo.ulaValid = true;
00293 }
00294 
00295 /**
00296  * Calculate New Key Material by given security key material and sequency number
00297  *
00298  * \param key Thread Master key pointer
00299  * \param key_material_buf Buffer for calculated MAC & MLE key: first 128-bit for MLE and rest 128-bit for MAC
00300  * \param threadSequency Key material key index.
00301  *
00302  */
00303 void thread_key_get(uint8_t *key, uint8_t *key_material_buf,  uint32_t key_sequence_counter)
00304 {
00305     static uint8_t key_seed[6] = {'T', 'h', 'r', 'e', 'a', 'd'};
00306     static uint8_t temp32_buf[4];
00307     common_write_32_bit(key_sequence_counter, temp32_buf);
00308     SHALIB_init_HMAC(key, 16);
00309     SHALIB_push_data_HMAC(temp32_buf, 4);
00310     SHALIB_push_data_HMAC(key_seed, 6);
00311     SHALIB_finish_HMAC(key_material_buf, 8);
00312 }
00313 
00314 /**
00315  * Thread key sequence & key synch
00316  *
00317  */
00318 void thread_management_key_synch_req(int8_t interface_id, uint32_t keySequnce)
00319 {
00320     protocol_interface_info_entry_t *cur;
00321     link_configuration_s *linkConfiguration;
00322     linkConfiguration = thread_joiner_application_get_config(interface_id);
00323     if (!linkConfiguration) {
00324         return;
00325     }
00326     cur = protocol_stack_interface_info_get_by_id(interface_id);
00327     if (!cur || !cur->thread_info) {
00328         return;
00329     }
00330     if (!cur->thread_info->masterSecretMaterial.valid_Info) {
00331         return;
00332     }
00333     //tr_debug("Sync key material by %"PRIu32, keySequnce);
00334 
00335     if (keySequnce <= linkConfiguration->key_sequence) {
00336         // Smaller or equal request ignored
00337         //tr_debug("Sync key material no change");
00338         return;
00339     }
00340     if ((cur->thread_info->masterSecretMaterial.keySwitchGuardTimer > 0)) {
00341         // Guard time prevent the change
00342         //tr_debug("Sync key material guard blocked");
00343         return;
00344     }
00345     // Calculate new keys
00346     tr_debug("Sync key material by %"PRIu32, keySequnce);
00347     thread_management_key_sets_calc(cur, linkConfiguration, keySequnce);
00348     thread_key_guard_timer_calculate(cur, linkConfiguration, false);
00349 }
00350 
00351 static void thread_history_key_material_push(thread_info_t *thread_info, uint8_t *mleKeyPtr, uint8_t keyId)
00352 {
00353     thread_info->masterSecretMaterial.historyKeyValid = true;
00354     thread_info->masterSecretMaterial.historyKeyId = keyId;
00355     memcpy(thread_info->masterSecretMaterial.historyKey, mleKeyPtr, 16);
00356 }
00357 
00358 void thread_security_update_from_mac(protocol_interface_info_entry_t *cur)
00359 {
00360     uint8_t *mleKey;
00361     uint8_t historyKeyId;
00362     link_configuration_s *linkConfiguration;
00363     linkConfiguration = thread_joiner_application_get_config(cur->id);
00364     if (!linkConfiguration) {
00365         return;
00366     }
00367 
00368     mleKey = mle_service_security_next_key_get(cur->id);
00369     if (!mleKey) {
00370         return;
00371     }
00372     historyKeyId = mle_service_security_next_key_id_get(cur->id);
00373 
00374     /* Set old secondary to history */
00375     thread_history_key_material_push(cur->thread_info, mleKey, historyKeyId);
00376     linkConfiguration->key_sequence++;
00377     mac_helper_link_frame_counter_set(cur->id, 0);
00378     thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
00379     thread_key_guard_timer_calculate(cur, linkConfiguration, false);
00380 }
00381 
00382 void thread_security_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
00383 {
00384     uint8_t key_material[32];
00385     uint8_t key_index;
00386     //primary key is generated from the current value of sequence counter
00387     uint32_t thrKeySequenceCounter = keySequence;
00388     /* Produced keys from Thread security material: MAC key | MLE key */
00389     thread_key_get(masterKey, key_material, thrKeySequenceCounter);
00390     /* Update keys as primary keys */
00391     key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
00392     tr_debug("Set current key Id: %u", key_index);
00393     mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
00394     mle_service_security_set_security_key(cur->id, key_material, key_index, true);
00395 }
00396 
00397 
00398 void thread_security_prev_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
00399 {
00400     uint8_t key_material[32];
00401     uint8_t key_index;
00402     uint32_t thrKeySequenceCounter;
00403     if (keySequence == 0) {
00404         // in initial value there is no prev available
00405         return;
00406     }
00407     thrKeySequenceCounter = keySequence - 1;
00408     /* Produced keys from Thread security material: MAC key | MLE key */
00409     thread_key_get(masterKey, key_material, thrKeySequenceCounter);
00410     /* Update keys as primary keys */
00411     key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
00412     tr_debug("Set previous key Id: %u", key_index);
00413     mac_helper_security_prev_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX);
00414     mle_service_security_set_security_key(cur->id, key_material, key_index, false);
00415     //copy master secret material to history
00416     thread_history_key_material_push(cur->thread_info, key_material, key_index);
00417 }
00418 
00419 void thread_security_next_key_generate(protocol_interface_info_entry_t *cur, uint8_t *masterKey, uint32_t keySequence)
00420 {
00421     uint8_t key_material[32];
00422     uint8_t key_index;
00423     uint32_t thrKeySequenceCounter;
00424     /* Will wrap modulo 32 bits */
00425     thrKeySequenceCounter = keySequence + 1;
00426     /* Produced keys from Thread security material: MAC key | MLE key */
00427     thread_key_get(masterKey, key_material, thrKeySequenceCounter);
00428     /* Update keys as non-primary keys */
00429     key_index = THREAD_KEY_INDEX(thrKeySequenceCounter);
00430     tr_debug("Set next key Id: %u", key_index);
00431     mac_helper_security_next_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX); /* Auth counter not relevant for Thread */
00432     mle_service_security_set_security_key(cur->id, key_material, key_index, false);
00433 }
00434 
00435 int thread_management_key_sets_calc(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration, uint32_t thrKeySequenceCounter)
00436 {
00437     int ret_val = -1;
00438 
00439     if (thrKeySequenceCounter == linkConfiguration->key_sequence) {
00440         /* Same key - do not change */
00441         ret_val = 0;
00442     } else if (thrKeySequenceCounter == (linkConfiguration->key_sequence + 1)) {
00443         /* Next key - trig pending key */
00444         thread_security_trig_pending_key(cur);
00445         ret_val = 0;
00446     } else {
00447         /* Generate new key set */
00448         //Clean All Keys
00449         mac_helper_security_key_clean(cur);
00450 
00451         // Update key sequence
00452         linkConfiguration->key_sequence = thrKeySequenceCounter;
00453         // Zero all frame counters. MLE does it automatically
00454         mac_helper_link_frame_counter_set(cur->id, 0);
00455         // Store all frame counters as zero and update the sequence counter
00456         thread_nvm_store_fast_data_write_all(0, 0, thrKeySequenceCounter);
00457 
00458         thread_security_prev_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
00459         thread_security_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
00460         thread_security_next_key_generate(cur, linkConfiguration->master_key, linkConfiguration->key_sequence);
00461         ret_val = 0;
00462     }
00463     return ret_val;
00464 }
00465 
00466 int thread_management_get_my_iid16(int8_t interface_id, uint8_t *iidPtr)
00467 {
00468     protocol_interface_info_entry_t *cur;
00469     cur = protocol_stack_interface_info_get_by_id(interface_id);
00470     if (!cur) {
00471         return -1;
00472     }
00473 
00474     if (!cur->thread_info) {
00475         return -1;
00476     }
00477 
00478     if (thread_attach_ready(cur) != 0) {
00479         return -1;
00480     }
00481 
00482     if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) {
00483         return -1;
00484     }
00485 
00486     memcpy(iidPtr, ADDR_SHORT_ADR_SUFFIC, 6);
00487     common_write_16_bit(mac_helper_mac16_address_get(cur), (iidPtr + 6));
00488 
00489     return 0;
00490 }
00491 
00492 int thread_management_get_current_keysequence(int8_t interface_id, uint32_t *sequencePtr)
00493 {
00494 
00495     link_configuration_s *linkConfiguration;
00496     linkConfiguration = thread_joiner_application_get_config(interface_id);
00497     if (!linkConfiguration) {
00498         return -1;
00499     }
00500     protocol_interface_info_entry_t *cur;
00501     cur = protocol_stack_interface_info_get_by_id(interface_id);
00502     if (!cur) {
00503         return -1;
00504     }
00505 
00506     if (!cur->thread_info) {
00507         return -1;
00508     }
00509 
00510     if (!cur->thread_info->masterSecretMaterial.valid_Info) {
00511         return -1;
00512     }
00513 
00514     *sequencePtr = linkConfiguration->key_sequence;
00515 
00516     return 0;
00517 }
00518 
00519 int thread_management_increment_key_sequence_counter(int8_t interface_id)
00520 {
00521     protocol_interface_info_entry_t *cur;
00522 
00523     cur = protocol_stack_interface_info_get_by_id(interface_id);
00524     if (cur && cur->thread_info) {
00525         /* Not sure if this check is needed - not sure exactly what the flag means! */
00526         if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) == 0) {
00527             return -1;
00528         }
00529 
00530         if ((cur->configure_flags & INTERFACE_BOOTSTRAP_DEFINED) == 0) {
00531             return -1;
00532         }
00533 
00534         //Trig Pending Key
00535         thread_security_trig_pending_key(cur);
00536         return 0;
00537     }
00538     return -1;
00539 }
00540 
00541 int thread_management_get_ml_prefix(int8_t interface_id, uint8_t *prefix_ptr)
00542 {
00543     // TODO get from static configuration
00544     protocol_interface_info_entry_t *cur;
00545     cur = protocol_stack_interface_info_get_by_id(interface_id);
00546     if (!cur || !prefix_ptr) {
00547         return -1;
00548     }
00549 
00550     if (!cur->thread_info) {
00551         return -1;
00552     }
00553 
00554     if (thread_attach_ready(cur) != 0) {
00555         return -1;
00556     }
00557 
00558     if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) {
00559         return -1;
00560     }
00561 
00562     memcpy(prefix_ptr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
00563 
00564     return 0;
00565 }
00566 
00567 /* Get my mesh local prefix /112 */
00568 int thread_management_get_ml_prefix_112(int8_t interface_id, uint8_t *prefix_ptr)
00569 {
00570     protocol_interface_info_entry_t *cur;
00571     cur = protocol_stack_interface_info_get_by_id(interface_id);
00572     if (!cur || !prefix_ptr) {
00573         return -1;
00574     }
00575 
00576     if (!cur->thread_info) {
00577         return -1;
00578     }
00579 
00580     if (thread_attach_ready(cur) != 0) {
00581         return -1;
00582     }
00583 
00584     if (!cur->thread_info->threadPrivatePrefixInfo.ulaValid) {
00585         return -1;
00586     }
00587 
00588     memcpy(prefix_ptr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
00589     memcpy(prefix_ptr + 8, ADDR_SHORT_ADR_SUFFIC, 6);
00590 
00591     return 0;
00592 }
00593 
00594 #endif
00595 
00596 /**
00597  *  Public interface functions.
00598  */
00599 
00600 /**
00601  * Set DHCPV6 server for Thread GP data purpose
00602  *
00603  * \param interface_id Network Interface
00604  * \param prefix_ptr pointer DHCPv6 Server Given Prefix
00605  *
00606  * return 0, Set OK
00607  * return <0 Set Not OK
00608  */
00609 int thread_dhcpv6_server_add(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_cnt, bool stableData)
00610 {
00611 #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
00612     protocol_interface_info_entry_t *cur;
00613     thread_prefix_tlv_t prefixTlv;
00614     thread_border_router_tlv_entry_t service;
00615     uint8_t temp[16];
00616     uint8_t *ptr = temp;
00617 
00618     cur = protocol_stack_interface_info_get_by_id(interface_id);
00619     if (!cur) {
00620         return -1;
00621     }
00622 
00623     if (!cur->thread_info) {
00624         return -1;
00625     }
00626 
00627     if (thread_dhcp6_server_init(interface_id, prefix_ptr, cur->mac, THREAD_MIN_PREFIX_LIFETIME) != 0) {
00628         tr_warn("SerVER alloc fail");
00629         return -1;
00630     }
00631 
00632     prefixTlv.domainId = 0;
00633     prefixTlv.Prefix = prefix_ptr;
00634     prefixTlv.PrefixLen = 64;
00635 
00636     memset(&service, 0, sizeof(thread_border_router_tlv_entry_t));
00637     service.Prf = 1;
00638     service.P_dhcp = true;
00639     service.P_on_mesh = true;
00640     service.stableData = stableData;
00641 
00642     // SET maximum number of accepted clients
00643     DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_cnt);
00644 
00645     tr_debug("GUA server Generate OK");
00646     memcpy(ptr, prefix_ptr, 8);
00647     memset(ptr + 8, 0, 8);
00648     //Network Data
00649     if (thread_local_server_list_add_on_mesh_server(&cur->thread_info->localServerDataBase, &prefixTlv, &service) != 0) {
00650         return -1;
00651     }
00652 
00653     return 0;
00654 #else
00655     (void) interface_id;
00656     (void) prefix_ptr;
00657     (void) max_client_cnt;
00658     (void) stableData;
00659     return -1;
00660 #endif
00661 }
00662 
00663 int thread_dhcpv6_server_set_lifetime(int8_t interface_id, uint8_t *prefix_ptr, uint32_t valid_lifetime)
00664 {
00665 #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
00666     if (!prefix_ptr) {
00667         return -1;
00668     }
00669 
00670     return DHCPv6_server_service_set_address_validlifetime(interface_id, prefix_ptr, valid_lifetime);
00671 #else
00672     (void) interface_id;
00673     (void) prefix_ptr;
00674     (void) valid_lifetime;
00675     return -1;
00676 #endif
00677 }
00678 
00679 int thread_dhcpv6_server_set_max_client(int8_t interface_id, uint8_t *prefix_ptr, uint32_t max_client_count)
00680 {
00681 #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
00682     if (!prefix_ptr) {
00683         return -1;
00684     }
00685 
00686     return DHCPv6_server_service_set_max_clients_accepts_count(interface_id, prefix_ptr, max_client_count);
00687 #else
00688     (void) interface_id;
00689     (void) prefix_ptr;
00690     (void) max_client_count;
00691     return -1;
00692 #endif
00693 }
00694 
00695 int thread_dhcpv6_server_set_anonymous_addressing(int8_t interface_id, uint8_t *prefix_ptr, bool anonymous)
00696 {
00697 #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
00698     if (!prefix_ptr) {
00699         return -1;
00700     }
00701 
00702     return DHCPv6_server_service_set_address_autonous_flag(interface_id, prefix_ptr, anonymous);
00703 #else
00704     (void) interface_id;
00705     (void) prefix_ptr;
00706     (void) anonymous;
00707     return -1;
00708 #endif
00709 
00710 }
00711 
00712 
00713 int thread_dhcpv6_server_delete(int8_t interface_id, uint8_t *prefix_ptr)
00714 {
00715 #if defined(HAVE_THREAD) && defined(HAVE_DHCPV6_SERVER)
00716     uint8_t temp[16];
00717     protocol_interface_info_entry_t *cur;
00718     thread_prefix_tlv_t prefixTlv;
00719     tr_debug("GUA server Delete");
00720     cur = protocol_stack_interface_info_get_by_id(interface_id);
00721     if (!cur) {
00722         return -1;
00723     }
00724 
00725     if (!cur->thread_info) {
00726         return -1;
00727     }
00728 
00729     memcpy(temp, prefix_ptr, 8);
00730     memset(temp + 8, 0, 8);
00731 
00732     prefixTlv.domainId = 0;
00733     prefixTlv.Prefix = prefix_ptr;
00734     prefixTlv.PrefixLen = 64;
00735     //Delete dhcp service
00736     DHCPv6_server_service_delete(interface_id, prefix_ptr, false);
00737     ipv6_route_delete(temp, 64, cur->id, NULL, ROUTE_THREAD);
00738     thread_local_server_list_del_on_mesh_server(&cur->thread_info->localServerDataBase, &prefixTlv);
00739 
00740     return 0;
00741 #else
00742     (void) interface_id;
00743     (void) prefix_ptr;
00744     return -1;
00745 #endif
00746 }
00747 
00748 #ifdef HAVE_THREAD
00749 static mac_neighbor_table_entry_t *neighbor_data_poll_referesh(protocol_interface_info_entry_t *cur, const uint8_t *address, addrtype_t type)
00750 {
00751     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(mac_neighbor_info(cur), address, type);
00752     if (!entry || !entry->connected_device ) {
00753         return NULL;
00754     }
00755 
00756     entry->lifetime  = entry->link_lifetime ;
00757     return entry;
00758 }
00759 void thread_comm_status_indication_cb(int8_t if_id, const mlme_comm_status_t *status)
00760 {
00761     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(if_id);
00762     if (!cur) {
00763         return;
00764     }
00765     mac_neighbor_table_entry_t *entry;
00766 
00767     switch (status->status) {
00768 
00769         case MLME_SECURITY_FAIL:
00770 
00771             break;
00772 
00773         case MLME_COUNTER_ERROR:
00774 
00775             break;
00776 
00777         case MLME_DATA_POLL_NOTIFICATION:
00778             entry = neighbor_data_poll_referesh(cur, status->SrcAddr, (addrtype_t)status->SrcAddrMode);
00779             if (entry) {
00780                 thread_neighbor_communication_update(cur, entry->index );
00781             }
00782             break;
00783         default:
00784             break;
00785     }
00786 }
00787 #endif
00788 
00789 int thread_management_node_init(
00790     int8_t interface_id,
00791     channel_list_s *channel_list,
00792     device_configuration_s *device_configuration,
00793     link_configuration_s *static_configuration)
00794 {
00795 #ifdef HAVE_THREAD
00796     protocol_interface_info_entry_t *cur;
00797     nwk_scan_params_t *scan_params;
00798 
00799     if (!device_configuration) {
00800         return -1;
00801     }
00802 
00803     cur = protocol_stack_interface_info_get_by_id(interface_id);
00804 
00805     if (!cur) {
00806         tr_warn("Invalid interface id");
00807         return -1;
00808     }
00809 
00810     if (!cur->thread_info) {
00811         tr_warn("Not Thread specific interface");
00812         return -1;
00813     }
00814 
00815     if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) !=  0) {
00816         return -1;
00817     }
00818 
00819     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER || cur->border_router_setup) {
00820         return -1;
00821     }
00822 
00823     if (thread_init(cur) < 0) {
00824         thread_nd_service_delete(cur->id);
00825         tr_warn("Thread Boostarp Init Fail");
00826         return -1;
00827     }
00828     if (thread_management_server_init(cur->id) != 0) {
00829         tr_warn("Thread management server init fail");
00830         return -1;
00831     }
00832 
00833     if (thread_diagnostic_init(cur->id) != 0) {
00834         tr_warn("Thread diagnostic init fail");
00835         return -1;
00836     }
00837     //Store setup to application Joiner Application
00838     if (thread_joiner_application_init(cur->id, device_configuration, static_configuration) != 0) {
00839         tr_error("mandatory device configuration missing");
00840         return -2;
00841     }
00842 
00843     // Joiner application copies and massages the device configuration - switch to massaged version
00844     device_configuration = thread_joiner_application_get_device_config(cur->id);
00845     if (!device_configuration) {
00846         return -1;
00847     }
00848     cur->if_lowpan_security_params->nwk_security_mode = NET_SEC_MODE_NO_LINK_SECURITY;
00849     cur->mac_parameters->mac_configured_sec_level = 0;
00850 
00851     // If no-one has already set a secret key, use the EUI-64 - Thread
00852     // wants RFC 7217 IIDs. Also ensure they're on for the Thread interface.
00853     // (Note that this will likely enable opaque IIDs on Ethernet too).
00854     if (!addr_opaque_iid_key_is_set()) {
00855         // Could we include some private key here?
00856         arm_nwk_ipv6_opaque_iid_key(device_configuration->eui64, 8);
00857         arm_nwk_ipv6_opaque_iid_enable(cur->id, true);
00858     }
00859     // Copy the channel list
00860     memset(&cur->mac_parameters->mac_channel_list, 0, sizeof(channel_list_s));
00861     if (channel_list) {
00862         // Application has given limited set of channels
00863         cur->mac_parameters->mac_channel_list = *channel_list;
00864     } else {
00865         cur->mac_parameters->mac_channel_list.channel_page = CHANNEL_PAGE_0;
00866         cur->mac_parameters->mac_channel_list.channel_mask[0] = 0x07FFF800;
00867     }
00868 
00869     scan_params = &cur->mac_parameters->nwk_scan_params;
00870     memset(&scan_params->stack_chan_list, 0, sizeof(channel_list_s));
00871     if (channel_list) {
00872         // Application has given limited set of channels
00873         scan_params->stack_chan_list = *channel_list;
00874     } else {
00875         scan_params->stack_chan_list.channel_page = CHANNEL_PAGE_0;
00876         scan_params->stack_chan_list.channel_mask[0] = 0x07FFF800;
00877     }
00878     scan_params->scan_duration = 5;
00879 
00880     cur->thread_info->masterSecretMaterial.valid_Info = false;
00881     thread_key_guard_timer_calculate(cur, static_configuration, true);
00882 
00883     cur->thread_info->maxChildCount = THREAD_MAX_CHILD_COUNT;
00884     cur->thread_info->rfc6775 = false;
00885     cur->thread_info->host_link_timeout = THREAD_END_DEVICE_DEFAULT_TIMEOUT;
00886     /* Thread will manage the address query timing, and report negatives. Set this high so as not to interfere. */
00887     cur->ipv6_neighbour_cache.retrans_timer = 10000;
00888 
00889     // Set default partition weighting
00890     cur->thread_info->partition_weighting = THREAD_DEFAULT_WEIGHTING;
00891 
00892     /* IP forwarding is off by default */
00893     cur->ip_forwarding = false;
00894 
00895     lowpan_adaptation_indirect_queue_params_set(cur,
00896                                                 THREAD_INDIRECT_BIG_PACKET_THRESHOLD,
00897                                                 THREAD_INDIRECT_BIG_PACKETS_TOTAL,
00898                                                 THREAD_INDIRECT_SMALL_PACKETS_PER_CHILD);
00899 
00900     if (cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST) {
00901         cur->thread_info->requestFullNetworkData = false;
00902     } else {
00903         cur->thread_info->requestFullNetworkData = true;
00904     }
00905 
00906     cur->lowpan_info &= ~INTERFACE_NWK_BOOTSRAP_PANA_AUTHENTICATION;
00907     cur->configure_flags |= INTERFACE_SECURITY_DEFINED;
00908     cur->comm_status_ind_cb = thread_comm_status_indication_cb;
00909     return 0;
00910 #else
00911     (void) interface_id;
00912     (void) channel_list;
00913     (void) device_configuration;
00914     (void) static_configuration;
00915     return -1;
00916 #endif
00917 }
00918 
00919 int thread_management_device_type_set(int8_t interface_id, thread_device_type_e device_type)
00920 {
00921 #ifdef HAVE_THREAD
00922     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00923 
00924     if (!cur || !cur->thread_info) {
00925         tr_warn("Not Thread specific interface");
00926         return -1;
00927     }
00928     if (device_type == THREAD_DEVICE_REED) {
00929         // Change mode to router
00930         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_ROUTER;
00931     } else if (device_type == THREAD_DEVICE_FED) {
00932         //FED devices makes links and makes address resolutions
00933         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST;
00934         cur->thread_info->end_device_link_synch = true;
00935     } else if (device_type == THREAD_DEVICE_MED) {
00936         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_HOST;
00937         cur->thread_info->end_device_link_synch = false;
00938     } else if (device_type == THREAD_DEVICE_SED) {
00939         cur->bootsrap_mode = ARM_NWK_BOOTSRAP_MODE_6LoWPAN_SLEEPY_HOST;
00940         cur->thread_info->end_device_link_synch = false;
00941     }
00942     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
00943         // bootstrap active need to restart
00944         thread_bootstrap_reset_restart(interface_id);
00945     }
00946 
00947     return 0;
00948 #else
00949     (void) interface_id;
00950     (void) device_type;
00951     return -1;
00952 #endif
00953 }
00954 
00955 int thread_management_max_child_count(
00956     int8_t interface_id,
00957     uint8_t maxChildCount)
00958 {
00959 #ifdef HAVE_THREAD
00960     protocol_interface_info_entry_t *cur;
00961 
00962     cur = protocol_stack_interface_info_get_by_id(interface_id);
00963     if (!cur) {
00964         tr_warn("Invalid interface id");
00965         return -1;
00966     }
00967 
00968     if (!cur->thread_info) {
00969         tr_warn("Not Thread specific interface");
00970         return -1;
00971     }
00972 
00973     mac_description_storage_size_t buffer;
00974     if (!cur->mac_api || !cur->mac_api->mac_storage_sizes_get || cur->mac_api->mac_storage_sizes_get(cur->mac_api, &buffer) != 0) {
00975         return -1;
00976     }
00977 
00978     if (maxChildCount > buffer.device_decription_table_size) {
00979         tr_error("Accept values are between 0-%d for max Child count", buffer.device_decription_table_size);
00980         return -1;
00981     }
00982     cur->thread_info->maxChildCount = maxChildCount;
00983     return 0;
00984 #else
00985     (void) interface_id;
00986     (void) maxChildCount;
00987     return -1;
00988 #endif
00989 }
00990 
00991 link_configuration_s *thread_management_configuration_get(int8_t interface_id)
00992 {
00993 #ifdef HAVE_THREAD
00994     return thread_joiner_application_get_config(interface_id);
00995 #else
00996     (void) interface_id;
00997     return NULL;
00998 #endif
00999 }
01000 
01001 device_configuration_s *thread_management_device_configuration_get(int8_t interface_id)
01002 {
01003 #ifdef HAVE_THREAD
01004     return thread_joiner_application_get_device_config(interface_id);
01005 #else
01006     (void) interface_id;
01007     return NULL;
01008 #endif
01009 }
01010 
01011 int thread_management_link_configuration_store(int8_t interface_id, link_configuration_s *link_config)
01012 {
01013 #ifdef HAVE_THREAD
01014     int ret = thread_joiner_application_link_configuration_store(interface_id, link_config);
01015 
01016     if (interface_id == -1) {
01017         return ret;
01018     }
01019 
01020     if (ret >= 0) {
01021         protocol_interface_info_entry_t *cur =  protocol_stack_interface_info_get_by_id(interface_id);
01022         if (!link_config || !cur  || !cur->thread_info) {
01023             return -2;
01024         }
01025         if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) !=  0) {
01026             // take new settings into use after restart
01027             thread_bootstrap_reset_restart(interface_id);
01028         }
01029     }
01030 
01031     return ret;
01032 #else
01033     (void) interface_id;
01034     (void) link_config;
01035     return -1;
01036 #endif
01037 }
01038 
01039 int thread_management_link_configuration_add(int8_t interface_id, uint8_t *additional_ptr, uint8_t additional_len)
01040 {
01041 #ifdef HAVE_THREAD
01042     if (interface_id < 0) {
01043         return -1;
01044     }
01045 
01046     int ret = thread_joiner_application_update_configuration(interface_id, additional_ptr, additional_len, true);
01047     if (ret != 0) {
01048         return ret;
01049     }
01050 
01051     protocol_interface_info_entry_t *cur =  protocol_stack_interface_info_get_by_id(interface_id);
01052     if (!cur  || !cur->thread_info) {
01053         return -2;
01054     }
01055     if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) !=  0) {
01056         // take new settings into use after restart
01057         thread_bootstrap_reset_restart(interface_id);
01058     }
01059 
01060     return ret;
01061 #else
01062     (void) interface_id;
01063     (void) additional_ptr;
01064     (void) additional_len;
01065     return -1;
01066 #endif
01067 }
01068 
01069 int thread_management_link_configuration_delete(int8_t interface_id)
01070 {
01071 #ifdef HAVE_THREAD
01072     int ret = thread_joiner_application_link_configuration_delete(interface_id);
01073 
01074     if (interface_id == -1) {
01075         return ret;
01076     }
01077 
01078     if (ret >= 0) {
01079         protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01080         if (!cur  || !cur->thread_info) {
01081             return -2;
01082         }
01083         if ((cur->lowpan_info & INTERFACE_NWK_ACTIVE) !=  0) {
01084             thread_bootstrap_reset_restart(interface_id);
01085         }
01086     }
01087     return ret;
01088 #else
01089     (void) interface_id;
01090     return -1;
01091 #endif
01092 }
01093 
01094 int thread_management_get_leader_address(int8_t interface_id, uint8_t *address_buffer)
01095 {
01096 #ifdef HAVE_THREAD
01097 
01098     protocol_interface_info_entry_t *cur;
01099 
01100     cur = protocol_stack_interface_info_get_by_id(interface_id);
01101     if (cur) {
01102         if ((cur->thread_info) && (thread_attach_ready(cur) == 0)  &&
01103                 (cur->thread_info->threadPrivatePrefixInfo.ulaValid)) {
01104             thread_addr_write_mesh_local_16(address_buffer, thread_router_addr_from_id(cur->thread_info->thread_leader_data->leaderRouterId), cur->thread_info);
01105             return 0;
01106         }
01107     }
01108     return -1;
01109 #else
01110     (void) interface_id;
01111     (void) address_buffer;
01112     return -1;
01113 #endif
01114 }
01115 
01116 int thread_management_get_leader_aloc(int8_t interface_id, uint8_t *address_buffer)
01117 {
01118 #ifdef HAVE_THREAD
01119 
01120     protocol_interface_info_entry_t *cur;
01121 
01122     cur = protocol_stack_interface_info_get_by_id(interface_id);
01123     if (cur) {
01124         if ((cur->thread_info) && (thread_attach_ready(cur) == 0)  &&
01125                 (cur->thread_info->threadPrivatePrefixInfo.ulaValid)) {
01126             thread_addr_write_mesh_local_16(address_buffer, 0xfc00, cur->thread_info);
01127             return 0;
01128         }
01129     }
01130     return -1;
01131 #else
01132     (void) interface_id;
01133     (void) address_buffer;
01134     return -1;
01135 #endif
01136 }
01137 int thread_management_get_ml64_address(int8_t interface_id, uint8_t *address_ptr)
01138 {
01139 #ifdef HAVE_THREAD
01140     protocol_interface_info_entry_t *cur;
01141     cur = protocol_stack_interface_info_get_by_id(interface_id);
01142     if (!cur) {
01143         return -1;
01144     }
01145 
01146     if (!address_ptr) {
01147         return -1;
01148     }
01149 
01150     if (0 != thread_management_get_ml_prefix(interface_id, address_ptr)) {
01151         return -2;
01152     }
01153 
01154     memcpy(&address_ptr[8], cur->iid_slaac, 8);
01155     return 0;
01156 #else
01157     (void) interface_id;
01158     (void) address_ptr;
01159     return -1;
01160 #endif
01161 }
01162 
01163 int thread_management_get_ml16_address(int8_t interface_id, uint8_t *address_ptr)
01164 {
01165 #ifdef HAVE_THREAD
01166     if (!address_ptr) {
01167         return -1;
01168     }
01169 
01170     if (0 != thread_management_get_ml_prefix(interface_id, address_ptr)) {
01171         return -2;
01172     }
01173 
01174     if (0 != thread_management_get_my_iid16(interface_id, address_ptr + 8)) {
01175         return -2;
01176     }
01177 
01178     return 0;
01179 #else
01180     (void) interface_id;
01181     (void) address_ptr;
01182     return -1;
01183 #endif
01184 }
01185 
01186 int thread_management_get_parent_address(int8_t interface_id, uint8_t *address_ptr)
01187 {
01188 #ifdef HAVE_THREAD
01189     protocol_interface_info_entry_t *cur;
01190     cur = protocol_stack_interface_info_get_by_id(interface_id);
01191 
01192     if (!cur || !cur->thread_info || !address_ptr) {
01193         return -1;
01194     }
01195     memset(address_ptr, 0, 16);
01196     if (cur->thread_info->thread_endnode_parent) {
01197         memcpy(address_ptr, ADDR_LINK_LOCAL_PREFIX, 8);
01198         address_ptr += 8;
01199         memcpy(address_ptr, cur->thread_info->thread_endnode_parent->mac64, 8);
01200         *address_ptr ^= 2;
01201     }
01202 
01203     return 0;
01204 #else
01205     (void) interface_id;
01206     (void) address_ptr;
01207     return -1;
01208 #endif
01209 }
01210 
01211 int thread_management_get_commissioner_address(int8_t interface_id, uint8_t *address_ptr, uint16_t *port_ptr)
01212 {
01213 #ifdef HAVE_THREAD
01214     protocol_interface_info_entry_t *cur;
01215     cur = protocol_stack_interface_info_get_by_id(interface_id);
01216 
01217     if (!cur || !cur->thread_info || !address_ptr) {
01218         return -1;
01219     }
01220 
01221     if (!cur->thread_info->registered_commissioner.commissioner_valid) {
01222         return -2;
01223     }
01224     memcpy(address_ptr, cur->thread_info->threadPrivatePrefixInfo.ulaPrefix, 8);
01225     memcpy(address_ptr + 8, ADDR_SHORT_ADR_SUFFIC, 6);
01226     common_write_16_bit(0xfc30 + (cur->thread_info->registered_commissioner.session_id % 8), address_ptr + 14);
01227 
01228     if (port_ptr) {
01229         *port_ptr = THREAD_MANAGEMENT_PORT;// Default commissioner port
01230     }
01231 
01232     return 0;
01233 #else
01234     (void) interface_id;
01235     (void) address_ptr;
01236     (void) port_ptr;
01237     return -1;
01238 #endif
01239 }
01240 int8_t thread_management_set_link_timeout(int8_t interface_id, uint32_t link_timeout)
01241 {
01242 #ifdef HAVE_THREAD
01243     protocol_interface_info_entry_t *cur;
01244 
01245     cur = protocol_stack_interface_info_get_by_id(interface_id);
01246     if (!cur) {
01247         tr_warn("Invalid interface id");
01248         return -1;
01249     }
01250     thread_info_t *thread = cur->thread_info;
01251     if (!thread) {
01252         tr_warn("Thread not active");
01253         return -2;
01254     }
01255     tr_info("set new link timeout %"PRIu32" , old value %"PRIu32"", link_timeout, thread->host_link_timeout);
01256     thread->host_link_timeout = link_timeout;
01257     thread_bootstrap_child_update_trig(cur);
01258     return 0;
01259 #else
01260     (void) interface_id;
01261     (void) link_timeout;
01262     return -1;
01263 #endif
01264 }
01265 
01266 int8_t thread_management_get_link_timeout(int8_t interface_id, uint32_t *link_timeout)
01267 {
01268 #ifdef HAVE_THREAD
01269     const protocol_interface_info_entry_t *cur;
01270 
01271     if (!link_timeout) {
01272         tr_warn("Invalid input ptr");
01273         return -3;
01274     }
01275     cur = protocol_stack_interface_info_get_by_id(interface_id);
01276     if (!cur) {
01277         tr_warn("Invalid interface id");
01278         return -1;
01279     }
01280     const thread_info_t *thread = cur->thread_info;
01281     if (!thread) {
01282         tr_warn("Thread not active");
01283         return -2;
01284     }
01285     *link_timeout = thread->host_link_timeout;
01286     return 0;
01287 #else
01288     (void) interface_id;
01289     (void) link_timeout;
01290     return -1;
01291 #endif
01292 }
01293 
01294 int8_t thread_management_set_request_full_nwk_data(int8_t interface_id, bool full_nwk_data)
01295 {
01296 #ifdef HAVE_THREAD
01297     protocol_interface_info_entry_t *cur;
01298     cur = protocol_stack_interface_info_get_by_id(interface_id);
01299     if (!cur) {
01300         tr_warn("Invalid interface id");
01301         return -1;
01302     }
01303     if (!cur->thread_info) {
01304         tr_warn("Thread not active");
01305         return -2;
01306     }
01307     if (cur->thread_info->requestFullNetworkData != full_nwk_data) {
01308         cur->thread_info->requestFullNetworkData = full_nwk_data;
01309         thread_bootstrap_child_update_trig(cur);
01310     }
01311     return 0;
01312 #else
01313     (void) interface_id;
01314     (void) full_nwk_data;
01315     return -1;
01316 #endif
01317 }
01318 
01319 int8_t thread_management_get_request_full_nwk_data(int8_t interface_id, bool *full_nwk_data)
01320 {
01321 #ifdef HAVE_THREAD
01322     const protocol_interface_info_entry_t *cur;
01323 
01324     if (!full_nwk_data) {
01325         tr_warn("Invalid input ptr");
01326         return -3;
01327     }
01328     cur = protocol_stack_interface_info_get_by_id(interface_id);
01329     if (!cur) {
01330         tr_warn("Invalid interface id");
01331         return -1;
01332     }
01333     if (!cur->thread_info) {
01334         tr_warn("Thread not active");
01335         return -2;
01336     }
01337     *full_nwk_data = cur->thread_info->requestFullNetworkData;
01338     return 0;
01339 #else
01340     (void) interface_id;
01341     (void) full_nwk_data;
01342     return -1;
01343 #endif
01344 }
01345 
01346 int thread_management_device_certificate_set(int8_t interface_id, const unsigned char *device_certificate_ptr, uint16_t device_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
01347 {
01348     (void) device_certificate_ptr;
01349     (void) device_certificate_len;
01350     (void) priv_key_ptr;
01351     (void) priv_key_len;
01352 
01353 #ifdef HAVE_THREAD
01354     protocol_interface_info_entry_t *cur;
01355 
01356     cur = protocol_stack_interface_info_get_by_id(interface_id);
01357     if (!cur) {
01358         tr_warn("invalid interface id");
01359         return -1;
01360     }
01361 
01362     return thread_ccm_device_certificate_set(cur, device_certificate_ptr, device_certificate_len, priv_key_ptr, priv_key_len);
01363 
01364 #else
01365     (void) interface_id;
01366     return -1;
01367 #endif
01368 }
01369 int thread_management_network_certificate_set(int8_t interface_id, const unsigned char *network_certificate_ptr, uint16_t network_certificate_len, const unsigned char *priv_key_ptr, uint16_t priv_key_len)
01370 {
01371     (void) network_certificate_ptr;
01372     (void) network_certificate_len;
01373     (void) priv_key_ptr;
01374     (void) priv_key_len;
01375 
01376 #ifdef HAVE_THREAD
01377     protocol_interface_info_entry_t *cur;
01378     int ret_val;
01379 
01380     cur = protocol_stack_interface_info_get_by_id(interface_id);
01381     if (!cur) {
01382         tr_debug("invalid interface id");
01383         return -1;
01384     }
01385 
01386     ret_val = thread_ccm_network_certificate_set(cur, network_certificate_ptr, network_certificate_len);
01387     if (0 > ret_val) {
01388         return -1;
01389     }
01390 
01391     return thread_ccm_network_private_key_set(cur, priv_key_ptr, priv_key_len);
01392 #else
01393     (void) interface_id;
01394     return -1;
01395 #endif
01396 }
01397 
01398 int thread_management_partition_weighting_set(int8_t interface_id, uint8_t partition_weighting)
01399 {
01400 #ifdef HAVE_THREAD
01401     protocol_interface_info_entry_t *cur;
01402 
01403     cur = protocol_stack_interface_info_get_by_id(interface_id);
01404     if (!cur || !cur->thread_info) {
01405         tr_debug("Invalid interface id");
01406         return -1;
01407     }
01408 
01409     if (cur->thread_info->partition_weighting == partition_weighting) {
01410         return 0;
01411     }
01412 
01413     bool trig_network_scan = false;
01414     if (cur->thread_info->thread_leader_data) {
01415         if (cur->thread_info->thread_leader_data->weighting < partition_weighting) {
01416             trig_network_scan = true;
01417         }
01418     }
01419 
01420     cur->thread_info->partition_weighting = partition_weighting;
01421 
01422     if (cur->lowpan_info & INTERFACE_NWK_ACTIVE) {
01423         if (trig_network_scan && thread_common_ccm_enabled(cur)) {
01424             thread_nvm_store_link_info_clear();
01425             // bootstrap active and weighting has changed
01426             thread_bootstrap_reset_restart(interface_id);
01427         }
01428     }
01429 
01430     return 0;
01431 #else
01432     (void) interface_id;
01433     (void) partition_weighting;
01434     return -1;
01435 #endif
01436 }