EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

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