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