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.
Fork of OmniWheels by
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 static int thread_joiner_application_nvm_link_config_read(thread_joiner_t *this) { 00921 00922 // read config from NVM, in case of failure current settings are unchanged. 00923 int nvm_read_status = thread_nvm_store_active_configuration_read(this->active_configuration_ptr, sizeof(configuration_set_t)); 00924 tr_debug("active conf read %d", nvm_read_status); 00925 // validate that active configuration settings are valid, even if we couldn't read from nvm. 00926 if(!configuration_set_validate(this->active_configuration_ptr->data, this->active_configuration_ptr->length, true)) { 00927 tr_debug("No active configuration avail"); 00928 return -1; 00929 } 00930 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 00931 00932 thread_nvm_fast_data_t fast_data; 00933 memset(&fast_data,0,sizeof(thread_nvm_fast_data_t)); 00934 int fast_data_read_ret = thread_nvm_store_fast_data_read(&fast_data); 00935 tr_info("From NVM %d", fast_data_read_ret); 00936 tr_info("mac-counter %"PRIu32,fast_data.mac_frame_counter); 00937 tr_info("mle-counter %"PRIu32,fast_data.mle_frame_counter); 00938 tr_info("seq-counter %"PRIu32,fast_data.seq_counter); 00939 00940 if (THREAD_NVM_FILE_SUCCESS == fast_data_read_ret) { 00941 if (this->configuration_ptr->key_sequence < fast_data.seq_counter) { 00942 this->configuration_ptr->key_sequence = fast_data.seq_counter; 00943 } 00944 } 00945 00946 fast_data.mac_frame_counter += MAC_FRAME_COUNTER_LIMIT; 00947 fast_data.mle_frame_counter += MLE_FRAME_COUNTER_LIMIT; 00948 thread_nvm_store_fast_data_write(&fast_data); 00949 00950 thread_nvm_store_device_configuration_read(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 00951 thread_nvm_store_link_info_read(); 00952 // Generate all random information, if device configuration read failed then the random mac and eid are created. 00953 bool new_value_generated = thread_joiner_application_validate_settings(this); 00954 if (new_value_generated) { 00955 thread_nvm_store_device_configuration_write(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 00956 } 00957 00958 this->configuration_valid = true; 00959 link_configuration_trace(this->configuration_ptr); 00960 00961 //Add Security to MLE service 00962 uint8_t key_material[32]; 00963 uint8_t key_index; 00964 //Define KEY's 00965 00966 thread_key_get(this->configuration_ptr->master_key, key_material, this->configuration_ptr->key_sequence); 00967 key_index = THREAD_KEY_INDEX(this->configuration_ptr->key_sequence); 00968 //Set Keys 00969 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00970 mac_helper_security_default_key_set(cur, &key_material[16], key_index, MAC_KEY_ID_MODE_IDX); 00971 mle_service_security_set_security_key(this->interface_id, key_material, key_index, true); 00972 // update counters 00973 mle_service_security_set_frame_counter(this->interface_id, fast_data.mle_frame_counter); 00974 mac_helper_link_frame_counter_set(this->interface_id, fast_data.mac_frame_counter); 00975 00976 // this saves all configurations 00977 if (THREAD_NVM_FILE_SUCCESS!=nvm_read_status) { 00978 thread_joiner_application_configuration_nvm_save(this->interface_id); 00979 } 00980 else { 00981 tr_info("Reading pending set"); 00982 configuration_set_t *pend_conf_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 00983 if (pend_conf_ptr) { 00984 memset(pend_conf_ptr, 0, sizeof(configuration_set_t)); 00985 int pending_ret = thread_nvm_store_pending_configuration_read(pend_conf_ptr, sizeof(configuration_set_t)); 00986 if(THREAD_NVM_FILE_SUCCESS==pending_ret) { 00987 if (this->pending_configuration_ptr) { 00988 ns_dyn_mem_free(this->pending_configuration_ptr); 00989 } 00990 this->pending_configuration_ptr = pend_conf_ptr; 00991 this->pending_configuration_ptr->timeout_in_ms = 0; 00992 this->pending_set_in_sync = false; 00993 } 00994 else { 00995 tr_info("Reading pending from NVM error:%d", pending_ret); 00996 ns_dyn_mem_free(pend_conf_ptr); 00997 } 00998 } 00999 } 01000 this->nvm_link_configuration_load = false; 01001 return 0; 01002 } 01003 01004 static int thread_joiner_application_nvm_link_config_delete(thread_joiner_t *this) 01005 { 01006 if (!this) { 01007 return -1; 01008 } 01009 int ret = thread_nvm_store_pending_configuration_remove(); 01010 01011 if (ret!=THREAD_NVM_FILE_SUCCESS) { 01012 tr_error("Pending configuration delete error: %d", ret); 01013 } 01014 01015 ret = thread_nvm_store_active_configuration_remove(); 01016 01017 if (ret!=THREAD_NVM_FILE_SUCCESS) { 01018 tr_error("Active configuration delete error: %d", ret); 01019 } 01020 01021 // delete link configuration from cache, device will be restarted after settings are deleted 01022 this->configuration_valid = false; 01023 return 0; 01024 } 01025 01026 uint64_t thread_joiner_application_active_timestamp_get(int8_t interface_id) 01027 { 01028 thread_joiner_t *this = thread_joiner_find(interface_id); 01029 if (!this) { 01030 return 0; 01031 } 01032 01033 return this->configuration_ptr->timestamp; 01034 } 01035 01036 uint8_t thread_joiner_application_security_policy_get(int8_t interface_id) 01037 { 01038 thread_joiner_t *this = thread_joiner_find(interface_id); 01039 if (!this) { 01040 return 0; 01041 } 01042 01043 return this->configuration_ptr->securityPolicy; 01044 } 01045 01046 uint8_t *thread_joiner_application_random_mac_get(int8_t interface_id) 01047 { 01048 thread_joiner_t *this = thread_joiner_find(interface_id); 01049 if (!this || !this->device_configuration_ptr) { 01050 tr_error("thread_joiner_application_random_mac_get NULL parameter "); 01051 return (uint8_t*)ADDR_UNSPECIFIED; 01052 } 01053 return this->device_configuration_ptr->extended_random_mac; 01054 } 01055 uint8_t *thread_joiner_application_ml_eid_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_ml_eid_get parameter NULL"); 01060 return (uint8_t*)ADDR_UNSPECIFIED; 01061 } 01062 return this->device_configuration_ptr->mesh_local_eid; 01063 } 01064 void thread_joiner_application_active_timestamp_set(int8_t interface_id, uint64_t timestamp) 01065 { 01066 thread_joiner_t *this = thread_joiner_find(interface_id); 01067 uint8_t *timestamp_ptr = NULL; 01068 if (!this) { 01069 return; 01070 } 01071 01072 thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp_ptr); 01073 if (timestamp_ptr) { 01074 common_write_64_bit(timestamp,timestamp_ptr); 01075 } 01076 01077 //update timestamps in active configuration and link configuration 01078 this->active_configuration_ptr->timestamp = timestamp; 01079 this->configuration_ptr->timestamp = timestamp; 01080 return; 01081 } 01082 01083 void thread_joiner_pending_config_activate(int8_t interface_id) 01084 { 01085 thread_joiner_t *this = thread_joiner_find(interface_id); 01086 01087 if (!this || !this->pending_configuration_ptr) { 01088 tr_error("No pending configuration or joiner!"); 01089 return; 01090 } 01091 01092 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 01093 01094 if (!cur) { 01095 tr_error("No interface information!"); 01096 return; 01097 } 01098 01099 /* 01100 * If pending configuration active timestamp is lower than current active timestamp allow pending configuration activation only 01101 * if master key is changed by the pending set 01102 */ 01103 link_configuration_s *link_configuration = thread_joiner_application_get_config(interface_id); 01104 01105 if (!link_configuration) { 01106 return; 01107 } 01108 01109 // Validate new link configuration 01110 uint8_t *master_key_ptr = NULL; 01111 uint64_t pending_active_timestamp = 0; 01112 thread_meshcop_tlv_data_get_uint64(this->pending_configuration_ptr->data,this->pending_configuration_ptr->length,MESHCOP_TLV_ACTIVE_TIME_STAMP, &pending_active_timestamp); 01113 thread_meshcop_tlv_find(this->pending_configuration_ptr->data,this->pending_configuration_ptr->length,MESHCOP_TLV_NETWORK_MASTER_KEY,&master_key_ptr); 01114 01115 if ((pending_active_timestamp < thread_joiner_application_active_timestamp_get(interface_id))) { 01116 // If new active timestamp is older than current master key must be changed. 01117 if (!master_key_ptr || 01118 memcmp(master_key_ptr,link_configuration->master_key,16) == 0) { 01119 tr_info("*** Pending set activation aborted - device has newer active timestamp"); 01120 thread_joiner_application_pending_config_delete(interface_id); 01121 return; 01122 } 01123 } 01124 01125 if (master_key_ptr && memcmp(master_key_ptr,link_configuration->master_key,16) != 0) { 01126 this->configuration_ptr->key_sequence = 0; 01127 // if write fails, keep going... 01128 (void)thread_nvm_store_seq_counter_write(this->configuration_ptr->key_sequence); 01129 } 01130 01131 tr_info("*** Activating pending configuration."); 01132 01133 ns_dyn_mem_free(this->old_active_configuration_ptr); 01134 this->old_active_configuration_ptr = this->active_configuration_ptr; 01135 this->active_configuration_ptr = this->pending_configuration_ptr; 01136 this->active_configuration_ptr->timestamp = pending_active_timestamp; 01137 // All information is copied from old configuration so if configuration is corrupt we dont change anything. 01138 this->pending_configuration_ptr = NULL; 01139 (void)thread_nvm_store_pending_configuration_remove(); 01140 configuration_set_copy_mandatory(this->active_configuration_ptr, this->old_active_configuration_ptr); 01141 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01142 link_configuration_trace(this->configuration_ptr); 01143 01144 thread_joiner_application_configuration_nvm_save(this->interface_id); 01145 01146 01147 if (thread_link_configuration_activate(cur, this->configuration_ptr) != 0) { 01148 tr_error("Activating pending configuration failed."); 01149 } 01150 01151 tr_info("*** Activating pending configuration done."); 01152 } 01153 01154 01155 void thread_joiner_application_seconds_timer(int8_t interface_id, uint32_t seconds) 01156 { 01157 thread_joiner_t *this = thread_joiner_find(interface_id); 01158 //tr_debug("seconds tick for joiner pending timeout in %d",this->pending_timeout_in_ms); 01159 if (!this) { 01160 return; 01161 } 01162 if (this->provisioning_timeout) { 01163 if (this->provisioning_timeout < seconds) { 01164 this->provisioning_done = PROVISIONING_STATUS_NOT_DONE; 01165 } 01166 this->provisioning_timeout -= seconds; 01167 } 01168 if (!this->pending_configuration_ptr || this->pending_configuration_ptr->timeout_in_ms == 0) { 01169 return; 01170 } 01171 if (this->pending_configuration_ptr->timeout_in_ms > seconds*1000) { 01172 this->pending_configuration_ptr->timeout_in_ms -= seconds*1000; 01173 return; 01174 } 01175 // Activate the pending config 01176 thread_joiner_pending_config_activate(interface_id); 01177 } 01178 01179 int thread_joiner_application_pending_config_create(int8_t interface_id, uint8_t *data_ptr, uint16_t data_len) 01180 { 01181 thread_joiner_t *this = thread_joiner_find(interface_id); 01182 if (!this || data_len > MAX_OPERATIONAL_DATASET_SIZE) { 01183 return -1; 01184 } 01185 if(!this->pending_configuration_ptr){ 01186 this->pending_configuration_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 01187 } 01188 if (!this->pending_configuration_ptr) { 01189 tr_error("pending configuration creation failed"); 01190 return -2; 01191 } 01192 memset(this->pending_configuration_ptr, 0, sizeof(configuration_set_t)); 01193 configuration_set_add_all_fields(this->pending_configuration_ptr,data_ptr,data_len, meshcop_pending_set_ignore, sizeof(meshcop_pending_set_ignore)); 01194 return 0; 01195 } 01196 01197 bool thread_joiner_application_pending_config_exists(int8_t interface_id) 01198 { 01199 thread_joiner_t *this = thread_joiner_find(interface_id); 01200 if (!this || !this->pending_configuration_ptr) { 01201 return false; 01202 } 01203 return true; 01204 } 01205 01206 bool thread_joiner_application_pending_delay_timer_in_sync(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 this->pending_set_in_sync; 01213 } 01214 01215 uint64_t thread_joiner_application_pending_config_timestamp_get(int8_t interface_id) 01216 { 01217 thread_joiner_t *this = thread_joiner_find(interface_id); 01218 if (!this || !this->pending_configuration_ptr || !this->pending_set_in_sync) { 01219 return 0; 01220 } 01221 return this->pending_configuration_ptr->timestamp; 01222 } 01223 01224 int thread_joiner_application_pending_config_timestamp_set(int8_t interface_id, uint64_t timestamp) 01225 { 01226 thread_joiner_t *this = thread_joiner_find(interface_id); 01227 if (!this || !this->pending_configuration_ptr) { 01228 return -1; 01229 } 01230 this->pending_configuration_ptr->timestamp = timestamp; 01231 return 0; 01232 } 01233 01234 01235 int thread_joiner_application_pending_config_enable(int8_t interface_id, uint32_t timeout_in_ms) 01236 { 01237 thread_joiner_t *this = thread_joiner_find(interface_id); 01238 if (!this || !this->pending_configuration_ptr) { 01239 return -1; 01240 } 01241 this->pending_configuration_ptr->timeout_in_ms = timeout_in_ms; 01242 this->pending_set_in_sync = true; 01243 01244 if(this->pending_configuration_ptr->timeout_in_ms > THREAD_MAX_DELAY_TIMER_SECONDS*1000) { 01245 this->pending_configuration_ptr->timeout_in_ms = THREAD_MAX_DELAY_TIMER_SECONDS*1000; 01246 } 01247 thread_joiner_application_configuration_nvm_save(this->interface_id); 01248 01249 return 0; 01250 } 01251 01252 uint32_t thread_joiner_application_pending_config_timeout_get(int8_t interface_id) 01253 { 01254 thread_joiner_t *this = thread_joiner_find(interface_id); 01255 if (!this || !this->pending_configuration_ptr) { 01256 return 0; 01257 } 01258 return this->pending_configuration_ptr->timeout_in_ms; 01259 } 01260 01261 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) 01262 { 01263 uint16_t result_len; 01264 thread_joiner_t *this = thread_joiner_find(interface_id); 01265 if (!this || !this->pending_configuration_ptr) { 01266 return 0; 01267 } 01268 01269 result_len = configuration_set_length(this->pending_configuration_ptr,req_tlv_ptr,req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01270 01271 /* Add pending timestamp if required and not ignored*/ 01272 if (thread_meshcop_tlv_list_type_available(req_tlv_ptr, req_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP) && 01273 !thread_meshcop_tlv_list_type_available(ignored_tlv_ptr, ignored_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP)) { 01274 result_len += 10; 01275 } 01276 01277 /* Always add delay timer */ 01278 result_len += 6; 01279 01280 return result_len; 01281 } 01282 01283 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) 01284 { 01285 thread_joiner_t *this = thread_joiner_find(interface_id); 01286 if (!this || !this->pending_configuration_ptr) { 01287 return ptr; 01288 } 01289 01290 /* Build pending config data */ 01291 ptr = configuration_set_write(this->pending_configuration_ptr, ptr, req_tlv_ptr, req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01292 01293 /* Add pending timestamp (len = 10) if required and not ignored */ 01294 if (thread_meshcop_tlv_list_type_available(req_tlv_ptr, req_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP) && 01295 !thread_meshcop_tlv_list_type_available(ignored_tlv_ptr, ignored_tlv_len, MESHCOP_TLV_PENDING_TIMESTAMP)) { 01296 ptr = thread_meshcop_tlv_data_write_uint64(ptr,MESHCOP_TLV_PENDING_TIMESTAMP, this->pending_configuration_ptr->timestamp); 01297 } 01298 01299 /* Always add delay timer (len = 6) */ 01300 ptr = thread_meshcop_tlv_data_write_uint32(ptr, MESHCOP_TLV_DELAY_TIMER, this->pending_configuration_ptr->timeout_in_ms); 01301 01302 return ptr; 01303 } 01304 01305 uint8_t *thread_joiner_application_pending_config_tlv_list_get(uint8_t interface_id, uint16_t *length) 01306 { 01307 uint16_t data_list_len = 0; 01308 uint8_t *result_ptr; 01309 uint8_t *return_ptr; 01310 01311 thread_joiner_t *this = thread_joiner_find(interface_id); 01312 if (!this || !this->pending_configuration_ptr) { 01313 return NULL; 01314 } 01315 *length = 0; 01316 thread_meshcop_tlv_list_generate(this->pending_configuration_ptr->data, this->pending_configuration_ptr->length, NULL, &data_list_len); 01317 if (data_list_len == 0){ 01318 return NULL; 01319 } 01320 01321 /* Add also room for pending timestamp */ 01322 *length = data_list_len + 1; 01323 result_ptr = return_ptr = ns_dyn_mem_alloc(*length); 01324 01325 if (!result_ptr) { 01326 return NULL; 01327 } 01328 01329 *result_ptr++ = MESHCOP_TLV_PENDING_TIMESTAMP; 01330 01331 thread_meshcop_tlv_list_generate(this->pending_configuration_ptr->data, this->pending_configuration_ptr->length, result_ptr, &data_list_len); 01332 01333 return return_ptr; 01334 } 01335 01336 void thread_joiner_application_pending_config_add_missing_fields(uint8_t interface_id) 01337 { 01338 thread_joiner_t *this = thread_joiner_find(interface_id); 01339 if (!this || !this->pending_configuration_ptr) { 01340 return; 01341 } 01342 //TODO Specification open here 01343 // a) copy only mandatory fields 01344 // b) copy everything but remove zero length tlvs 01345 //configuration_set_copy_mandatory(this->pending_configuration_ptr, this->active_configuration_ptr); 01346 configuration_set_copy_missing(this->pending_configuration_ptr, this->active_configuration_ptr); 01347 configuration_set_remove_null_tlv(this->pending_configuration_ptr); 01348 } 01349 01350 01351 bool thread_joiner_application_old_config_exists(int8_t interface_id) 01352 { 01353 thread_joiner_t *this = thread_joiner_find(interface_id); 01354 if (!this || !this->old_active_configuration_ptr) { 01355 return false; 01356 } 01357 return true; 01358 } 01359 void thread_joiner_application_old_config_delete(int8_t interface_id) 01360 { 01361 thread_joiner_t *this = thread_joiner_find(interface_id); 01362 if (!this || !this->old_active_configuration_ptr) { 01363 return; 01364 } 01365 ns_dyn_mem_free(this->old_active_configuration_ptr); 01366 this->old_active_configuration_ptr = NULL; 01367 01368 return; 01369 } 01370 int thread_joiner_application_old_config_activate(int8_t interface_id) 01371 { 01372 thread_joiner_t *this = thread_joiner_find(interface_id); 01373 if (!this || !this->old_active_configuration_ptr) { 01374 return -1; 01375 } 01376 this->active_configuration_ptr = this->old_active_configuration_ptr; 01377 this->old_active_configuration_ptr = NULL; 01378 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01379 link_configuration_trace(this->configuration_ptr); 01380 01381 return 0; 01382 } 01383 01384 void thread_joiner_application_pending_config_delete(int8_t interface_id) 01385 { 01386 thread_joiner_t *this = thread_joiner_find(interface_id); 01387 if (!this || !this->pending_configuration_ptr) { 01388 return; 01389 } 01390 ns_dyn_mem_free(this->pending_configuration_ptr); 01391 this->pending_configuration_ptr = NULL; 01392 thread_joiner_application_configuration_nvm_save(interface_id); 01393 return; 01394 } 01395 01396 void thread_joiner_application_next_pending_config_save(int8_t interface_id) 01397 { 01398 thread_joiner_t *this = thread_joiner_find(interface_id); 01399 if (!this || !this->pending_configuration_ptr) { 01400 return; 01401 } 01402 this->next_pending_configuration_ptr = configuration_set_copy(this->pending_configuration_ptr); 01403 if (!this->next_pending_configuration_ptr) { 01404 tr_error("next pending configuration creation failed"); 01405 } 01406 return; 01407 } 01408 bool thread_joiner_application_next_pending_config_exists(int8_t interface_id) 01409 { 01410 thread_joiner_t *this = thread_joiner_find(interface_id); 01411 if (!this || !this->next_pending_configuration_ptr) { 01412 return false; 01413 } 01414 return true; 01415 } 01416 01417 uint16_t thread_joiner_application_next_pending_config_length(int8_t interface_id) 01418 { 01419 uint16_t response_len = 0; 01420 thread_joiner_t *this = thread_joiner_find(interface_id); 01421 if (!this || !this->next_pending_configuration_ptr) { 01422 return 0; 01423 } 01424 response_len += 2 + 8; // Pending timestamp 01425 response_len += 2 + 4; // delay timer 01426 response_len += this->next_pending_configuration_ptr->length; 01427 return response_len; 01428 } 01429 01430 uint8_t *thread_joiner_application_next_pending_config_build(int8_t interface_id, uint8_t *ptr) 01431 { 01432 thread_joiner_t *this = thread_joiner_find(interface_id); 01433 if (!this || !this->next_pending_configuration_ptr) { 01434 return ptr; 01435 } 01436 memcpy(ptr, this->next_pending_configuration_ptr->data, this->next_pending_configuration_ptr->length ); 01437 ptr +=this->next_pending_configuration_ptr->length; 01438 ptr = thread_meshcop_tlv_data_write_uint64(ptr,MESHCOP_TLV_PENDING_TIMESTAMP, this->next_pending_configuration_ptr->timestamp); 01439 ptr = thread_meshcop_tlv_data_write_uint32(ptr,MESHCOP_TLV_DELAY_TIMER, this->next_pending_configuration_ptr->timeout_in_ms); 01440 return ptr; 01441 } 01442 void thread_joiner_application_next_pending_config_delete(int8_t interface_id) 01443 { 01444 thread_joiner_t *this = thread_joiner_find(interface_id); 01445 if (!this || !this->next_pending_configuration_ptr) { 01446 return; 01447 } 01448 ns_dyn_mem_free(this->next_pending_configuration_ptr); 01449 this->next_pending_configuration_ptr = NULL; 01450 01451 return; 01452 } 01453 void thread_joiner_application_next_active_config_save(int8_t interface_id) 01454 { 01455 thread_joiner_t *this = thread_joiner_find(interface_id); 01456 if (!this || !this->configuration_ptr) { 01457 return; 01458 } 01459 this->next_active_configuration_ptr = configuration_set_copy(this->active_configuration_ptr); 01460 if (!this->next_active_configuration_ptr) { 01461 tr_error("next pending configuration creation failed"); 01462 return; 01463 } 01464 return; 01465 } 01466 bool thread_joiner_application_next_active_config_exists(int8_t interface_id) 01467 { 01468 thread_joiner_t *this = thread_joiner_find(interface_id); 01469 if (!this || !this->next_active_configuration_ptr) { 01470 return false; 01471 } 01472 return true; 01473 } 01474 uint16_t thread_joiner_application_next_active_config_length(int8_t interface_id) 01475 { 01476 thread_joiner_t *this = thread_joiner_find(interface_id); 01477 if (!this || !this->next_active_configuration_ptr) { 01478 return 0; 01479 } 01480 return this->next_active_configuration_ptr->length; 01481 } 01482 01483 uint8_t *thread_joiner_application_next_active_config_write(int8_t interface_id, uint8_t *ptr) 01484 { 01485 thread_joiner_t *this = thread_joiner_find(interface_id); 01486 if (!this || !this->next_active_configuration_ptr) { 01487 return ptr; 01488 } 01489 memcpy(ptr, this->next_active_configuration_ptr->data, this->next_active_configuration_ptr->length ); 01490 ptr +=this->next_active_configuration_ptr->length; 01491 return ptr; 01492 } 01493 01494 void thread_joiner_application_next_active_config_delete(int8_t interface_id) 01495 { 01496 thread_joiner_t *this = thread_joiner_find(interface_id); 01497 if (!this || !this->next_active_configuration_ptr) { 01498 return; 01499 } 01500 ns_dyn_mem_free(this->next_active_configuration_ptr); 01501 this->next_active_configuration_ptr = NULL; 01502 01503 return; 01504 } 01505 01506 device_configuration_s *thread_joiner_application_get_device_config(int8_t interface_id) 01507 { 01508 thread_joiner_t *this = thread_joiner_find(interface_id); 01509 if (!this) { 01510 return NULL; 01511 } 01512 return this->device_configuration_ptr; 01513 } 01514 01515 int thread_joiner_application_link_configuration_store(int8_t interface_id, link_configuration_s *link_config) 01516 { 01517 thread_joiner_t *this = thread_joiner_get(interface_id); 01518 01519 if (!link_config || !this) { 01520 return -1; 01521 } 01522 01523 if (!this->configuration_ptr) { 01524 this->configuration_ptr = link_configuration_create(); 01525 } 01526 01527 thread_joiner_application_validate_settings(this);// Generate all random information 01528 configuration_set_generate(this->active_configuration_ptr, link_config); 01529 link_configuration_update(this->configuration_ptr, this->active_configuration_ptr->data, this->active_configuration_ptr->length); 01530 this->configuration_ptr->key_sequence = link_config->key_sequence; 01531 this->configuration_valid = true; 01532 link_configuration_trace(this->configuration_ptr); 01533 01534 // store link configuration to NVM. This also stores pending configuration and some other parameters! 01535 return thread_joiner_application_configuration_nvm_save(this->interface_id); 01536 } 01537 01538 int thread_joiner_application_link_configuration_delete(int8_t interface_id) 01539 { 01540 thread_joiner_t *this = thread_joiner_get(interface_id); 01541 01542 // delete link configuration from NVM 01543 return thread_joiner_application_nvm_link_config_delete(this); 01544 } 01545 01546 bool thread_joiner_application_nvm_link_configuration_load(int8_t interface_id) 01547 { 01548 thread_joiner_t *this = thread_joiner_find(interface_id); 01549 if (this && this->nvm_link_configuration_load == true) { 01550 this->nvm_link_configuration_load = false; 01551 if (thread_joiner_application_nvm_link_config_read(this) == 0) { 01552 return true; 01553 } else { 01554 tr_error("Failed to read link configuration settings from NVM"); 01555 } 01556 } 01557 return false; 01558 } 01559 01560 int thread_joiner_application_provisioning_set(int8_t interface_id, thread_provisioning_status_e status) 01561 { 01562 thread_joiner_t *this = thread_joiner_find(interface_id); 01563 if (this) { 01564 this->provisioning_done = status; 01565 if (status == PROVISIONING_STATUS_REJECTED) { 01566 // If commissioner rejects us retry done after some time -> state is changed back to not done 01567 this->provisioning_timeout = randLIB_get_random_in_range(20,120); 01568 } else { 01569 this->provisioning_timeout = 0; 01570 } 01571 } 01572 return 0; 01573 } 01574 01575 thread_provisioning_status_e thread_joiner_application_provisioning_get(int8_t interface_id) 01576 { 01577 thread_joiner_t *this = thread_joiner_find(interface_id); 01578 if (this) { 01579 return this->provisioning_done; 01580 } 01581 return PROVISIONING_STATUS_NOT_DONE; 01582 } 01583 01584 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) 01585 { 01586 int ret = -1; 01587 tr_debug("Thread joiner security started"); 01588 (void)address; 01589 (void)port; 01590 01591 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01592 01593 if( this ){ 01594 memcpy(pw, this->device_configuration_ptr->PSKd_ptr, this->device_configuration_ptr->PSKd_len ); 01595 *pw_len = this->device_configuration_ptr->PSKd_len; 01596 ret = 0; 01597 // ret = coap_service_security_key_set( service_id, address, port, 01598 // this->device_configuration_ptr->PSKd_ptr, 01599 // this->device_configuration_ptr->PSKd_len ); 01600 } 01601 01602 return ret; 01603 } 01604 01605 int joiner_application_security_done_cb(int8_t service_id, uint8_t address[16], uint8_t keyblock[40]) 01606 { 01607 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01608 uint8_t kek[32]; 01609 int ret; 01610 01611 tr_debug("Thread joiner security done service: %d, address: %s", service_id, trace_ipv6(address)); 01612 if (!this) { 01613 return -1; 01614 } 01615 01616 ns_sha256(keyblock, 40, kek); 01617 01618 ret = thread_commissioning_if_pairwise_key_add(this->interface_id, 10000, &address[8], kek); 01619 if (ret) { 01620 tr_debug("pairwise key set failed %d", ret); 01621 //TODO error? 01622 } 01623 thread_commissioning_if_enable_security(this->interface_id); 01624 return 0; 01625 } 01626 01627 static void thread_joiner_attach_cb(void* arg) 01628 { 01629 thread_joiner_t *this = arg; 01630 tr_debug("Attach to new network"); 01631 if (!this){ 01632 return; 01633 } 01634 // Cleaning up the joining information 01635 thread_joiner_application_commission_clean(this); 01636 if (this->done_cb) {// This is successfull 01637 this->done_cb(this->interface_id); 01638 } 01639 } 01640 static void thread_joiner_entrust_timeout_cb(void* arg) 01641 { 01642 thread_joiner_t *this = arg; 01643 tr_debug("No valid configuration received in time"); 01644 if (!this){ 01645 return; 01646 } 01647 // Cleaning up the joining information 01648 thread_joiner_application_commission_clean(this); 01649 if (this->done_cb) {// Failed 01650 this->done_cb(this->interface_id); 01651 } 01652 } 01653 01654 void thread_joiner_attach_if_needed(thread_joiner_t *this) 01655 { 01656 tr_debug("attach check"); 01657 if (this->finalisation_done && this->configuration_valid) { 01658 tr_debug("Start attach timer");// one second timer gives time for joiner router to get entrust response 01659 this->attach_timeout = eventOS_timeout_ms(thread_joiner_attach_cb, 1000, this); 01660 } else { 01661 tr_debug("Start entrust timeout");// 30 timer to get credentials 01662 this->entrust_timeout = eventOS_timeout_ms(thread_joiner_entrust_timeout_cb, 30000, this); 01663 } 01664 } 01665 01666 01667 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) 01668 { 01669 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01670 uint8_t result; 01671 (void)source_address; 01672 (void)source_port; 01673 01674 tr_debug("finalisation done"); 01675 01676 if (!this) { 01677 return -1; 01678 } 01679 01680 // CoAP message failed - try to reattach 01681 if(!response_ptr || !response_ptr->payload_ptr){ 01682 tr_debug("finalisation failed - no response"); 01683 goto error; 01684 } 01685 01686 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)); 01687 coap_service_close_secure_connection(service_id, this->parent_address, this->parent_port); 01688 // todo: free certificates 01689 if (1 <= thread_tmfcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &result)) { 01690 //Todo make attach 01691 this->finalisation_done = true; 01692 this->provisioning_done = PROVISIONING_STATUS_NOT_DONE; 01693 if (result == 1) { 01694 // If accepted no additional actions needed 01695 tr_debug("Provisioning done"); 01696 this->provisioning_done = PROVISIONING_STATUS_DONE; 01697 } 01698 thread_joiner_attach_if_needed(this); 01699 return 0; 01700 } 01701 thci_trace("joinerError"); 01702 tr_debug("finalisation rejected"); 01703 01704 error: 01705 //TODO cant delete as old configuration pointer is in use I quess 01706 // link_configuration_delete(this->configuration_ptr); 01707 thread_joiner_application_commission_clean(this); 01708 this->configuration_valid = false; 01709 this->done_cb(this->interface_id); 01710 blacklist_update(source_address, false); 01711 //This trigger re scan and we try to connect again 01712 //TODO this needs status code to allow blacklisting of thread network 01713 return 0; 01714 } 01715 static int thread_joiner_application_send_finalisation(thread_joiner_t *this, uint8_t parent_address[16], uint16_t port) 01716 { 01717 uint8_t *ptr, *data_ptr; 01718 uint16_t length; 01719 01720 tr_debug("Thread joiner finalisation send"); 01721 length = thread_joiner_application_device_configuration_length(this->device_configuration_ptr); 01722 length += 3;// State 01723 01724 data_ptr = ptr = ns_dyn_mem_alloc(length); 01725 if (!ptr) { 01726 tr_error("Failed to start Commissioning"); 01727 return -1; 01728 } 01729 ptr = thread_joiner_application_device_configuration_build(ptr, this->device_configuration_ptr); 01730 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 01731 01732 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)); 01733 coap_service_request_send(this->secure_coap_service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, parent_address, port, 01734 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); 01735 01736 ns_dyn_mem_free(data_ptr); 01737 01738 return 0; 01739 } 01740 01741 static uint8_t *thread_joiner_application_write_channel(uint8_t *ptr, uint16_t data) 01742 { 01743 *ptr++ = MESHCOP_TLV_CHANNEL; // type 01744 *ptr++ = 3; // length 01745 *ptr++ = 0; // channel page 01746 return common_write_16_bit(data, ptr); 01747 } 01748 01749 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) 01750 { 01751 thread_joiner_t *this = thread_joiner_find_by_service(service_id); 01752 (void)source_address; 01753 (void)source_port; 01754 01755 if (!this) { 01756 return -1; 01757 } 01758 01759 if (thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MASTER_KEY, NULL) < 16 || 01760 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, NULL) < 8 || 01761 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_XPANID, NULL) < 8 || 01762 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_NAME, NULL) == 0 || 01763 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PSKC, NULL) < 16 ) { 01764 // Absolutely minimum we must have is master secret to attach. 01765 // If commissioner wants to be connected we must have PSKc,Name,Xpanid 01766 // If there is some fields missing we could attach, but timestamp must be set to 0 which will then cause synchronization 01767 tr_debug("Not include all TLv's"); 01768 thci_trace("joinerError"); 01769 return -1; 01770 } 01771 uint8_t *result_ptr; 01772 memcpy(this->active_configuration_ptr->data,request_ptr->payload_ptr, request_ptr->payload_len); 01773 this->active_configuration_ptr->length = request_ptr->payload_len; 01774 01775 result_ptr = this->active_configuration_ptr->data + this->active_configuration_ptr->length; 01776 01777 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_ACTIVE_TIME_STAMP, NULL) == 0) { 01778 result_ptr = thread_meshcop_tlv_data_write_uint64(result_ptr,MESHCOP_TLV_ACTIVE_TIME_STAMP, 0); 01779 } 01780 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_XPANID, NULL) == 0) { 01781 result_ptr = thread_meshcop_tlv_data_write(result_ptr,MESHCOP_TLV_XPANID, 8, this->configuration_ptr->extented_pan_id ); 01782 } 01783 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_CHANNEL, NULL) == 0) { 01784 result_ptr = thread_joiner_application_write_channel(result_ptr, this->configuration_ptr->rfChannel); 01785 } 01786 if (thread_meshcop_tlv_find(this->active_configuration_ptr->data, this->active_configuration_ptr->length, MESHCOP_TLV_PANID, NULL) == 0) { 01787 result_ptr = thread_meshcop_tlv_data_write_uint16(result_ptr,MESHCOP_TLV_PANID, this->configuration_ptr->panId ); 01788 } 01789 01790 this->active_configuration_ptr->length = result_ptr - this->active_configuration_ptr->data; 01791 01792 // check if everything is present 01793 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))) { 01794 // Some fields are missing we need to sync settings during attach 01795 uint8_t *timestamp_ptr = NULL; 01796 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp_ptr); 01797 if (timestamp_ptr) { 01798 common_write_64_bit(0,timestamp_ptr); 01799 } 01800 } 01801 01802 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); 01803 01804 uint32_t network_key_seq = 0; 01805 if (thread_meshcop_tlv_data_get_uint32(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_KEY_SEQUENCE, &network_key_seq)) { 01806 this->configuration_ptr->key_sequence = network_key_seq; 01807 } 01808 01809 /*We must null out the master secret*/ 01810 #ifdef THREAD_THCI_SUPPORT 01811 uint8_t *master_secret_ptr; 01812 if (thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_NETWORK_MASTER_KEY, &master_secret_ptr) >= 16) { 01813 memset(master_secret_ptr,0,16); 01814 } 01815 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)); 01816 #endif 01817 01818 // save link configuration to NVM 01819 01820 thci_trace("joinerAccepted"); 01821 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data,this->active_configuration_ptr->length); 01822 this->configuration_valid = true; 01823 thread_joiner_application_configuration_nvm_save(this->interface_id); 01824 01825 link_configuration_trace(this->configuration_ptr); 01826 01827 #ifdef THREAD_THCI_SUPPORT 01828 thci_trace("Device - Joiner|Direction - sent|EUI - %s|Type - JOIN_ent.resp|Length - 0|Payload - ", trace_array(this->device_configuration_ptr->eui64,8)); 01829 #endif 01830 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); 01831 01832 //TODO Add delay timer of 3 seconds and then do attach 01833 thread_joiner_attach_if_needed(this); 01834 01835 return 0; 01836 } 01837 01838 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) 01839 { 01840 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01841 thread_joiner_t *this = thread_joiner_find(interface_id); 01842 if (!this || !done_cb || !cur) { 01843 return -1; 01844 } 01845 if (!this->configuration_ptr) { 01846 this->configuration_ptr = link_configuration_create(); 01847 } 01848 01849 if (!this->configuration_ptr) { 01850 tr_error("Commission start failed"); 01851 return -2; 01852 } 01853 this->configuration_valid = false; 01854 01855 01856 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 01857 coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_ENTRUST, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_joiner_application_entrust_recv_cb); 01858 01859 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); 01860 01861 tr_debug("start pskd commissioning: interface %d, parent: %s, port %d", interface_id, trace_ipv6(parent_address), joiner_port); 01862 // save initial information 01863 this->configuration_ptr->panId = panid; 01864 this->configuration_ptr->rfChannel = channel; 01865 if (xpanid) { 01866 memcpy(this->configuration_ptr->extented_pan_id, xpanid, 8); 01867 } 01868 01869 link_configuration_trace(this->configuration_ptr); 01870 //TODO this callback needs status for blacklist 01871 this->done_cb = done_cb; 01872 memcpy(this->parent_address,parent_address,16); 01873 this->parent_port = joiner_port; 01874 01875 thci_trace("joinerDtlsSessionStarted"); 01876 thread_joiner_application_send_finalisation(this, parent_address, joiner_port); 01877 return 0; 01878 } 01879 01880 int thread_joiner_application_configuration_nvm_save(int8_t interface_id) 01881 { 01882 tr_info("thread_joiner_application_configuration_nvm_save"); 01883 01884 thread_joiner_t *this = thread_joiner_find(interface_id); 01885 if (!this) { 01886 return -1; 01887 } 01888 01889 thread_nvm_store_device_configuration_write(this->device_configuration_ptr->extended_random_mac,this->device_configuration_ptr->mesh_local_eid); 01890 thread_nvm_store_pending_configuration_write(this->pending_configuration_ptr, sizeof(configuration_set_t)); 01891 thread_nvm_store_seq_counter_write(this->configuration_ptr->key_sequence); 01892 thread_nvm_store_active_configuration_write(this->active_configuration_ptr, sizeof(configuration_set_t)); 01893 01894 /* allow configuration to be read in bootstrap */ 01895 this->nvm_link_configuration_load = true; 01896 return 0; 01897 } 01898 01899 int thread_joiner_application_update_configuration(uint8_t interface_id, uint8_t *msg_ptr, uint16_t msg_len, bool include_missing_tlvs) 01900 { 01901 thread_joiner_t *this = thread_joiner_find(interface_id); 01902 configuration_set_t *configuration_ptr; 01903 if (!this) { 01904 return -1; 01905 } 01906 configuration_ptr = ns_dyn_mem_alloc(sizeof(configuration_set_t)); 01907 if (!configuration_ptr) { 01908 return -2; 01909 } 01910 memcpy(configuration_ptr,this->active_configuration_ptr,sizeof(configuration_set_t)); 01911 this->active_configuration_ptr->length = 0; 01912 configuration_set_add_all_fields(this->active_configuration_ptr,msg_ptr,msg_len, meshcop_active_set_ignore, sizeof(meshcop_active_set_ignore)); 01913 if (include_missing_tlvs) { 01914 configuration_set_copy_missing(this->active_configuration_ptr, configuration_ptr); 01915 configuration_set_remove_null_tlv(this->active_configuration_ptr); 01916 } else { 01917 configuration_set_copy_mandatory(this->active_configuration_ptr, configuration_ptr); 01918 } 01919 thread_meshcop_tlv_data_get_uint64(msg_ptr, msg_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, &this->active_configuration_ptr->timestamp); 01920 link_configuration_update(this->configuration_ptr,msg_ptr,msg_len); 01921 ns_dyn_mem_free(configuration_ptr); 01922 thread_joiner_application_configuration_nvm_save(interface_id); 01923 01924 return 0; 01925 } 01926 uint8_t *thread_joiner_application_active_config_tlv_list_get(uint8_t interface_id, uint16_t *length) 01927 { 01928 uint8_t *result_ptr; 01929 thread_joiner_t *this = thread_joiner_find(interface_id); 01930 if (!this || !this->active_configuration_ptr) { 01931 return NULL; 01932 } 01933 *length = 0; 01934 thread_meshcop_tlv_list_generate(this->active_configuration_ptr->data, this->active_configuration_ptr->length,NULL, length); 01935 if (*length == 0){ 01936 return NULL; 01937 } 01938 result_ptr = ns_dyn_mem_alloc(*length); 01939 if (!result_ptr) { 01940 } 01941 thread_meshcop_tlv_list_generate(this->active_configuration_ptr->data, this->active_configuration_ptr->length,result_ptr, length); 01942 01943 return result_ptr; 01944 } 01945 uint8_t *thread_joiner_application_active_config_params_get(uint8_t interface_id, uint16_t *length) 01946 { 01947 thread_joiner_t *this = thread_joiner_find(interface_id); 01948 if (!this || !this->active_configuration_ptr || !length) { 01949 return NULL; 01950 } 01951 *length = this->active_configuration_ptr->length; 01952 return this->active_configuration_ptr->data; 01953 } 01954 01955 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) 01956 { 01957 thread_joiner_t *this = thread_joiner_find(interface_id); 01958 if (!this || !this->active_configuration_ptr) { 01959 return 0; 01960 } 01961 return configuration_set_length(this->active_configuration_ptr, req_tlv_ptr, req_tlv_len, ignored_tlv_ptr, ignored_tlv_len); 01962 } 01963 01964 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) 01965 { 01966 thread_joiner_t *this = thread_joiner_find(interface_id); 01967 if (!this || !this->active_configuration_ptr) { 01968 return ptr; 01969 } 01970 return configuration_set_write(this->active_configuration_ptr, ptr,req_tlv_ptr,req_tlv_len, ignored_tlv_ptr,ignored_tlv_len); 01971 } 01972 01973 int thread_joiner_application_device_configuration_length(device_configuration_s *device_configuration) 01974 { 01975 int length; 01976 01977 if (!device_configuration) { 01978 return 0; 01979 } 01980 length = 2 + 1 + 2 + 6 + 2 + device_configuration->vendor_data_len;// Status + Stack version + vendor data 01981 if (device_configuration->provisioning_uri_ptr) { 01982 length += 2 + strlen(device_configuration->provisioning_uri_ptr); 01983 } 01984 if (device_configuration->vendor_name_ptr) { 01985 length += 2 + strlen(device_configuration->vendor_name_ptr); 01986 } 01987 if (device_configuration->vendor_model_ptr) { 01988 length += 2 + strlen(device_configuration->vendor_model_ptr); 01989 } 01990 if (device_configuration->vendor_sw_version_ptr) { 01991 length += 2 + strlen(device_configuration->vendor_sw_version_ptr); 01992 } 01993 return length; 01994 } 01995 01996 uint8_t *thread_joiner_application_device_configuration_build(uint8_t *ptr, device_configuration_s *device_configuration) 01997 { 01998 if (!ptr || !device_configuration) { 01999 return ptr; 02000 } 02001 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_STACK_VERSION, 6, device_configuration->vendor_stack_version); 02002 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_DATA, 02003 device_configuration->vendor_data_len, 02004 device_configuration->vendor_data_ptr); 02005 02006 if (device_configuration->provisioning_uri_ptr) { 02007 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_PROVISIONING_URL, 02008 strlen(device_configuration->provisioning_uri_ptr), 02009 (uint8_t *)device_configuration->provisioning_uri_ptr); 02010 } 02011 if (device_configuration->vendor_name_ptr) { 02012 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_NAME, 02013 strlen(device_configuration->vendor_name_ptr), 02014 (uint8_t *)device_configuration->vendor_name_ptr); 02015 } 02016 if (device_configuration->vendor_model_ptr) { 02017 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_MODEL, 02018 strlen(device_configuration->vendor_model_ptr), 02019 (uint8_t *)device_configuration->vendor_model_ptr); 02020 } 02021 if (device_configuration->vendor_sw_version_ptr) { 02022 ptr = thread_tmfcop_tlv_data_write(ptr, MESHCOP_TLV_VENDOR_SW_VERSION, 02023 strlen(device_configuration->vendor_sw_version_ptr), 02024 (uint8_t *)device_configuration->vendor_sw_version_ptr); 02025 } 02026 return ptr; 02027 } 02028 02029 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) 02030 { 02031 thread_joiner_t *this = thread_joiner_find(interface_id); 02032 uint64_t timestamp = 0; 02033 02034 if (!this) { 02035 return -1; 02036 } 02037 configuration_set_add_all_fields(this->active_configuration_ptr, data_ptr, data_len, ignore_ptr, ingore_len); 02038 thread_meshcop_tlv_data_get_uint64(data_ptr, data_len, MESHCOP_TLV_ACTIVE_TIME_STAMP, ×tamp); 02039 thread_joiner_application_active_timestamp_set(this->interface_id, timestamp); 02040 link_configuration_update(this->configuration_ptr,this->active_configuration_ptr->data,this->active_configuration_ptr->length); 02041 this->configuration_valid = true; 02042 thread_joiner_application_configuration_nvm_save(this->interface_id); 02043 02044 link_configuration_trace(this->configuration_ptr); 02045 02046 return 0; 02047 } 02048 #endif 02049
Generated on Fri Jul 22 2022 04:54:03 by
1.7.2
