Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
thread_joiner_application.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 00030 00031 #include "nsconfig.h" 00032 #ifdef HAVE_THREAD 00033 #include <ns_types.h> 00034 #include "ns_list.h" 00035 #include "ns_trace.h" 00036 #include "nsdynmemLIB.h" 00037 #include "ns_nvm_helper.h" 00038 #include "randLIB.h" 00039 #include "common_functions.h" 00040 #include "thread_tmfcop_lib.h" 00041 #include "ns_sha256.h" 00042 00043 #include "NWK_INTERFACE/Include/protocol.h" 00044 #include "Service_Libs/blacklist/blacklist.h" 00045 00046 #include "coap_service_api.h" 00047 00048 #include "eventOS_event_timer.h" 00049 #include "thread_discovery.h" 00050 #include "thread_beacon.h" 00051 #include "thread_config.h" 00052 #include "thread_meshcop_lib.h" 00053 #include "thread_commissioning_if.h" 00054 #include "thread_management_if.h" 00055 #include "thread_common.h" 00056 #include "thread_bootstrap.h" 00057 #include "thread_network_synch.h" 00058 #include "thread_network_data_lib.h" 00059 #include "thread_joiner_application.h" 00060 #include "6LoWPAN/Thread/thread_extension_bootstrap.h" 00061 #include "mac_api.h" 00062 #include "6LoWPAN/MAC/mac_helper.h" 00063 #include "thread_nvm_store.h" 00064 #include "thread_management_internal.h" 00065 00066 #define TRACE_GROUP TRACE_GROUP_THREAD_JOINER_APPLICATION 00067 00068 /* List of active/pending configuration dataset TLVs*/ 00069 const uint8_t mle_pending_configuration_dataset_tlvs[] = { 00070 MESHCOP_TLV_ACTIVE_TIME_STAMP, 00071 MESHCOP_TLV_NETWORK_NAME, 00072 MESHCOP_TLV_PANID, 00073 MESHCOP_TLV_CHANNEL, 00074 MESHCOP_TLV_CHANNEL_MASK, 00075 MESHCOP_TLV_XPANID, 00076 MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 00077 MESHCOP_TLV_NETWORK_MASTER_KEY, 00078 MESHCOP_TLV_PSKC, 00079 MESHCOP_TLV_SECURITY_POLICY}; 00080 00081 const uint8_t pending_configuration_dataset_tlvs[] = { 00082 MESHCOP_TLV_PENDING_TIMESTAMP, 00083 MESHCOP_TLV_ACTIVE_TIME_STAMP, 00084 MESHCOP_TLV_NETWORK_NAME, 00085 MESHCOP_TLV_PANID, 00086 MESHCOP_TLV_CHANNEL, 00087 MESHCOP_TLV_CHANNEL_MASK, 00088 MESHCOP_TLV_XPANID, 00089 MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 00090 MESHCOP_TLV_NETWORK_MASTER_KEY, 00091 MESHCOP_TLV_PSKC, 00092 MESHCOP_TLV_SECURITY_POLICY}; 00093 00094 const uint8_t active_configuration_dataset_tlvs[] = { 00095 MESHCOP_TLV_ACTIVE_TIME_STAMP, 00096 MESHCOP_TLV_NETWORK_NAME, 00097 MESHCOP_TLV_PANID, 00098 MESHCOP_TLV_CHANNEL, 00099 MESHCOP_TLV_CHANNEL_MASK, 00100 MESHCOP_TLV_XPANID, 00101 MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 00102 MESHCOP_TLV_NETWORK_MASTER_KEY, 00103 MESHCOP_TLV_PSKC, 00104 MESHCOP_TLV_SECURITY_POLICY}; 00105 00106 const uint8_t mle_active_configuration_dataset_tlvs[] = { 00107 MESHCOP_TLV_NETWORK_NAME, 00108 MESHCOP_TLV_PANID, 00109 MESHCOP_TLV_CHANNEL, 00110 MESHCOP_TLV_CHANNEL_MASK, 00111 MESHCOP_TLV_XPANID, 00112 MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 00113 MESHCOP_TLV_NETWORK_MASTER_KEY, 00114 MESHCOP_TLV_PSKC, 00115 MESHCOP_TLV_SECURITY_POLICY}; 00116 00117 const uint8_t entrust_dataset_tlvs[] = { 00118 MESHCOP_TLV_ACTIVE_TIME_STAMP, 00119 MESHCOP_TLV_NETWORK_NAME, 00120 MESHCOP_TLV_CHANNEL_MASK,// Missing specification 00121 MESHCOP_TLV_XPANID, 00122 MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 00123 MESHCOP_TLV_NETWORK_MASTER_KEY, 00124 MESHCOP_TLV_PSKC, 00125 MESHCOP_TLV_SECURITY_POLICY, 00126 MESHCOP_TLV_NETWORK_KEY_SEQUENCE}; 00127 00128 const uint8_t meshcop_pending_set_ignore[] = { 00129 MESHCOP_TLV_BORDER_ROUTER_LOCATOR, 00130 MESHCOP_TLV_COMMISSIONER_SESSION_ID, 00131 MESHCOP_TLV_PENDING_TIMESTAMP, 00132 MESHCOP_TLV_COMMISSIONER_ID, 00133 MESHCOP_TLV_STEERING_DATA, 00134 MESHCOP_TLV_DELAY_TIMER, 00135 MESHCOP_TLV_GET, 00136 MESHCOP_TLV_COMMISSIONER_UDP_PORT, 00137 MESHCOP_TLV_JOINER_UDP_PORT, 00138 MESHCOP_TLV_STATE, 00139 MESHCOP_TLV_NETWORK_KEY_SEQUENCE 00140 }; 00141 00142 const uint8_t meshcop_active_set_ignore[] = { 00143 MESHCOP_TLV_PENDING_TIMESTAMP, 00144 MESHCOP_TLV_COMMISSIONER_SESSION_ID, 00145 MESHCOP_TLV_COMMISSIONER_ID, 00146 MESHCOP_TLV_STEERING_DATA, 00147 MESHCOP_TLV_DELAY_TIMER, 00148 MESHCOP_TLV_NETWORK_KEY_SEQUENCE 00149 }; 00150 00151 const uint8_t mle_active_configuration_dataset_ignore_tlvs[] = { 00152 MESHCOP_TLV_ACTIVE_TIME_STAMP 00153 }; 00154 00155 const uint8_t mle_pending_configuration_dataset_ignore_tlvs[] = { 00156 MESHCOP_TLV_PENDING_TIMESTAMP 00157 }; 00158 00159 uint8_t mle_active_configuration_dataset_tlvs_size(void) 00160 { 00161 return sizeof(mle_active_configuration_dataset_tlvs); 00162 } 00163 00164 uint8_t active_configuration_dataset_tlvs_size(void) 00165 { 00166 return sizeof(active_configuration_dataset_tlvs); 00167 } 00168 00169 uint8_t mle_active_configuration_dataset_ignore_tlvs_size(void) 00170 { 00171 return sizeof(mle_active_configuration_dataset_ignore_tlvs); 00172 } 00173 00174 uint8_t mle_pending_configuration_dataset_ignore_tlvs_size(void) 00175 { 00176 return sizeof(mle_pending_configuration_dataset_ignore_tlvs); 00177 } 00178 00179 uint8_t mle_pending_configuration_dataset_tlvs_size(void) 00180 { 00181 return sizeof(mle_pending_configuration_dataset_tlvs); 00182 } 00183 uint8_t pending_configuration_dataset_tlvs_size(void) 00184 { 00185 return sizeof(pending_configuration_dataset_tlvs); 00186 } 00187 uint8_t entrust_dataset_tlvs_size(void) 00188 { 00189 return sizeof(entrust_dataset_tlvs); 00190 } 00191 #define MAX_OPERATIONAL_DATASET_SIZE 254 00192 00193 typedef struct { 00194 uint32_t timeout_in_ms; 00195 uint64_t timestamp; 00196 uint16_t length; 00197 uint8_t data[MAX_OPERATIONAL_DATASET_SIZE]; 00198 } configuration_set_t; 00199 00200 typedef struct { 00201 link_configuration_s *configuration_ptr; 00202 configuration_set_t *active_configuration_ptr; 00203 configuration_set_t *pending_configuration_ptr; 00204 configuration_set_t *old_active_configuration_ptr; 00205 configuration_set_t *next_active_configuration_ptr; 00206 configuration_set_t *next_pending_configuration_ptr; 00207 device_configuration_s *device_configuration_ptr; 00208 uint8_t parent_address[16]; 00209 uint16_t parent_port; 00210 thread_joiner_application_commission_done_cb *done_cb; 00211 timeout_t *attach_timeout; 00212 timeout_t *entrust_timeout; 00213 uint32_t provisioning_timeout; 00214 thread_provisioning_status_e provisioning_done; 00215 bool configuration_valid: 1; //TODO this should???? be put in link configuration 00216 bool finalisation_done: 1; 00217 bool nvm_link_configuration_load: 1; // load link configuration settings from NVM in restart 00218 int8_t interface_id; 00219 int8_t coap_service_id; 00220 int8_t secure_coap_service_id; 00221 bool pending_set_in_sync:1; 00222 ns_list_link_t link; 00223 } thread_joiner_t; 00224 00225 00226 static NS_LIST_DEFINE(instance_list, thread_joiner_t, link); 00227 00228 static int thread_joiner_application_nvm_link_config_read(thread_joiner_t *this); 00229 static bool thread_joiner_application_validate_settings(thread_joiner_t *this); 00230 static uint8_t *thread_joiner_application_write_channel(uint8_t *ptr, uint16_t data); 00231 00232 static int stringlen(const char *s, int n) 00233 { 00234 char *end = memchr(s, 0, n); 00235 return end?end-s:n; 00236 } 00237 00238 static char *str_dub(char *str) 00239 { 00240 char *result_ptr = NULL; 00241 if (str) { 00242 result_ptr = ns_dyn_mem_alloc(strlen(str) + 1); 00243 if(result_ptr) { 00244 strcpy(result_ptr,str); 00245 } 00246 } 00247 return result_ptr; 00248 } 00249 00250 static thread_joiner_t *thread_joiner_find(int8_t interface_id) 00251 { 00252 thread_joiner_t *this = NULL; 00253 ns_list_foreach(thread_joiner_t, cur_ptr, &instance_list) { 00254 if (cur_ptr->interface_id == interface_id) { 00255 this = cur_ptr; 00256 break; 00257 } 00258 } 00259 return this; 00260 } 00261 00262 static thread_joiner_t *thread_joiner_find_by_service(int8_t service_id) 00263 { 00264 thread_joiner_t *this = NULL; 00265 ns_list_foreach(thread_joiner_t, cur_ptr, &instance_list) { 00266 if (cur_ptr->coap_service_id == service_id || cur_ptr->secure_coap_service_id == service_id) { 00267 this = cur_ptr; 00268 break; 00269 } 00270 } 00271 return this; 00272 } 00273 00274 static thread_joiner_t *thread_joiner_get(int8_t interface_id) 00275 { 00276 thread_joiner_t *this = thread_joiner_find(interface_id); 00277 if (!this) { 00278 this = ns_dyn_mem_alloc(sizeof(thread_joiner_t)); 00279 if(this){ 00280 memset(this, 0, sizeof(thread_joiner_t)); 00281 ns_list_add_to_start(&instance_list, this); 00282 this->interface_id = interface_id; 00283 this->provisioning_done = PROVISIONING_STATUS_DONE; // Default value for provisioning is done 00284 } 00285 } 00286 return this; 00287 } 00288 00289 static void thread_joiner_application_commission_clean(thread_joiner_t *this) 00290 { 00291 thread_commissioning_if_pairwise_key_delete_all(this->interface_id); 00292 memset(this->parent_address,0,16); 00293 this->parent_port = 0; 00294 coap_service_delete(this->secure_coap_service_id); 00295 coap_service_delete(this->coap_service_id); 00296 this->secure_coap_service_id = 0; 00297 this->coap_service_id = 0; 00298 eventOS_timeout_cancel(this->attach_timeout); 00299 eventOS_timeout_cancel(this->entrust_timeout); 00300 this->attach_timeout = NULL; 00301 this->entrust_timeout = NULL; 00302 } 00303 00304 //@TODO wrong place move these 00305 //@TODO Steering data is wrongly made it is not part of static configuration 00306 //@TODO PSKc is static data and should always be present not dynamic. 00307 static link_configuration_s *link_configuration_create(void) 00308 { 00309 link_configuration_s *this = ns_dyn_mem_alloc(sizeof(link_configuration_s)); 00310 if (!this) { 00311 return NULL; 00312 } 00313 memset(this, 0, sizeof(link_configuration_s)); 00314 this->securityPolicy = SECURITY_POLICY_ALL_SECURITY; // Set all default values ('1') for security policy flags 00315 return this; 00316 } 00317 00318 static void link_configuration_delete(link_configuration_s *this) 00319 { 00320 if (!this) { 00321 return; 00322 } 00323 ns_dyn_mem_free(this); 00324 } 00325 00326 static void link_configuration_copy(link_configuration_s *this, link_configuration_s *configuration_ptr) 00327 { 00328 if (!this || !configuration_ptr) { 00329 return; 00330 } 00331 memcpy(this->name, configuration_ptr->name, 16); 00332 memcpy(this->PSKc, configuration_ptr->PSKc, 16); 00333 memcpy(this->master_key, configuration_ptr->master_key, 16); 00334 memcpy(this->mesh_local_ula_prefix, configuration_ptr->mesh_local_ula_prefix, 8); 00335 memcpy(this->extented_pan_id, configuration_ptr->extented_pan_id, 8); 00336 memcpy(this->channel_mask, configuration_ptr->channel_mask,5); 00337 this->key_rotation = configuration_ptr->key_rotation; 00338 this->key_sequence = configuration_ptr->key_sequence; 00339 this->panId = configuration_ptr->panId; 00340 this->rfChannel = configuration_ptr->rfChannel; 00341 this->securityPolicy = configuration_ptr->securityPolicy; 00342 this->timestamp = configuration_ptr->timestamp; 00343 return; 00344 } 00345 static int link_configuration_update(link_configuration_s *link_configuration, uint8_t *msg_ptr, uint16_t msg_len) 00346 { 00347 uint8_t *ptr; 00348 uint16_t len; 00349 00350 if( !msg_ptr || !link_configuration ){ 00351 return -1; 00352 } 00353 len = thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_NETWORK_NAME, &ptr); 00354 if ( len > 0 ) { 00355 memset(link_configuration->name, 0, 16); 00356 memcpy(link_configuration->name, ptr, (len > 16) ? 16 : len); 00357 } 00358 00359 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_CHANNEL, &ptr) >= 3) { 00360 //channel_page = channel_ptr[0]; 00361 link_configuration->rfChannel = common_read_16_bit(&ptr[1]); 00362 } 00363 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_CHANNEL_MASK, &ptr) > 5) { 00364 //channel_page = channel_ptr[0]; 00365 if(ptr[0] == 0 && ptr[1] == 4) { 00366 link_configuration->channel_page = ptr[0]; 00367 memcpy(link_configuration->channel_mask,&ptr[2],4); 00368 } else { 00369 tr_warn("Invalid channel mask"); 00370 } 00371 } 00372 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_XPANID, &ptr) >= 8) { 00373 memcpy(link_configuration->extented_pan_id, ptr, 8); 00374 } 00375 00376 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr) >= 8) { 00377 memcpy(link_configuration->mesh_local_ula_prefix, ptr, 8); 00378 } 00379 00380 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_NETWORK_MASTER_KEY, &ptr) >= 16) { 00381 memcpy(link_configuration->master_key, ptr, 16); 00382 } 00383 00384 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &ptr) >= 8) { 00385 link_configuration->timestamp = common_read_64_bit(ptr); 00386 } 00387 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_PANID, &ptr) >= 2) { 00388 link_configuration->panId = common_read_16_bit(ptr); 00389 } 00390 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_PSKC, &ptr) >= 16) { 00391 memcpy(link_configuration->PSKc, ptr, 16); 00392 } 00393 00394 if (thread_meshcop_tlv_find(msg_ptr, msg_len, MESHCOP_TLV_SECURITY_POLICY, &ptr) >= 3) { 00395 link_configuration->securityPolicy = ptr[2]; 00396 link_configuration->key_rotation = common_read_16_bit(ptr); 00397 } 00398 00399 return 0; 00400 } 00401 00402 static void link_configuration_trace(link_configuration_s *this) 00403 { 00404 if (!this) { 00405 return; 00406 } 00407 tr_debug("NwkName: %s", trace_array(this->name, 16)); 00408 tr_debug("Mesh ula: %s", trace_array(this->mesh_local_ula_prefix, 8)); 00409 tr_debug("Extendend PanId: %s", trace_array(this->extented_pan_id, 8)); 00410 tr_debug("panid: %"PRIu16", Channel:%"PRIu16", keyRot:%"PRIu16", keySeq:%"PRIu32, this->panId, this->rfChannel, this->key_rotation, this->key_sequence); 00411 return; 00412 } 00413 00414 static device_configuration_s *device_configuration_create(void) 00415 { 00416 device_configuration_s *this = ns_dyn_mem_alloc(sizeof(device_configuration_s)); 00417 if (!this) { 00418 return NULL; 00419 } 00420 memset(this, 0, sizeof(device_configuration_s)); 00421 return this; 00422 } 00423 00424 static void device_configuration_delete(device_configuration_s *this) 00425 { 00426 if (!this) { 00427 return; 00428 } 00429 ns_dyn_mem_free(this->PSKd_ptr); 00430 ns_dyn_mem_free(this->provisioning_uri_ptr); 00431 ns_dyn_mem_free(this->vendor_name_ptr); 00432 ns_dyn_mem_free(this->vendor_model_ptr); 00433 ns_dyn_mem_free(this->vendor_sw_version_ptr); 00434 ns_dyn_mem_free(this->vendor_data_ptr); 00435 ns_dyn_mem_free(this); 00436 } 00437 static void device_configuration_copy(device_configuration_s *this, device_configuration_s *configuration_ptr) 00438 { 00439 if (!this || !configuration_ptr) { 00440 return; 00441 } 00442 memcpy(this->eui64, configuration_ptr->eui64,8); 00443 memcpy(this->extended_random_mac, configuration_ptr->extended_random_mac,8); 00444 memcpy(this->mesh_local_eid, configuration_ptr->mesh_local_eid,8); 00445 memcpy(this->vendor_stack_version, configuration_ptr->vendor_stack_version,6); 00446 //TODO: count PSKc instead and use that 00447 if( configuration_ptr->PSKd_ptr && configuration_ptr->PSKd_len > 0 ){ 00448 this->PSKd_ptr = ns_dyn_mem_alloc(configuration_ptr->PSKd_len); 00449 if( this->PSKd_ptr ){ 00450 memcpy(this->PSKd_ptr, configuration_ptr->PSKd_ptr, configuration_ptr->PSKd_len); 00451 this->PSKd_len = configuration_ptr->PSKd_len; 00452 }else{ 00453 this->PSKd_len = 0; 00454 } 00455 } 00456 00457 this->provisioning_uri_ptr = str_dub(configuration_ptr->provisioning_uri_ptr); 00458 this->vendor_name_ptr = str_dub(configuration_ptr->vendor_name_ptr); 00459 this->vendor_model_ptr = str_dub(configuration_ptr->vendor_model_ptr); 00460 this->vendor_sw_version_ptr = str_dub(configuration_ptr->vendor_sw_version_ptr); 00461 00462 uint16_t vendor_data_len = configuration_ptr->vendor_data_len; 00463 00464 if(vendor_data_len) { 00465 if (vendor_data_len > 64) { 00466 vendor_data_len = 64; 00467 } 00468 this->vendor_data_ptr = ns_dyn_mem_alloc(vendor_data_len); 00469 if(this->vendor_data_ptr) { 00470 memcpy(this->vendor_data_ptr, configuration_ptr->vendor_data_ptr, vendor_data_len); 00471 this->vendor_data_len = vendor_data_len; 00472 } 00473 } 00474 return; 00475 } 00476 static void device_configuration_trace(device_configuration_s *this) 00477 { 00478 if (!this) { 00479 return; 00480 } 00481 tr_debug("Mesh local eid: %s", trace_array(this->mesh_local_eid, 8)); 00482 tr_debug("extended random: %s", trace_array(this->extended_random_mac, 8)); 00483 tr_debug("uri: %s", this->provisioning_uri_ptr ? this->provisioning_uri_ptr: "(none)"); 00484 tr_debug("name: %s", this->vendor_name_ptr); 00485 tr_debug("mode: %s", this->vendor_model_ptr); 00486 tr_debug("version: %s", this->vendor_sw_version_ptr); 00487 tr_debug("vendor data: %s", trace_array(this->vendor_data_ptr, this->vendor_data_len)); 00488 return; 00489 } 00490 00491 static void device_configuration_validate(device_configuration_s *this) 00492 { 00493 // Set defaults if not overridden by client 00494 if (!this->vendor_model_ptr) { 00495 this->vendor_model_ptr = str_dub(THREAD_VENDOR_MODEL); 00496 } 00497 if (!this->vendor_name_ptr) { 00498 this->vendor_name_ptr = str_dub(THREAD_VENDOR_NAME); 00499 } 00500 if (!this->vendor_sw_version_ptr) { 00501 this->vendor_sw_version_ptr = str_dub(THREAD_SW_VERSION); 00502 } 00503 if (memcmp(this->vendor_stack_version, "\0\0\0\0\0\0",6) == 0) { 00504 // Empty lets set defaults 00505 this->vendor_stack_version[0] = (uint8_t)(THREAD_ARM_OUI >> 16); 00506 this->vendor_stack_version[1] = (uint8_t)(THREAD_ARM_OUI >> 8); 00507 this->vendor_stack_version[2] = (uint8_t)(THREAD_ARM_OUI); 00508 this->vendor_stack_version[3] = (uint8_t)(THREAD_BUILD_NUMBER >> 4); 00509 this->vendor_stack_version[4] = (uint8_t)(((THREAD_BUILD_NUMBER & 0x0f) << 4) || THREAD_REVISION_NUMBER); 00510 this->vendor_stack_version[5] = (uint8_t)((THREAD_VERSION_MIN << 4) || THREAD_VERSION_MAJ); 00511 } 00512 } 00513 00514 static configuration_set_t *configuration_set_copy(configuration_set_t *source_ptr) 00515 { 00516 configuration_set_t *result_ptr; 00517 if (!source_ptr) { 00518 return NULL; 00519 } 00520 result_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 00521 if (!result_ptr) { 00522 return NULL; 00523 } 00524 memcpy(result_ptr->data,source_ptr->data,source_ptr->length); 00525 result_ptr->length = source_ptr->length; 00526 result_ptr->timeout_in_ms = source_ptr->timeout_in_ms; 00527 result_ptr->timestamp = source_ptr->timestamp; 00528 return result_ptr; 00529 } 00530 00531 static bool configuration_set_tlv_required(uint8_t tlv_id, const uint8_t *tlv_ptr, uint8_t tlv_len) 00532 { 00533 while(tlv_len) 00534 { 00535 if(tlv_ptr[tlv_len-- -1] == tlv_id) { 00536 return true; 00537 } 00538 } 00539 return false; 00540 } 00541 00542 static uint16_t configuration_set_length(configuration_set_t *config_ptr, const uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 00543 { 00544 const uint8_t *tlv_ptr; 00545 uint16_t tlv_len; 00546 int16_t result_len = 0; 00547 tlv_len = config_ptr->length; 00548 tlv_ptr = config_ptr->data; 00549 00550 while (tlv_ptr && tlv_len) { 00551 if ((!req_tlv_ptr || req_tlv_len == 0 || configuration_set_tlv_required(*tlv_ptr, req_tlv_ptr, req_tlv_len)) && 00552 !configuration_set_tlv_required(*tlv_ptr, ignored_tlv_ptr, ignored_tlv_len)){ 00553 int16_t required_len = thread_meshcop_tlv_length_required(tlv_ptr, tlv_len); 00554 if (required_len < 0) { 00555 return 0; 00556 } 00557 result_len += required_len; 00558 } 00559 tlv_ptr = thread_meshcop_tlv_get_next(tlv_ptr, &tlv_len); 00560 } 00561 00562 return result_len; 00563 } 00564 00565 static uint8_t *configuration_set_write(configuration_set_t *config_ptr, uint8_t *ptr, const uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 00566 { 00567 const uint8_t *tlv_ptr; 00568 uint16_t tlv_len; 00569 tlv_len = config_ptr->length; 00570 tlv_ptr = config_ptr->data; 00571 while (tlv_ptr && tlv_len) { 00572 if ((!req_tlv_ptr || req_tlv_len == 0 || configuration_set_tlv_required(*tlv_ptr, req_tlv_ptr, req_tlv_len)) && 00573 !configuration_set_tlv_required(*tlv_ptr, ignored_tlv_ptr,ignored_tlv_len)) { 00574 int16_t required_len = thread_meshcop_tlv_length_required(tlv_ptr,tlv_len); 00575 if (required_len < 0 || config_ptr->length + required_len > MAX_OPERATIONAL_DATASET_SIZE) { 00576 // Source configuration is corrupted or length exceeded 00577 return ptr; 00578 } 00579 memcpy(ptr,tlv_ptr,required_len); 00580 ptr += required_len; 00581 } 00582 tlv_ptr = thread_meshcop_tlv_get_next(tlv_ptr, &tlv_len); 00583 } 00584 return ptr; 00585 } 00586 00587 static uint8_t *configuration_set_add_fields(configuration_set_t *destination_ptr, const uint8_t *source_ptr, uint16_t source_len, const uint8_t *required_tlv_ptr, uint8_t required_tlv_len) 00588 { 00589 uint8_t *ptr; 00590 ptr = destination_ptr->data + destination_ptr->length; 00591 while (source_ptr && source_len) { 00592 if (configuration_set_tlv_required(*source_ptr, required_tlv_ptr, required_tlv_len)) { 00593 int16_t required_len = thread_meshcop_tlv_length_required(source_ptr,source_len); 00594 if (required_len < 0 || destination_ptr->length + required_len > MAX_OPERATIONAL_DATASET_SIZE) { 00595 // Source configuration is corrupted or length exceeded 00596 return ptr; 00597 } 00598 memcpy(ptr,source_ptr,required_len); 00599 destination_ptr->length += required_len; 00600 ptr += required_len; 00601 } 00602 source_ptr = thread_meshcop_tlv_get_next(source_ptr, &source_len); 00603 } 00604 return ptr; 00605 } 00606 static uint8_t *configuration_set_add_all_fields(configuration_set_t *destination_ptr, const uint8_t *source_ptr, uint16_t source_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 00607 { 00608 uint8_t *ptr; 00609 ptr = destination_ptr->data + destination_ptr->length; 00610 while (source_ptr && source_len) { 00611 if (!configuration_set_tlv_required(*source_ptr, ignored_tlv_ptr, ignored_tlv_len)) { 00612 int16_t required_len = thread_meshcop_tlv_length_required(source_ptr,source_len); 00613 if (required_len < 0 || destination_ptr->length + required_len > MAX_OPERATIONAL_DATASET_SIZE) { 00614 // Source configuration is corrupted or length exceeded 00615 return ptr; 00616 } 00617 memcpy(ptr,source_ptr,required_len); 00618 destination_ptr->length += required_len; 00619 ptr += required_len; 00620 } 00621 source_ptr = thread_meshcop_tlv_get_next(source_ptr, &source_len); 00622 } 00623 return ptr; 00624 } 00625 static void configuration_set_copy_missing(configuration_set_t *destination_ptr, configuration_set_t *source_ptr) 00626 { 00627 uint8_t *tlv_list_ptr; 00628 uint16_t tlv_list_len = 0; 00629 if (!source_ptr || !destination_ptr) { 00630 return; 00631 } 00632 thread_meshcop_tlv_list_generate(source_ptr->data, source_ptr->length,NULL, &tlv_list_len); 00633 if (tlv_list_len == 0){ 00634 return; 00635 } 00636 tlv_list_ptr = ns_dyn_mem_temporary_alloc(tlv_list_len); 00637 if (!tlv_list_ptr) { 00638 return; 00639 } 00640 thread_meshcop_tlv_list_generate(source_ptr->data, source_ptr->length,tlv_list_ptr, &tlv_list_len); 00641 tr_debug("list in source: %s",trace_array(tlv_list_ptr,tlv_list_len)); 00642 00643 for(uint8_t n = 0;n < tlv_list_len;n++) { 00644 if(thread_meshcop_tlv_exist(destination_ptr->data, destination_ptr->length, tlv_list_ptr[n])){ 00645 // Depending specification 0 length TLVs from source should be also removed 00646 tlv_list_len = thread_meshcop_tlv_list_remove(tlv_list_ptr,tlv_list_len,tlv_list_ptr[n]); 00647 n--; // When we remove item from list we stay put 00648 } 00649 } 00650 if (tlv_list_len == 0) { 00651 // All mandatory TLVs present 00652 ns_dyn_mem_free(tlv_list_ptr); 00653 return; 00654 } 00655 tr_debug("mandatory TLVs needed: %s",trace_array(tlv_list_ptr,tlv_list_len)); 00656 configuration_set_add_fields(destination_ptr, source_ptr->data, source_ptr->length, tlv_list_ptr, tlv_list_len); 00657 ns_dyn_mem_free(tlv_list_ptr); 00658 } 00659 static void configuration_set_remove_null_tlv(configuration_set_t *configuration_ptr) 00660 { 00661 uint8_t *ptr; 00662 uint8_t *next_ptr; 00663 uint16_t length; 00664 if (!configuration_ptr) { 00665 return; 00666 } 00667 length = configuration_ptr->length; 00668 ptr = configuration_ptr->data; 00669 00670 do { 00671 if(thread_meshcop_tlv_length(ptr,length) == 0){ 00672 // remove this TLV 00673 configuration_ptr->length -= thread_meshcop_tlv_length_required(ptr,length); 00674 next_ptr = (uint8_t*)thread_meshcop_tlv_get_next(ptr,&length); 00675 if (next_ptr) { 00676 memmove(ptr,next_ptr,length); 00677 } 00678 } else { 00679 ptr = (uint8_t*)thread_meshcop_tlv_get_next(ptr,&length); 00680 } 00681 00682 } while (ptr && length); 00683 return; 00684 } 00685 00686 static void configuration_set_copy_mandatory(configuration_set_t *destination_ptr, configuration_set_t *source_ptr) 00687 { 00688 uint8_t tlv_list[sizeof(active_configuration_dataset_tlvs)]; 00689 uint16_t tlv_list_len = sizeof(active_configuration_dataset_tlvs); 00690 if (!source_ptr || !destination_ptr) { 00691 return; 00692 } 00693 memcpy(tlv_list,active_configuration_dataset_tlvs, sizeof(active_configuration_dataset_tlvs)); 00694 00695 for(uint8_t n = 0;n < sizeof(active_configuration_dataset_tlvs);n++) { 00696 if(0 < thread_meshcop_tlv_find(destination_ptr->data, destination_ptr->length, active_configuration_dataset_tlvs[n], NULL)){ 00697 // Depending specification 0 length TLVs from source should be also removed 00698 tlv_list_len = thread_meshcop_tlv_list_remove(tlv_list,tlv_list_len,active_configuration_dataset_tlvs[n]); 00699 } 00700 } 00701 if (tlv_list_len == 0) { 00702 // All mandatory TLVs present 00703 return; 00704 } 00705 tr_debug("mandatory TLVs needed: %s",trace_array(tlv_list,tlv_list_len)); 00706 configuration_set_add_fields(destination_ptr, source_ptr->data, source_ptr->length, tlv_list, tlv_list_len); 00707 } 00708 static void configuration_set_generate(configuration_set_t *destination_ptr, link_configuration_s *configuration_ptr) 00709 { 00710 uint8_t *response_ptr; 00711 00712 if (!destination_ptr || !configuration_ptr) { 00713 return; 00714 } 00715 response_ptr = destination_ptr->data; 00716 00717 response_ptr = thread_joiner_application_write_channel(response_ptr, configuration_ptr->rfChannel); 00718 *response_ptr++ = MESHCOP_TLV_CHANNEL_MASK; // type 00719 *response_ptr++ = 6; // length 00720 *response_ptr++ = configuration_ptr->channel_page; // channel page 00721 *response_ptr++ = 4; // channel mask length 00722 memcpy(response_ptr,configuration_ptr->channel_mask,4); 00723 response_ptr += 4; 00724 response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_XPANID, 8, configuration_ptr->extented_pan_id); 00725 response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, 8, configuration_ptr->mesh_local_ula_prefix); 00726 response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_NETWORK_MASTER_KEY, 16, configuration_ptr->master_key); 00727 response_ptr = thread_tmfcop_tlv_data_write_uint16(response_ptr, MESHCOP_TLV_PANID, configuration_ptr->panId); 00728 response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_PSKC, 16, configuration_ptr->PSKc); 00729 response_ptr = thread_tmfcop_tlv_data_write(response_ptr, MESHCOP_TLV_NETWORK_NAME, stringlen((char*)&configuration_ptr->name, 16), configuration_ptr->name); 00730 *response_ptr++ = MESHCOP_TLV_SECURITY_POLICY; // type 00731 *response_ptr++ = 3; // length 00732 response_ptr = common_write_16_bit(configuration_ptr->key_rotation,response_ptr); 00733 *response_ptr++ = configuration_ptr->securityPolicy; 00734 response_ptr = thread_tmfcop_tlv_data_write_uint64(response_ptr, MESHCOP_TLV_ACTIVE_TIME_STAMP, configuration_ptr->timestamp); 00735 00736 destination_ptr->length = response_ptr - destination_ptr->data; 00737 } 00738 00739 static bool configuration_set_validate(uint8_t *configuration_set, uint16_t configuration_set_len, bool make_full_validation) 00740 { 00741 if (thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_NETWORK_MASTER_KEY, NULL) < 16 || 00742 thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, NULL) < 8 || 00743 thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_XPANID, NULL) < 8 || 00744 thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_NETWORK_NAME, NULL) == 0 || 00745 thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_PSKC, NULL) < 16 ) { 00746 // Absolutely minimum we must have is master secret to attach. 00747 // If commissioner wants to be connected we must have PSKc,Name,Xpanid 00748 // If there is some fields missing we could attach, but timestamp must be set to 0 which will then cause synchronization 00749 tr_debug("Not all TLv's included"); 00750 return false; 00751 } 00752 00753 if (make_full_validation) { 00754 if ((thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_CHANNEL, NULL) == 0) || 00755 (thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_PANID, NULL) == 0) || 00756 (thread_meshcop_tlv_find(configuration_set, configuration_set_len, MESHCOP_TLV_XPANID, NULL) == 0)) { 00757 tr_debug("Not all TLv's included"); 00758 return false; 00759 } 00760 } 00761 return true; 00762 } 00763 00764 static bool thread_joiner_application_validate_settings(thread_joiner_t *this) 00765 { 00766 bool new_value_generated=0; 00767 if (memcmp(this->device_configuration_ptr->extended_random_mac,ADDR_UNSPECIFIED, 8) == 0) { 00768 randLIB_get_n_bytes_random(this->device_configuration_ptr->extended_random_mac, 8); 00769 this->device_configuration_ptr->extended_random_mac[0] |= 2; //Set Local Bit 00770 this->device_configuration_ptr->extended_random_mac[0] &= ~1; //Clear multicast bit 00771 new_value_generated = 1; 00772 tr_info("Generating Random MAC"); 00773 } 00774 while (addr_iid_reserved(this->device_configuration_ptr->mesh_local_eid) || 00775 memcmp(this->device_configuration_ptr->mesh_local_eid, ADDR_SHORT_ADR_SUFFIC,6) == 0 ) { 00776 // addr_iid_reserved checks the all zeroes case. 00777 randLIB_get_n_bytes_random(this->device_configuration_ptr->mesh_local_eid, 8); 00778 new_value_generated = 1; 00779 tr_info("Generating Random ML-EID"); 00780 } 00781 if (this->configuration_ptr->key_rotation < 3600) { 00782 this->configuration_ptr->key_rotation = 3600; 00783 } 00784 return new_value_generated; 00785 } 00786 00787 int thread_joiner_application_init(int8_t interface_id, device_configuration_s *device_configuration_ptr, link_configuration_s *default_configuration_ptr) 00788 { 00789 thread_joiner_t *this; 00790 uint8_t pskd_len; 00791 00792 if ( !device_configuration_ptr ) { 00793 return -1; 00794 } 00795 pskd_len = device_configuration_ptr->PSKd_len; 00796 00797 if (pskd_len > 32 || pskd_len < 6 ) { 00798 return -2; 00799 } 00800 00801 this = thread_joiner_get(interface_id); 00802 if (!this) { 00803 return -3; 00804 } 00805 00806 if ( !this->device_configuration_ptr ) { 00807 this->device_configuration_ptr = device_configuration_create(); 00808 } 00809 if ( !this->device_configuration_ptr ) { 00810 tr_error("Joiner Device creation failed"); 00811 return -4; 00812 } 00813 device_configuration_copy(this->device_configuration_ptr, device_configuration_ptr); 00814 device_configuration_validate(this->device_configuration_ptr); // Set defaults if missing 00815 device_configuration_trace(this->device_configuration_ptr); 00816 if (memcmp(this->device_configuration_ptr->eui64, "\0\0\0\0\0\0\0\0",8) == 0) { 00817 //EUI64 is not set we then read that from Radio 00818 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00819 00820 if (cur && cur->mac_api) { 00821 cur->mac_api->mac64_get(cur->mac_api,MAC_EXTENDED_READ_ONLY, this->device_configuration_ptr->eui64); 00822 } 00823 } 00824 // Adding entropy for our random seed 00825 randLIB_add_seed(common_read_64_bit(this->device_configuration_ptr->eui64)); 00826 00827 // create link configuration, could be replaced by configuration settings read from NVM 00828 if (!this->configuration_ptr) { 00829 this->configuration_ptr = link_configuration_create(); 00830 } 00831 this->configuration_valid = false; 00832 00833 if (!this->configuration_ptr) { 00834 tr_error("Joiner creation failed"); 00835 device_configuration_delete(this->device_configuration_ptr); 00836 return -4; 00837 } 00838 if(!this->active_configuration_ptr){ 00839 this->active_configuration_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 00840 } 00841 if (!this->active_configuration_ptr) { 00842 tr_error("Active configuration creation failed"); 00843 device_configuration_delete(this->device_configuration_ptr); 00844 link_configuration_delete(this->configuration_ptr); 00845 return -5; 00846 } 00847 memset(this->active_configuration_ptr, 0, sizeof(configuration_set_t)); 00848 00849 if (default_configuration_ptr) { 00850 link_configuration_copy(this->configuration_ptr, default_configuration_ptr); 00851 thread_joiner_application_validate_settings(this);// Generate all random information 00852 if( memcmp(this->configuration_ptr->master_key,ADDR_UNSPECIFIED ,16) != 0 || 00853 memcmp(this->configuration_ptr->PSKc,ADDR_UNSPECIFIED ,16) != 0 ) { 00854 //If no master key or PSKc set we assume not valid configuration for thread network others may be possible to be 0 00855 //This allows some configurations to be set statically for testing purposes 00856 this->configuration_valid = true; 00857 configuration_set_generate(this->active_configuration_ptr, this->configuration_ptr); 00858 } 00859 } 00860 // Always load link configuration from bootstrap state machine. NVM overrides Static configuration 00861 this->nvm_link_configuration_load = true; 00862 00863 link_configuration_trace(this->configuration_ptr); 00864 00865 return 0; 00866 } 00867 00868 int thread_joiner_application_form_network(int8_t interface_id, uint8_t *commissioning_credentials_ptr, char *name_ptr) 00869 { 00870 thread_joiner_t *this = thread_joiner_find(interface_id); 00871 (void)commissioning_credentials_ptr; 00872 (void)name_ptr; 00873 tr_debug("Joiner form random network"); 00874 if (!this) { 00875 return -1; 00876 } 00877 /* 00878 * TODO generate random network parameter and enable commissioner to join the network 00879 */ 00880 00881 return 0; 00882 } 00883 00884 void thread_joiner_application_deinit(int8_t interface_id) 00885 { 00886 thread_joiner_t *this = thread_joiner_find(interface_id); 00887 if (this) { 00888 ns_list_remove(&instance_list, this); 00889 link_configuration_delete(this->configuration_ptr); 00890 device_configuration_delete(this->device_configuration_ptr); 00891 if (this->pending_configuration_ptr) { 00892 ns_dyn_mem_free(this->pending_configuration_ptr); 00893 } 00894 if (this->next_pending_configuration_ptr) { 00895 ns_dyn_mem_free(this->next_pending_configuration_ptr); 00896 } 00897 if (this->active_configuration_ptr) { 00898 ns_dyn_mem_free(this->active_configuration_ptr); 00899 } 00900 if (this->old_active_configuration_ptr) { 00901 ns_dyn_mem_free(this->old_active_configuration_ptr); 00902 } 00903 ns_dyn_mem_free(this); 00904 } 00905 } 00906 00907 link_configuration_s *thread_joiner_application_get_config(int8_t interface_id) 00908 { 00909 thread_joiner_t *this = thread_joiner_find(interface_id); 00910 if (!this) { 00911 return NULL; 00912 } 00913 00914 if (this->configuration_valid == false) { 00915 return NULL; 00916 } 00917 return this->configuration_ptr; 00918 } 00919 00920 uint8_t *thread_joiner_application_network_name_get(int8_t interface_id) 00921 { 00922 thread_joiner_t *this = thread_joiner_find(interface_id); 00923 if (!this) { 00924 return NULL; 00925 } 00926 return this->configuration_ptr->name; 00927 } 00928 00929 static int thread_joiner_application_nvm_link_config_read(thread_joiner_t *this) { 00930 00931 // read config from NVM, in case of failure current settings are unchanged. 00932 int nvm_read_status = thread_nvm_store_active_configuration_read(this->active_configuration_ptr, sizeof(configuration_set_t)); 00933 tr_debug("active conf read %d", nvm_read_status); 00934 // validate that active configuration settings are valid, even if we couldn't read from nvm. 00935 if(!configuration_set_validate(this->active_configuration_ptr->data, this->active_configuration_ptr->length, true)) { 00936 tr_debug("No active configuration avail"); 00937 return -1; 00938 } 00939 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 00940 00941 thread_nvm_fast_data_t fast_data; 00942 memset(&fast_data,0,sizeof(thread_nvm_fast_data_t)); 00943 int fast_data_read_ret = thread_nvm_store_fast_data_read(&fast_data); 00944 tr_info("From NVM %d", fast_data_read_ret); 00945 tr_info("mac-counter %"PRIu32,fast_data.mac_frame_counter); 00946 tr_info("mle-counter %"PRIu32,fast_data.mle_frame_counter); 00947 tr_info("seq-counter %"PRIu32,fast_data.seq_counter); 00948 00949 if (THREAD_NVM_FILE_SUCCESS == fast_data_read_ret) { 00950 if (this->configuration_ptr->key_sequence < fast_data.seq_counter) { 00951 this->configuration_ptr->key_sequence = fast_data.seq_counter; 00952 } 00953 } 00954 00955 fast_data.mac_frame_counter += MAC_FRAME_COUNTER_LIMIT; 00956 fast_data.mle_frame_counter += MLE_FRAME_COUNTER_LIMIT; 00957 thread_nvm_store_fast_data_write(&fast_data); 00958 00959 thread_nvm_store_device_configuration_read(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 00960 thread_nvm_store_link_info_read(); 00961 // Generate all random information, if device configuration read failed then the random mac and eid are created. 00962 bool new_value_generated = thread_joiner_application_validate_settings(this); 00963 if (new_value_generated) { 00964 thread_nvm_store_device_configuration_write(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 00965 } 00966 00967 this->configuration_valid = true; 00968 link_configuration_trace(this->configuration_ptr); 00969 00970 //Add Security to MLE service 00971 uint8_t key_material[32]; 00972 uint8_t key_index; 00973 //Define KEY's 00974 00975 thread_key_get(this->configuration_ptr->master_key, key_material, this->configuration_ptr->key_sequence); 00976 key_index = THREAD_KEY_INDEX(this->configuration_ptr->key_sequence); 00977 //Set Keys 00978 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00979 mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX); 00980 mle_service_security_set_security_key(this->interface_id, key_material, key_index, true); 00981 // update counters 00982 mle_service_security_set_frame_counter(this->interface_id, fast_data.mle_frame_counter); 00983 mac_helper_link_frame_counter_set(this->interface_id, fast_data.mac_frame_counter); 00984 00985 // this saves all configurations 00986 if (THREAD_NVM_FILE_SUCCESS!=nvm_read_status) { 00987 thread_joiner_application_configuration_nvm_save(this->interface_id); 00988 } 00989 else { 00990 tr_info("Reading pending set"); 00991 configuration_set_t *pend_conf_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 00992 if (pend_conf_ptr) { 00993 memset(pend_conf_ptr, 0, sizeof(configuration_set_t)); 00994 int pending_ret = thread_nvm_store_pending_configuration_read(pend_conf_ptr, sizeof(configuration_set_t)); 00995 if(THREAD_NVM_FILE_SUCCESS==pending_ret) { 00996 if (this->pending_configuration_ptr) { 00997 ns_dyn_mem_free(this->pending_configuration_ptr); 00998 } 00999 this->pending_configuration_ptr = pend_conf_ptr; 01000 this->pending_configuration_ptr->timeout_in_ms = 0; 01001 this->pending_set_in_sync = false; 01002 } 01003 else { 01004 tr_info("Reading pending from NVM error:%d", pending_ret); 01005 ns_dyn_mem_free(pend_conf_ptr); 01006 } 01007 } 01008 } 01009 this->nvm_link_configuration_load = false; 01010 return 0; 01011 } 01012 01013 static int thread_joiner_application_nvm_link_config_delete(thread_joiner_t *this) 01014 { 01015 if (!this) { 01016 return -1; 01017 } 01018 int ret = thread_nvm_store_pending_configuration_remove(); 01019 01020 if (ret!=THREAD_NVM_FILE_SUCCESS) { 01021 tr_error("Pending configuration delete error: %d", ret); 01022 } 01023 01024 ret = thread_nvm_store_active_configuration_remove(); 01025 01026 if (ret!=THREAD_NVM_FILE_SUCCESS) { 01027 tr_error("Active configuration delete error: %d", ret); 01028 } 01029 01030 // delete link configuration from cache, device will be restarted after settings are deleted 01031 this->configuration_valid = false; 01032 return 0; 01033 } 01034 01035 uint64_t thread_joiner_application_active_timestamp_get(int8_t interface_id) 01036 { 01037 thread_joiner_t *this = thread_joiner_find(interface_id); 01038 if (!this) { 01039 return 0; 01040 } 01041 01042 return this->configuration_ptr->timestamp; 01043 } 01044 01045 uint8_t thread_joiner_application_security_policy_get(int8_t interface_id) 01046 { 01047 thread_joiner_t *this = thread_joiner_find(interface_id); 01048 if (!this) { 01049 return 0; 01050 } 01051 01052 return this->configuration_ptr->securityPolicy; 01053 } 01054 01055 uint8_t *thread_joiner_application_random_mac_get(int8_t interface_id) 01056 { 01057 thread_joiner_t *this = thread_joiner_find(interface_id); 01058 if (!this || !this->device_configuration_ptr) { 01059 tr_error("thread_joiner_application_random_mac_get NULL parameter "); 01060 return (uint8_t*)ADDR_UNSPECIFIED; 01061 } 01062 return this->device_configuration_ptr->extended_random_mac; 01063 } 01064 uint8_t *thread_joiner_application_ml_eid_get(int8_t interface_id) 01065 { 01066 thread_joiner_t *this = thread_joiner_find(interface_id); 01067 if (!this || !this->device_configuration_ptr) { 01068 tr_error("thread_joiner_application_ml_eid_get parameter NULL"); 01069 return (uint8_t*)ADDR_UNSPECIFIED; 01070 } 01071 return this->device_configuration_ptr->mesh_local_eid; 01072 } 01073 void thread_joiner_application_active_timestamp_set(int8_t interface_id, uint64_t timestamp) 01074 { 01075 thread_joiner_t *this = thread_joiner_find(interface_id); 01076 uint8_t *timestamp_ptr = NULL; 01077 if (!this) { 01078 return; 01079 } 01080 01081 thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp_ptr); 01082 if (timestamp_ptr) { 01083 common_write_64_bit(timestamp,timestamp_ptr); 01084 } 01085 01086 //update timestamps in active configuration and link configuration 01087 this->active_configuration_ptr->timestamp = timestamp; 01088 this->configuration_ptr->timestamp = timestamp; 01089 return; 01090 } 01091 01092 void thread_joiner_pending_config_activate(int8_t interface_id) 01093 { 01094 thread_joiner_t *this = thread_joiner_find(interface_id); 01095 01096 if (!this || !this->pending_configuration_ptr) { 01097 tr_error("No pending configuration or joiner!"); 01098 return; 01099 } 01100 01101 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 01102 01103 if (!cur) { 01104 tr_error("No interface information!"); 01105 return; 01106 } 01107 01108 /* 01109 * If pending configuration active timestamp is lower than current active timestamp allow pending configuration activation only 01110 * if master key is changed by the pending set 01111 */ 01112 link_configuration_s *link_configuration = thread_joiner_application_get_config(interface_id); 01113 01114 if (!link_configuration) { 01115 return; 01116 } 01117 01118 // Validate new link configuration 01119 uint8_t *master_key_ptr = NULL; 01120 uint64_t pending_active_timestamp = 0; 01121 thread_meshcop_tlv_data_get_uint64(this->pending_configuration_ptr->data,this->pending_configuration_ptr->length,MESHCOP_TLV_ACTIVE_TIME_STAMP, &pending_active_timestamp); 01122 thread_meshcop_tlv_find(this->pending_configuration_ptr->data,this->pending_configuration_ptr->length,MESHCOP_TLV_NETWORK_MASTER_KEY,&master_key_ptr); 01123 01124 if ((pending_active_timestamp < thread_joiner_application_active_timestamp_get(interface_id))) { 01125 // If new active timestamp is older than current master key must be changed. 01126 if (!master_key_ptr || 01127 memcmp(master_key_ptr,link_configuration->master_key,16) == 0) { 01128 tr_info("*** Pending set activation aborted - device has newer active timestamp"); 01129 thread_joiner_application_pending_config_delete(interface_id); 01130 return; 01131 } 01132 } 01133 01134 if (master_key_ptr && memcmp(master_key_ptr,link_configuration->master_key,16) != 0) { 01135 this->configuration_ptr->key_sequence = 0; 01136 // if write fails, keep going... 01137 (void)thread_nvm_store_seq_counter_write(this->configuration_ptr->key_sequence); 01138 } 01139 01140 tr_info("*** Activating pending configuration."); 01141 01142 ns_dyn_mem_free(this->old_active_configuration_ptr); 01143 this->old_active_configuration_ptr = this->active_configuration_ptr; 01144 this->active_configuration_ptr = this->pending_configuration_ptr; 01145 this->active_configuration_ptr->timestamp = pending_active_timestamp; 01146 // All information is copied from old configuration so if configuration is corrupt we dont change anything. 01147 this->pending_configuration_ptr = NULL; 01148 (void)thread_nvm_store_pending_configuration_remove(); 01149 configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr); 01150 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01151 link_configuration_trace(this->configuration_ptr); 01152 01153 thread_joiner_application_configuration_nvm_save(this->interface_id); 01154 01155 01156 if (thread_link_configuration_activate(cur, this->configuration_ptr) != 0) { 01157 tr_error("Activating pending configuration failed."); 01158 } 01159 01160 tr_info("*** Activating pending configuration done."); 01161 } 01162 01163 01164 void thread_joiner_application_seconds_timer(int8_t interface_id, uint32_t seconds) 01165 { 01166 thread_joiner_t *this = thread_joiner_find(interface_id); 01167 //tr_debug("seconds tick for joiner pending timeout in %d",this->pending_timeout_in_ms); 01168 if (!this) { 01169 return; 01170 } 01171 if (this->provisioning_timeout) { 01172 if (this->provisioning_timeout < seconds) { 01173 this->provisioning_done = PROVISIONING_STATUS_NOT_DONE; 01174 } 01175 this->provisioning_timeout -= seconds; 01176 } 01177 if (!this->pending_configuration_ptr || this->pending_configuration_ptr->timeout_in_ms == 0) { 01178 return; 01179 } 01180 if (this->pending_configuration_ptr->timeout_in_ms > seconds*1000) { 01181 this->pending_configuration_ptr->timeout_in_ms -= seconds*1000; 01182 return; 01183 } 01184 // Activate the pending config 01185 thread_joiner_pending_config_activate(interface_id); 01186 } 01187 01188 int thread_joiner_application_pending_config_create(int8_t interface_id, uint8_t *data_ptr, uint16_t data_len) 01189 { 01190 thread_joiner_t *this = thread_joiner_find(interface_id); 01191 if (!this || data_len > MAX_OPERATIONAL_DATASET_SIZE) { 01192 return -1; 01193 } 01194 if(!this->pending_configuration_ptr){ 01195 this->pending_configuration_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 01196 } 01197 if (!this->pending_configuration_ptr) { 01198 tr_error("pending configuration creation failed"); 01199 return -2; 01200 } 01201 memset(this->pending_configuration_ptr, 0, sizeof(configuration_set_t)); 01202 configuration_set_add_all_fields(this->pending_configuration_ptr,data_ptr,data_len, meshcop_pending_set_ignore, sizeof(meshcop_pending_set_ignore)); 01203 return 0; 01204 } 01205 01206 bool thread_joiner_application_pending_config_exists(int8_t interface_id) 01207 { 01208 thread_joiner_t *this = thread_joiner_find(interface_id); 01209 if (!this || !this->pending_configuration_ptr) { 01210 return false; 01211 } 01212 return true; 01213 } 01214 01215 bool thread_joiner_application_pending_delay_timer_in_sync(int8_t interface_id) 01216 { 01217 thread_joiner_t *this = thread_joiner_find(interface_id); 01218 if (!this || !this->pending_configuration_ptr) { 01219 return false; 01220 } 01221 return this->pending_set_in_sync; 01222 } 01223 01224 uint64_t thread_joiner_application_pending_config_timestamp_get(int8_t interface_id) 01225 { 01226 thread_joiner_t *this = thread_joiner_find(interface_id); 01227 if (!this || !this->pending_configuration_ptr || !this->pending_set_in_sync) { 01228 return 0; 01229 } 01230 return this->pending_configuration_ptr->timestamp; 01231 } 01232 01233 int thread_joiner_application_pending_config_timestamp_set(int8_t interface_id, uint64_t timestamp) 01234 { 01235 thread_joiner_t *this = thread_joiner_find(interface_id); 01236 if (!this || !this->pending_configuration_ptr) { 01237 return -1; 01238 } 01239 this->pending_configuration_ptr->timestamp = timestamp; 01240 return 0; 01241 } 01242 01243 01244 int thread_joiner_application_pending_config_enable(int8_t interface_id, uint32_t timeout_in_ms) 01245 { 01246 thread_joiner_t *this = thread_joiner_find(interface_id); 01247 if (!this || !this->pending_configuration_ptr) { 01248 return -1; 01249 } 01250 this->pending_configuration_ptr->timeout_in_ms = timeout_in_ms; 01251 this->pending_set_in_sync = true; 01252 01253 if(this->pending_configuration_ptr->timeout_in_ms > THREAD_MAX_DELAY_TIMER_SECONDS*1000) { 01254 this->pending_configuration_ptr->timeout_in_ms = THREAD_MAX_DELAY_TIMER_SECONDS*1000; 01255 } 01256 thread_joiner_application_configuration_nvm_save(this->interface_id); 01257 01258 return 0; 01259 } 01260 01261 uint32_t thread_joiner_application_pending_config_timeout_get(int8_t interface_id) 01262 { 01263 thread_joiner_t *this = thread_joiner_find(interface_id); 01264 if (!this || !this->pending_configuration_ptr) { 01265 return 0; 01266 } 01267 return this->pending_configuration_ptr->timeout_in_ms; 01268 } 01269 01270 uint16_t thread_joiner_application_pending_config_length(uint8_t interface_id, uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 01271 { 01272 uint16_t result_len; 01273 thread_joiner_t *this = thread_joiner_find(interface_id); 01274 if (!this || !this->pending_configuration_ptr) { 01275 return 0; 01276 } 01277 01278 result_len = configuration_set_length(this->pending_configuration_ptr,req_tlv_ptr,req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01279 01280 /* Add pending timestamp if required and not ignored*/ 01281 if (thread_meshcop_tlv_list_type_available(req_tlv_ptr, req_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP) && 01282 !thread_meshcop_tlv_list_type_available(ignored_tlv_ptr, ignored_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP)) { 01283 result_len += 10; 01284 } 01285 01286 /* Always add delay timer */ 01287 result_len += 6; 01288 01289 return result_len; 01290 } 01291 01292 uint8_t *thread_joiner_application_pending_config_build(uint8_t interface_id, uint8_t *ptr, uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 01293 { 01294 thread_joiner_t *this = thread_joiner_find(interface_id); 01295 if (!this || !this->pending_configuration_ptr) { 01296 return ptr; 01297 } 01298 01299 /* Build pending config data */ 01300 ptr = configuration_set_write(this->pending_configuration_ptr, ptr, req_tlv_ptr, req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01301 01302 /* Add pending timestamp (len = 10) if required and not ignored */ 01303 if (thread_meshcop_tlv_list_type_available(req_tlv_ptr, req_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP) && 01304 !thread_meshcop_tlv_list_type_available(ignored_tlv_ptr, ignored_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP)) { 01305 ptr = thread_meshcop_tlv_data_write_uint64(ptr,MESHCOP_TLV_PENDING_TIMESTAMP, this->pending_configuration_ptr->timestamp); 01306 } 01307 01308 /* Always add delay timer (len = 6) */ 01309 ptr = thread_meshcop_tlv_data_write_uint32(ptr, MESHCOP_TLV_DELAY_TIMER, this->pending_configuration_ptr->timeout_in_ms); 01310 01311 return ptr; 01312 } 01313 01314 uint8_t *thread_joiner_application_pending_config_tlv_list_get(uint8_t interface_id, uint16_t *length) 01315 { 01316 uint16_t data_list_len = 0; 01317 uint8_t *result_ptr; 01318 uint8_t *return_ptr; 01319 01320 thread_joiner_t *this = thread_joiner_find(interface_id); 01321 if (!this || !this->pending_configuration_ptr) { 01322 return NULL; 01323 } 01324 *length = 0; 01325 thread_meshcop_tlv_list_generate(this->pending_configuration_ptr->data, this->pending_configuration_ptr->length, NULL, &data_list_len); 01326 if (data_list_len == 0){ 01327 return NULL; 01328 } 01329 01330 /* Add also room for pending timestamp */ 01331 *length = data_list_len + 1; 01332 result_ptr = return_ptr = ns_dyn_mem_alloc(*length); 01333 01334 if (!result_ptr) { 01335 return NULL; 01336 } 01337 01338 *result_ptr++ = MESHCOP_TLV_PENDING_TIMESTAMP; 01339 01340 thread_meshcop_tlv_list_generate(this->pending_configuration_ptr->data, this->pending_configuration_ptr->length, result_ptr, &data_list_len); 01341 01342 return return_ptr; 01343 } 01344 01345 void thread_joiner_application_pending_config_add_missing_fields(uint8_t interface_id) 01346 { 01347 thread_joiner_t *this = thread_joiner_find(interface_id); 01348 if (!this || !this->pending_configuration_ptr) { 01349 return; 01350 } 01351 //TODO Specification open here 01352 // a) copy only mandatory fields 01353 // b) copy everything but remove zero length tlvs 01354 //configuration_set_copy_mandatory(this->pending_configuration_ptr, this->active_configuration_ptr); 01355 configuration_set_copy_missing(this->pending_configuration_ptr, this->active_configuration_ptr); 01356 configuration_set_remove_null_tlv(this->pending_configuration_ptr); 01357 } 01358 01359 01360 bool thread_joiner_application_old_config_exists(int8_t interface_id) 01361 { 01362 thread_joiner_t *this = thread_joiner_find(interface_id); 01363 if (!this || !this->old_active_configuration_ptr) { 01364 return false; 01365 } 01366 return true; 01367 } 01368 void thread_joiner_application_old_config_delete(int8_t interface_id) 01369 { 01370 thread_joiner_t *this = thread_joiner_find(interface_id); 01371 if (!this || !this->old_active_configuration_ptr) { 01372 return; 01373 } 01374 ns_dyn_mem_free(this->old_active_configuration_ptr); 01375 this->old_active_configuration_ptr = NULL; 01376 01377 return; 01378 } 01379 int thread_joiner_application_old_config_activate(int8_t interface_id) 01380 { 01381 thread_joiner_t *this = thread_joiner_find(interface_id); 01382 if (!this || !this->old_active_configuration_ptr) { 01383 return -1; 01384 } 01385 this->active_configuration_ptr = this->old_active_configuration_ptr; 01386 this->old_active_configuration_ptr = NULL; 01387 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01388 link_configuration_trace(this->configuration_ptr); 01389 01390 return 0; 01391 } 01392 01393 void thread_joiner_application_pending_config_delete(int8_t interface_id) 01394 { 01395 thread_joiner_t *this = thread_joiner_find(interface_id); 01396 if (!this || !this->pending_configuration_ptr) { 01397 return; 01398 } 01399 ns_dyn_mem_free(this->pending_configuration_ptr); 01400 this->pending_configuration_ptr = NULL; 01401 thread_joiner_application_configuration_nvm_save(interface_id); 01402 return; 01403 } 01404 01405 void thread_joiner_application_next_pending_config_save(int8_t interface_id) 01406 { 01407 thread_joiner_t *this = thread_joiner_find(interface_id); 01408 if (!this || !this->pending_configuration_ptr) { 01409 return; 01410 } 01411 this->next_pending_configuration_ptr = configuration_set_copy(this->pending_configuration_ptr); 01412 if (!this->next_pending_configuration_ptr) { 01413 tr_error("next pending configuration creation failed"); 01414 } 01415 return; 01416 } 01417 bool thread_joiner_application_next_pending_config_exists(int8_t interface_id) 01418 { 01419 thread_joiner_t *this = thread_joiner_find(interface_id); 01420 if (!this || !this->next_pending_configuration_ptr) { 01421 return false; 01422 } 01423 return true; 01424 } 01425 01426 uint16_t thread_joiner_application_next_pending_config_length(int8_t interface_id) 01427 { 01428 uint16_t response_len = 0; 01429 thread_joiner_t *this = thread_joiner_find(interface_id); 01430 if (!this || !this->next_pending_configuration_ptr) { 01431 return 0; 01432 } 01433 response_len += 2 + 8; // Pending timestamp 01434 response_len += 2 + 4; // delay timer 01435 response_len += this->next_pending_configuration_ptr->length; 01436 return response_len; 01437 } 01438 01439 uint8_t *thread_joiner_application_next_pending_config_build(int8_t interface_id, uint8_t *ptr) 01440 { 01441 thread_joiner_t *this = thread_joiner_find(interface_id); 01442 if (!this || !this->next_pending_configuration_ptr) { 01443 return ptr; 01444 } 01445 memcpy(ptr, this->next_pending_configuration_ptr->data, this->next_pending_configuration_ptr->length ); 01446 ptr +=this->next_pending_configuration_ptr->length; 01447 ptr = thread_meshcop_tlv_data_write_uint64(ptr,MESHCOP_TLV_PENDING_TIMESTAMP, this->next_pending_configuration_ptr->timestamp); 01448 ptr = thread_meshcop_tlv_data_write_uint32(ptr,MESHCOP_TLV_DELAY_TIMER, this->next_pending_configuration_ptr->timeout_in_ms); 01449 return ptr; 01450 } 01451 void thread_joiner_application_next_pending_config_delete(int8_t interface_id) 01452 { 01453 thread_joiner_t *this = thread_joiner_find(interface_id); 01454 if (!this || !this->next_pending_configuration_ptr) { 01455 return; 01456 } 01457 ns_dyn_mem_free(this->next_pending_configuration_ptr); 01458 this->next_pending_configuration_ptr = NULL; 01459 01460 return; 01461 } 01462 void thread_joiner_application_next_active_config_save(int8_t interface_id) 01463 { 01464 thread_joiner_t *this = thread_joiner_find(interface_id); 01465 if (!this || !this->configuration_ptr) { 01466 return; 01467 } 01468 this->next_active_configuration_ptr = configuration_set_copy(this->active_configuration_ptr); 01469 if (!this->next_active_configuration_ptr) { 01470 tr_error("next pending configuration creation failed"); 01471 return; 01472 } 01473 return; 01474 } 01475 bool thread_joiner_application_next_active_config_exists(int8_t interface_id) 01476 { 01477 thread_joiner_t *this = thread_joiner_find(interface_id); 01478 if (!this || !this->next_active_configuration_ptr) { 01479 return false; 01480 } 01481 return true; 01482 } 01483 uint16_t thread_joiner_application_next_active_config_length(int8_t interface_id) 01484 { 01485 thread_joiner_t *this = thread_joiner_find(interface_id); 01486 if (!this || !this->next_active_configuration_ptr) { 01487 return 0; 01488 } 01489 return this->next_active_configuration_ptr->length; 01490 } 01491 01492 uint8_t *thread_joiner_application_next_active_config_write(int8_t interface_id, uint8_t *ptr) 01493 { 01494 thread_joiner_t *this = thread_joiner_find(interface_id); 01495 if (!this || !this->next_active_configuration_ptr) { 01496 return ptr; 01497 } 01498 memcpy(ptr, this->next_active_configuration_ptr->data, this->next_active_configuration_ptr->length ); 01499 ptr +=this->next_active_configuration_ptr->length; 01500 return ptr; 01501 } 01502 01503 void thread_joiner_application_next_active_config_delete(int8_t interface_id) 01504 { 01505 thread_joiner_t *this = thread_joiner_find(interface_id); 01506 if (!this || !this->next_active_configuration_ptr) { 01507 return; 01508 } 01509 ns_dyn_mem_free(this->next_active_configuration_ptr); 01510 this->next_active_configuration_ptr = NULL; 01511 01512 return; 01513 } 01514 01515 device_configuration_s *thread_joiner_application_get_device_config(int8_t interface_id) 01516 { 01517 thread_joiner_t *this = thread_joiner_find(interface_id); 01518 if (!this) { 01519 return NULL; 01520 } 01521 return this->device_configuration_ptr; 01522 } 01523 01524 int thread_joiner_application_link_configuration_store(int8_t interface_id, link_configuration_s *link_config) 01525 { 01526 thread_joiner_t *this = thread_joiner_get(interface_id); 01527 01528 if (!link_config || !this) { 01529 return -1; 01530 } 01531 01532 if (!this->configuration_ptr) { 01533 this->configuration_ptr = link_configuration_create(); 01534 } 01535 01536 thread_joiner_application_validate_settings(this);// Generate all random information 01537 configuration_set_generate(this->active_configuration_ptr, link_config); 01538 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01539 this->configuration_ptr->key_sequence = link_config->key_sequence; 01540 this->configuration_valid = true; 01541 link_configuration_trace(this->configuration_ptr); 01542 01543 // store link configuration to NVM. This also stores pending configuration and some other parameters! 01544 return thread_joiner_application_configuration_nvm_save(this->interface_id); 01545 } 01546 01547 int thread_joiner_application_link_configuration_delete(int8_t interface_id) 01548 { 01549 thread_joiner_t *this = thread_joiner_get(interface_id); 01550 01551 // delete link configuration from NVM 01552 return thread_joiner_application_nvm_link_config_delete(this); 01553 } 01554 01555 bool thread_joiner_application_nvm_link_configuration_load(int8_t interface_id) 01556 { 01557 thread_joiner_t *this = thread_joiner_find(interface_id); 01558 if (this && this->nvm_link_configuration_load == true) { 01559 this->nvm_link_configuration_load = false; 01560 if (thread_joiner_application_nvm_link_config_read(this) == 0) { 01561 return true; 01562 } else { 01563 tr_error("Failed to read link configuration settings from NVM"); 01564 } 01565 } 01566 return false; 01567 } 01568 01569 int thread_joiner_application_provisioning_set(int8_t interface_id, thread_provisioning_status_e status) 01570 { 01571 thread_joiner_t *this = thread_joiner_find(interface_id); 01572 if (this) { 01573 this->provisioning_done = status; 01574 if (status == PROVISIONING_STATUS_REJECTED) { 01575 // If commissioner rejects us retry done after some time -> state is changed back to not done 01576 this->provisioning_timeout = randLIB_get_random_in_range(20,120); 01577 } else { 01578 this->provisioning_timeout = 0; 01579 } 01580 } 01581 return 0; 01582 } 01583 01584 thread_provisioning_status_e thread_joiner_application_provisioning_get(int8_t interface_id) 01585 { 01586 thread_joiner_t *this = thread_joiner_find(interface_id); 01587 if (this) { 01588 return this->provisioning_done; 01589 } 01590 return PROVISIONING_STATUS_NOT_DONE; 01591 } 01592 01593 static int joiner_application_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len) 01594 { 01595 int ret = -1; 01596 tr_debug("Thread joiner security started"); 01597 (void)address; 01598 (void)port; 01599 01600 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01601 01602 if( this ){ 01603 memcpy(pw, this->device_configuration_ptr->PSKd_ptr, this->device_configuration_ptr->PSKd_len ); 01604 *pw_len = this->device_configuration_ptr->PSKd_len; 01605 ret = 0; 01606 // ret = coap_service_security_key_set( service_id, address, port, 01607 // this->device_configuration_ptr->PSKd_ptr, 01608 // this->device_configuration_ptr->PSKd_len ); 01609 } 01610 01611 return ret; 01612 } 01613 01614 int joiner_application_security_done_cb(int8_t service_id, uint8_t address[16], uint8_t keyblock[40]) 01615 { 01616 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01617 uint8_t kek[32]; 01618 int ret; 01619 01620 tr_debug("Thread joiner security done service: %d, address: %s", service_id, trace_ipv6(address)); 01621 if (!this) { 01622 return -1; 01623 } 01624 01625 ns_sha256(keyblock, 40, kek); 01626 01627 ret = thread_commissioning_if_pairwise_key_add(this->interface_id, 10000, &address[8], kek); 01628 if (ret) { 01629 tr_debug("pairwise key set failed %d", ret); 01630 //TODO error? 01631 } 01632 thread_commissioning_if_enable_security(this->interface_id); 01633 return 0; 01634 } 01635 01636 static void thread_joiner_attach_cb(void* arg) 01637 { 01638 thread_joiner_t *this = arg; 01639 tr_debug("Attach to new network"); 01640 if (!this){ 01641 return; 01642 } 01643 // Cleaning up the joining information 01644 thread_joiner_application_commission_clean(this); 01645 if (this->done_cb) {// This is successfull 01646 this->done_cb(this->interface_id); 01647 } 01648 } 01649 static void thread_joiner_entrust_timeout_cb(void* arg) 01650 { 01651 thread_joiner_t *this = arg; 01652 tr_debug("No valid configuration received in time"); 01653 if (!this){ 01654 return; 01655 } 01656 // Cleaning up the joining information 01657 thread_joiner_application_commission_clean(this); 01658 if (this->done_cb) {// Failed 01659 this->done_cb(this->interface_id); 01660 } 01661 } 01662 01663 void thread_joiner_attach_if_needed(thread_joiner_t *this) 01664 { 01665 tr_debug("attach check"); 01666 if (this->finalisation_done && this->configuration_valid) { 01667 tr_debug("Start attach timer");// one second timer gives time for joiner router to get entrust response 01668 this->attach_timeout = eventOS_timeout_ms(thread_joiner_attach_cb, 1000, this); 01669 } else { 01670 tr_debug("Start entrust timeout");// 30 timer to get credentials 01671 this->entrust_timeout = eventOS_timeout_ms(thread_joiner_entrust_timeout_cb, 30000, this); 01672 } 01673 } 01674 01675 01676 int thread_joiner_application_finalisation_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 01677 { 01678 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01679 uint8_t result; 01680 (void)source_address; 01681 (void)source_port; 01682 01683 tr_debug("finalisation done"); 01684 01685 if (!this) { 01686 return -1; 01687 } 01688 01689 // CoAP message failed - try to reattach 01690 if(!response_ptr || !response_ptr->payload_ptr){ 01691 tr_debug("finalisation failed - no response"); 01692 goto error; 01693 } 01694 01695 thci_trace("Device - Joiner|Direction - recv|EUI - %s|Type - JOIN_FIN.resp|Length - %d|Payload - %s",trace_array(this->device_configuration_ptr->eui64,8), response_ptr->payload_len, trace_array(response_ptr->payload_ptr, response_ptr->payload_len)); 01696 coap_service_close_secure_connection(service_id, this->parent_address, this->parent_port); 01697 // todo: free certificates 01698 if (1 <= thread_tmfcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &result)) { 01699 //Todo make attach 01700 this->finalisation_done = true; 01701 this->provisioning_done = PROVISIONING_STATUS_NOT_DONE; 01702 if (result == 1) { 01703 // If accepted no additional actions needed 01704 tr_debug("Provisioning done"); 01705 this->provisioning_done = PROVISIONING_STATUS_DONE; 01706 } 01707 thread_joiner_attach_if_needed(this); 01708 return 0; 01709 } 01710 thci_trace("joinerError"); 01711 tr_debug("finalisation rejected"); 01712 01713 error: 01714 //TODO cant delete as old configuration pointer is in use I quess 01715 // link_configuration_delete(this->configuration_ptr); 01716 thread_joiner_application_commission_clean(this); 01717 this->configuration_valid = false; 01718 this->done_cb(this->interface_id); 01719 blacklist_update(source_address, false); 01720 //This trigger re scan and we try to connect again 01721 //TODO this needs status code to allow blacklisting of thread network 01722 return 0; 01723 } 01724 static int thread_joiner_application_send_finalisation(thread_joiner_t *this, uint8_t parent_address[16], uint16_t port) 01725 { 01726 uint8_t *ptr, *data_ptr; 01727 uint16_t length; 01728 01729 tr_debug("Thread joiner finalisation send"); 01730 length = thread_joiner_application_device_configuration_length(this->device_configuration_ptr); 01731 length += 3;// State 01732 01733 data_ptr = ptr = ns_dyn_mem_alloc(length); 01734 if (!ptr) { 01735 tr_error("Failed to start Commissioning"); 01736 return -1; 01737 } 01738 ptr = thread_joiner_application_device_configuration_build(ptr, this->device_configuration_ptr); 01739 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 01740 01741 thci_trace("Device - Joiner|Direction - sent|EUI - %s|Type - JOIN_FIN.req|Length - %d|Payload - %s",trace_array(this->device_configuration_ptr->eui64,8),(int)( ptr - data_ptr), trace_array(data_ptr, ptr - data_ptr)); 01742 coap_service_request_send(this->secure_coap_service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, parent_address, port, 01743 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_JOINER_FINALIZATION, COAP_CT_OCTET_STREAM, data_ptr, ptr - data_ptr, thread_joiner_application_finalisation_cb); 01744 01745 ns_dyn_mem_free(data_ptr); 01746 01747 return 0; 01748 } 01749 01750 static uint8_t *thread_joiner_application_write_channel(uint8_t *ptr, uint16_t data) 01751 { 01752 *ptr++ = MESHCOP_TLV_CHANNEL; // type 01753 *ptr++ = 3; // length 01754 *ptr++ = 0; // channel page 01755 return common_write_16_bit(data, ptr); 01756 } 01757 01758 static int thread_joiner_application_entrust_recv_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 01759 { 01760 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01761 (void)source_address; 01762 (void)source_port; 01763 01764 if (!this) { 01765 return -1; 01766 } 01767 01768 if (thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MASTER_KEY, NULL) < 16 || 01769 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, NULL) < 8 || 01770 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_XPANID, NULL) < 8 || 01771 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_NAME, NULL) == 0 || 01772 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PSKC, NULL) < 16 ) { 01773 // Absolutely minimum we must have is master secret to attach. 01774 // If commissioner wants to be connected we must have PSKc,Name,Xpanid 01775 // If there is some fields missing we could attach, but timestamp must be set to 0 which will then cause synchronization 01776 tr_debug("Not include all TLv's"); 01777 thci_trace("joinerError"); 01778 return -1; 01779 } 01780 uint8_t *result_ptr; 01781 memcpy(this->active_configuration_ptr->data,request_ptr->payload_ptr, request_ptr->payload_len); 01782 this->active_configuration_ptr->length = request_ptr->payload_len; 01783 01784 result_ptr = this->active_configuration_ptr->data + this->active_configuration_ptr->length; 01785 01786 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_ACTIVE_TIME_STAMP, NULL) == 0) { 01787 result_ptr = thread_meshcop_tlv_data_write_uint64(result_ptr,MESHCOP_TLV_ACTIVE_TIME_STAMP, 0); 01788 } 01789 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_XPANID, NULL) == 0) { 01790 result_ptr = thread_meshcop_tlv_data_write(result_ptr,MESHCOP_TLV_XPANID, 8, this->configuration_ptr->extented_pan_id ); 01791 } 01792 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_CHANNEL, NULL) == 0) { 01793 result_ptr = thread_joiner_application_write_channel(result_ptr, this->configuration_ptr->rfChannel); 01794 } 01795 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_PANID, NULL) == 0) { 01796 result_ptr = thread_meshcop_tlv_data_write_uint16(result_ptr,MESHCOP_TLV_PANID, this->configuration_ptr->panId ); 01797 } 01798 01799 this->active_configuration_ptr->length = result_ptr - this->active_configuration_ptr->data; 01800 01801 // check if everything is present 01802 if (!thread_meshcop_tlv_list_present(this->active_configuration_ptr->data, this->active_configuration_ptr->length, mle_active_configuration_dataset_tlvs, sizeof(mle_active_configuration_dataset_tlvs))) { 01803 // Some fields are missing we need to sync settings during attach 01804 uint8_t *timestamp_ptr = NULL; 01805 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp_ptr); 01806 if (timestamp_ptr) { 01807 common_write_64_bit(0,timestamp_ptr); 01808 } 01809 } 01810 01811 thread_meshcop_tlv_data_get_uint64(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); 01812 01813 uint32_t network_key_seq = 0; 01814 if (thread_meshcop_tlv_data_get_uint32(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_KEY_SEQUENCE, &network_key_seq)) { 01815 this->configuration_ptr->key_sequence = network_key_seq; 01816 } 01817 01818 /*We must null out the master secret*/ 01819 #ifdef THREAD_THCI_SUPPORT 01820 uint8_t *master_secret_ptr; 01821 if (thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MASTER_KEY, &master_secret_ptr) >= 16) { 01822 memset(master_secret_ptr,0,16); 01823 } 01824 thci_trace("Device - Joiner|Direction - recv|EUI - %s|Type - JOIN_ent.req|Length - %d|Payload - %s",trace_array(this->device_configuration_ptr->eui64,8), request_ptr->payload_len, trace_array(request_ptr->payload_ptr, request_ptr->payload_len)); 01825 #endif 01826 01827 // save link configuration to NVM 01828 01829 thci_trace("joinerAccepted"); 01830 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data,this->active_configuration_ptr->length); 01831 this->configuration_valid = true; 01832 thread_joiner_application_configuration_nvm_save(this->interface_id); 01833 01834 link_configuration_trace(this->configuration_ptr); 01835 01836 #ifdef THREAD_THCI_SUPPORT 01837 thci_trace("Device - Joiner|Direction - sent|EUI - %s|Type - JOIN_ent.resp|Length - 0|Payload - ", trace_array(this->device_configuration_ptr->eui64,8)); 01838 #endif 01839 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, NULL, 0); 01840 01841 //TODO Add delay timer of 3 seconds and then do attach 01842 thread_joiner_attach_if_needed(this); 01843 01844 return 0; 01845 } 01846 01847 int thread_joiner_application_pskd_commission_start(int8_t interface_id, uint8_t parent_address[16], uint16_t joiner_port, uint16_t panid, uint8_t xpanid[8], uint8_t channel, thread_joiner_application_commission_done_cb *done_cb) 01848 { 01849 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01850 thread_joiner_t *this = thread_joiner_find(interface_id); 01851 if (!this || !done_cb || !cur) { 01852 return -1; 01853 } 01854 if (!this->configuration_ptr) { 01855 this->configuration_ptr = link_configuration_create(); 01856 } 01857 01858 if (!this->configuration_ptr) { 01859 tr_error("Commission start failed"); 01860 return -2; 01861 } 01862 this->configuration_valid = false; 01863 01864 01865 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 01866 coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_ENTRUST, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_joiner_application_entrust_recv_cb); 01867 01868 this->secure_coap_service_id = coap_service_initialize(this->interface_id, THREAD_DEFAULT_JOINER_PORT, COAP_SERVICE_OPTIONS_EPHEMERAL_PORT | COAP_SERVICE_OPTIONS_SECURE | 0x80, joiner_application_security_start_cb, joiner_application_security_done_cb); 01869 01870 tr_debug("start pskd commissioning: interface %d, parent: %s, port %d", interface_id, trace_ipv6(parent_address), joiner_port); 01871 // save initial information 01872 this->configuration_ptr->panId = panid; 01873 this->configuration_ptr->rfChannel = channel; 01874 if (xpanid) { 01875 memcpy(this->configuration_ptr->extented_pan_id, xpanid, 8); 01876 } 01877 01878 link_configuration_trace(this->configuration_ptr); 01879 //TODO this callback needs status for blacklist 01880 this->done_cb = done_cb; 01881 memcpy(this->parent_address,parent_address,16); 01882 this->parent_port = joiner_port; 01883 01884 thci_trace("joinerDtlsSessionStarted"); 01885 thread_joiner_application_send_finalisation(this, parent_address, joiner_port); 01886 return 0; 01887 } 01888 01889 int thread_joiner_application_configuration_nvm_save(int8_t interface_id) 01890 { 01891 tr_info("thread_joiner_application_configuration_nvm_save"); 01892 01893 thread_joiner_t *this = thread_joiner_find(interface_id); 01894 if (!this) { 01895 return -1; 01896 } 01897 01898 thread_nvm_store_device_configuration_write(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 01899 thread_nvm_store_pending_configuration_write(this->pending_configuration_ptr, sizeof(configuration_set_t)); 01900 thread_nvm_store_seq_counter_write(this->configuration_ptr->key_sequence); 01901 thread_nvm_store_active_configuration_write(this->active_configuration_ptr, sizeof(configuration_set_t)); 01902 01903 /* allow configuration to be read in bootstrap */ 01904 this->nvm_link_configuration_load = true; 01905 return 0; 01906 } 01907 01908 int thread_joiner_application_update_configuration(uint8_t interface_id, uint8_t *msg_ptr, uint16_t msg_len, bool include_missing_tlvs) 01909 { 01910 thread_joiner_t *this = thread_joiner_find(interface_id); 01911 configuration_set_t *configuration_ptr; 01912 if (!this) { 01913 return -1; 01914 } 01915 configuration_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 01916 if (!configuration_ptr) { 01917 return -2; 01918 } 01919 memcpy(configuration_ptr,this->active_configuration_ptr,sizeof(configuration_set_t)); 01920 this->active_configuration_ptr->length = 0; 01921 configuration_set_add_all_fields(this->active_configuration_ptr,msg_ptr,msg_len, meshcop_active_set_ignore, sizeof(meshcop_active_set_ignore)); 01922 if (include_missing_tlvs) { 01923 configuration_set_copy_missing(this->active_configuration_ptr, configuration_ptr); 01924 configuration_set_remove_null_tlv(this->active_configuration_ptr); 01925 } else { 01926 configuration_set_copy_mandatory(this->active_configuration_ptr, configuration_ptr); 01927 } 01928 thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); 01929 link_configuration_update(this->configuration_ptr,msg_ptr,msg_len); 01930 ns_dyn_mem_free(configuration_ptr); 01931 thread_joiner_application_configuration_nvm_save(interface_id); 01932 01933 return 0; 01934 } 01935 uint8_t *thread_joiner_application_active_config_tlv_list_get(uint8_t interface_id, uint16_t *length) 01936 { 01937 uint8_t *result_ptr; 01938 thread_joiner_t *this = thread_joiner_find(interface_id); 01939 if (!this || !this->active_configuration_ptr) { 01940 return NULL; 01941 } 01942 *length = 0; 01943 thread_meshcop_tlv_list_generate(this->active_configuration_ptr->data, this->active_configuration_ptr->length,NULL, length); 01944 if (*length == 0){ 01945 return NULL; 01946 } 01947 result_ptr = ns_dyn_mem_alloc(*length); 01948 if (!result_ptr) { 01949 } 01950 thread_meshcop_tlv_list_generate(this->active_configuration_ptr->data, this->active_configuration_ptr->length,result_ptr, length); 01951 01952 return result_ptr; 01953 } 01954 uint8_t *thread_joiner_application_active_config_params_get(uint8_t interface_id, uint16_t *length) 01955 { 01956 thread_joiner_t *this = thread_joiner_find(interface_id); 01957 if (!this || !this->active_configuration_ptr || !length) { 01958 return NULL; 01959 } 01960 *length = this->active_configuration_ptr->length; 01961 return this->active_configuration_ptr->data; 01962 } 01963 01964 uint16_t thread_joiner_application_active_config_length(uint8_t interface_id, const uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 01965 { 01966 thread_joiner_t *this = thread_joiner_find(interface_id); 01967 if (!this || !this->active_configuration_ptr) { 01968 return 0; 01969 } 01970 return configuration_set_length(this->active_configuration_ptr, req_tlv_ptr, req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01971 } 01972 01973 uint8_t *thread_joiner_application_active_config_write(uint8_t interface_id, uint8_t *ptr, const uint8_t *req_tlv_ptr, uint8_t req_tlv_len, const uint8_t *ignored_tlv_ptr, uint8_t ignored_tlv_len) 01974 { 01975 thread_joiner_t *this = thread_joiner_find(interface_id); 01976 if (!this || !this->active_configuration_ptr) { 01977 return ptr; 01978 } 01979 return configuration_set_write(this->active_configuration_ptr, ptr,req_tlv_ptr,req_tlv_len, ignored_tlv_ptr,ignored_tlv_len); 01980 } 01981 01982 int thread_joiner_application_device_configuration_length(device_configuration_s *device_configuration) 01983 { 01984 int length; 01985 01986 if (!device_configuration) { 01987 return 0; 01988 } 01989 length = 2 + 1 + 2 + 6 + 2 + device_configuration->vendor_data_len;// Status + Stack version + vendor data 01990 if (device_configuration->provisioning_uri_ptr) { 01991 length += 2 + strlen(device_configuration->provisioning_uri_ptr); 01992 } 01993 if (device_configuration->vendor_name_ptr) { 01994 length += 2 + strlen(device_configuration->vendor_name_ptr); 01995 } 01996 if (device_configuration->vendor_model_ptr) { 01997 length += 2 + strlen(device_configuration->vendor_model_ptr); 01998 } 01999 if (device_configuration->vendor_sw_version_ptr) { 02000 length += 2 + strlen(device_configuration->vendor_sw_version_ptr); 02001 } 02002 return length; 02003 } 02004 02005 uint8_t *thread_joiner_application_device_configuration_build(uint8_t *ptr, device_configuration_s *device_configuration) 02006 { 02007 if (!ptr || !device_configuration) { 02008 return ptr; 02009 } 02010 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_STACK_VERSION, 6, device_configuration->vendor_stack_version); 02011 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_DATA, 02012 device_configuration->vendor_data_len, 02013 device_configuration->vendor_data_ptr); 02014 02015 if (device_configuration->provisioning_uri_ptr) { 02016 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_PROVISIONING_URL, 02017 strlen(device_configuration->provisioning_uri_ptr), 02018 (uint8_t *)device_configuration->provisioning_uri_ptr); 02019 } 02020 if (device_configuration->vendor_name_ptr) { 02021 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_NAME, 02022 strlen(device_configuration->vendor_name_ptr), 02023 (uint8_t *)device_configuration->vendor_name_ptr); 02024 } 02025 if (device_configuration->vendor_model_ptr) { 02026 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_MODEL, 02027 strlen(device_configuration->vendor_model_ptr), 02028 (uint8_t *)device_configuration->vendor_model_ptr); 02029 } 02030 if (device_configuration->vendor_sw_version_ptr) { 02031 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_SW_VERSION, 02032 strlen(device_configuration->vendor_sw_version_ptr), 02033 (uint8_t *)device_configuration->vendor_sw_version_ptr); 02034 } 02035 return ptr; 02036 } 02037 02038 int8_t thread_joiner_application_active_configuration_update(int8_t interface_id, uint8_t *data_ptr, uint16_t data_len, const uint8_t *ignore_ptr, uint8_t ingore_len) 02039 { 02040 thread_joiner_t *this = thread_joiner_find(interface_id); 02041 uint64_t timestamp = 0; 02042 02043 if (!this) { 02044 return -1; 02045 } 02046 configuration_set_add_all_fields(this->active_configuration_ptr, data_ptr, data_len, ignore_ptr, ingore_len); 02047 thread_meshcop_tlv_data_get_uint64(data_ptr, data_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp); 02048 thread_joiner_application_active_timestamp_set(this->interface_id, timestamp); 02049 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data,this->active_configuration_ptr->length); 02050 this->configuration_valid = true; 02051 thread_joiner_application_configuration_nvm_save(this->interface_id); 02052 02053 link_configuration_trace(this->configuration_ptr); 02054 02055 return 0; 02056 } 02057 #endif 02058
Generated on Tue Jul 12 2022 12:45:58 by
