takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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