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