Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
thread_commissioning_api.c
00001 /* 00002 * Copyright (c) 2015-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 /*Nanostack includes*/ 00031 #include "nsconfig.h" 00032 00033 #include <string.h> 00034 #include "ns_types.h" 00035 #include "ns_list.h" 00036 #include "ns_trace.h" 00037 #include "nsdynmemLIB.h" 00038 #include "common_functions.h" 00039 #include "ns_sha256.h" 00040 00041 /*thread includes*/ 00042 #include "thread_config.h" 00043 #include "thread_management_if.h" 00044 #include "thread_meshcop_lib.h" 00045 #include "thread_management_api.h" 00046 #include "thread_commissioning_api.h" 00047 #include "thread_beacon.h" 00048 /*Private includes*/ 00049 #include "6LoWPAN/Thread/thread_common.h" 00050 #include "6LoWPAN/Thread/thread_management_internal.h" 00051 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"// Get coordinator address 00052 00053 #define TRACE_GROUP TRACE_GROUP_THREAD_COMMISSIONING_API 00054 #ifdef HAVE_THREAD 00055 00056 #include "coap_service_api.h" 00057 00058 typedef struct device { 00059 uint8_t PSKd[32]; 00060 uint8_t kek[32];// shal libs needs 32 bytes kek is first 16 00061 uint8_t EUI64[8]; 00062 uint8_t IID[8]; 00063 thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr; 00064 uint16_t joiner_router_rloc; 00065 uint8_t PSKd_len; 00066 bool send_kek: 1; 00067 bool short_eui64: 1;/*< Use short format for bloom filter creation*/ 00068 00069 ns_list_link_t link; 00070 } device_t; 00071 00072 typedef NS_LIST_HEAD (device_t, link) device_list_t; 00073 00074 typedef struct commissioner_entry { 00075 device_list_t device_list; 00076 uint8_t destination_address[16]; 00077 uint8_t PSKc_ptr[16]; 00078 thread_commissioning_status_cb *status_cb_ptr; 00079 uint16_t destination_port; 00080 uint16_t session_id; 00081 int8_t management_instance; 00082 int8_t interface_id; 00083 int8_t coap_service_id; 00084 int8_t coap_secure_service_id; 00085 int8_t coap_virtual_service_id; 00086 bool registered: 1; 00087 bool native_commissioner: 1; 00088 00089 ns_list_link_t link; 00090 } commissioner_t; 00091 00092 static NS_LIST_DEFINE(instance_list, commissioner_t, link); 00093 00094 const uint8_t any_device[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 00095 00096 /* 00097 * Commissioned device handlers; 00098 */ 00099 static device_t *device_create(commissioner_t *commissioner_ptr) 00100 { 00101 device_t *device_ptr = ns_dyn_mem_alloc(sizeof(device_t)); 00102 if (device_ptr) { 00103 memset(device_ptr, 0, sizeof(device_t)); 00104 device_ptr->send_kek = false; 00105 device_ptr->joining_device_cb_ptr = NULL; 00106 ns_list_add_to_start(&commissioner_ptr->device_list, device_ptr); 00107 } 00108 return device_ptr; 00109 } 00110 00111 static void device_delete(commissioner_t *commissioner_ptr, device_t *device_ptr) 00112 { 00113 if (device_ptr) { 00114 ns_list_remove(&commissioner_ptr->device_list, device_ptr); 00115 ns_dyn_mem_free(device_ptr); 00116 } 00117 return; 00118 } 00119 00120 static device_t *device_find(commissioner_t *commissioner_ptr, uint8_t EUI64[8]) 00121 { 00122 device_t *this = NULL; 00123 if (!commissioner_ptr || !EUI64) { 00124 return NULL; 00125 } 00126 00127 ns_list_foreach(device_t, cur_ptr, &commissioner_ptr->device_list) { 00128 if (memcmp(cur_ptr->EUI64, EUI64, 8) == 0) { 00129 this = cur_ptr; 00130 break; 00131 } 00132 } 00133 return this; 00134 } 00135 00136 static device_t *device_find_by_iid(commissioner_t *commissioner_ptr, uint8_t IID[8]) 00137 { 00138 device_t *this = NULL; 00139 if (!IID) { 00140 return NULL; 00141 } 00142 ns_list_foreach(device_t, cur_ptr, &commissioner_ptr->device_list) { 00143 tr_debug("device iid %s and commissioner iid %s", trace_array(cur_ptr->IID,8),trace_array(IID,8)); 00144 if (memcmp(cur_ptr->IID, IID, 8) == 0) { 00145 this = cur_ptr; 00146 break; 00147 } 00148 } 00149 return this; 00150 } 00151 #define device_get_first(commissioner) ns_list_get_first(&commissioner->device_list) 00152 00153 00154 /* Commissioner class handlers*/ 00155 static commissioner_t *commissioner_find(int8_t interface_id) 00156 { 00157 commissioner_t *this = NULL; 00158 ns_list_foreach(commissioner_t, cur_ptr, &instance_list) { 00159 if (cur_ptr->interface_id == interface_id) { 00160 this = cur_ptr; 00161 break; 00162 } 00163 } 00164 return this; 00165 } 00166 static commissioner_t *commissioner_find_by_service(int8_t service_id) 00167 { 00168 commissioner_t *this = NULL; 00169 ns_list_foreach(commissioner_t, cur_ptr, &instance_list) { 00170 if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id) { 00171 this = cur_ptr; 00172 break; 00173 } 00174 } 00175 return this; 00176 } 00177 static commissioner_t *commissioner_create(int8_t interface_id) 00178 { 00179 commissioner_t *this = ns_dyn_mem_alloc(sizeof(commissioner_t)); 00180 if (this) { 00181 memset(this, 0, sizeof(commissioner_t)); 00182 this->interface_id = interface_id; 00183 this->registered = false; 00184 ns_list_init(&this->device_list); 00185 ns_list_add_to_start(&instance_list, this); 00186 } 00187 return this; 00188 } 00189 00190 static void commissioner_delete(commissioner_t *this) 00191 { 00192 if (this) { 00193 device_t *device_ptr = device_get_first(this); 00194 while (device_ptr != NULL) { 00195 device_delete(this, device_ptr); 00196 device_ptr = device_get_first(this); 00197 } 00198 ns_list_remove(&instance_list, this); 00199 ns_dyn_mem_free(this); 00200 } 00201 return; 00202 } 00203 00204 /*Internal helper functions*/ 00205 static int commissioning_meshcop_map_state(commissioning_state_e state) 00206 { 00207 if (state == COMMISSIONING_STATE_ACCEPT) { 00208 return 1; 00209 } else if (state == COMMISSIONING_STATE_PENDING) { 00210 return 0; 00211 } 00212 00213 return -1; 00214 } 00215 00216 00217 static int commission_finalisation_resp_send(int8_t coap_service_id, device_t *device_ptr, sn_coap_hdr_s *request_ptr, commissioning_state_e state) 00218 { 00219 commissioner_t *this = commissioner_find_by_service(coap_service_id); 00220 uint8_t payload[11];// 4 + 1 + 4 + 2 00221 uint8_t *ptr; 00222 00223 if (!this || !request_ptr || !device_ptr) { 00224 return -1; 00225 } 00226 00227 ptr = payload; 00228 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, (uint8_t)commissioning_meshcop_map_state(state)); 00229 00230 thci_trace("Device - Comm|Direction - sent|EUI - %s|Type - JOIN_FIN.resp|Length - %d|Payload - %s",trace_array(device_ptr->EUI64,8), (int)(ptr - payload), trace_array(payload, ptr - payload)); 00231 tr_debug("finalisation response send state:%d value:%d ", state, (uint8_t)commissioning_meshcop_map_state(state)); 00232 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload); 00233 return 0; 00234 } 00235 00236 /* 00237 * Callback functions 00238 */ 00239 00240 static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00241 { 00242 commissioner_t *this = commissioner_find_by_service(service_id); 00243 commissioning_state_e state = COMMISSIONING_STATE_REJECT; 00244 uint16_t session_id = 0; 00245 uint8_t *ptr; 00246 (void) source_address; 00247 (void) source_port; 00248 00249 tr_debug("Thread Petition response received service %d",service_id); 00250 if (!this) { 00251 return -1; 00252 } 00253 00254 if (!response_ptr || !response_ptr->payload_ptr || response_ptr->payload_len < 1) { 00255 tr_debug("invalid response"); 00256 thci_trace("commissionerPetitionError"); 00257 goto user_response; 00258 } 00259 00260 if ((2 <= thread_meshcop_tlv_data_get_uint16(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) && 00261 (1 <= thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &ptr) && *ptr == 1)) { 00262 state = COMMISSIONING_STATE_ACCEPT; 00263 thci_trace("commissionerPetitionAccepted"); 00264 this->session_id = session_id; 00265 this->registered = true; 00266 //@TODO order keep alive timer for the message and start sending it periodically 00267 } 00268 tr_debug("petition response session_id: %d state:%d",session_id, state); 00269 00270 user_response: 00271 if (state == COMMISSIONING_STATE_REJECT) { 00272 thci_trace("commissionerPetitionRejected"); 00273 } 00274 if (this->status_cb_ptr) { 00275 this->status_cb_ptr(this->interface_id, this->session_id, state); 00276 } 00277 return 0; 00278 } 00279 00280 static int commissioning_keep_alive_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00281 { 00282 commissioner_t *this = commissioner_find_by_service(service_id); 00283 uint8_t *ptr; 00284 (void) source_address; 00285 (void) source_port; 00286 00287 tr_debug("Thread keep alive response received"); 00288 if (!this) { 00289 tr_warn("commissioner service missing!"); 00290 thci_trace("commissionerError"); 00291 return -1; 00292 } 00293 if (!response_ptr) { 00294 tr_warn("commission ka response without ptr!"); 00295 thci_trace("commissionerError"); 00296 return -1; 00297 } 00298 00299 if (1 <= thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &ptr) && *ptr == 1) { 00300 // only handle success 00301 return 0; 00302 } 00303 00304 this->session_id = 0; 00305 this->registered = false; 00306 if (this->status_cb_ptr) { 00307 this->status_cb_ptr(this->interface_id, this->session_id, COMMISSIONING_STATE_REJECT); 00308 } 00309 00310 return -2; 00311 } 00312 00313 static int commission_finalisation_req_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00314 { 00315 commissioner_t *this = commissioner_find_by_service(service_id); 00316 uint8_t address[16]; 00317 device_t *device_ptr; 00318 int ret = -1;// always reject 00319 (void) source_port; 00320 00321 tr_debug("joiner finalisation recv addr %s", trace_ipv6(source_address)); 00322 if (!this || !source_address || !request_ptr) { 00323 return -1; 00324 } 00325 00326 device_ptr = device_find_by_iid(this, &source_address[8]); 00327 if (device_ptr) { 00328 ret = 0; // accept even without application confirmation 00329 } 00330 thci_trace("Device - Comm|Direction - recv|EUI - %s|Type - JOIN_FIN.req|Length - %d|Payload - %s",trace_array(device_ptr->EUI64,8), request_ptr->payload_len, trace_array(request_ptr->payload_ptr, request_ptr->payload_len)); 00331 memcpy(address,source_address,16); 00332 00333 if (device_ptr) { 00334 if (device_ptr->joining_device_cb_ptr) { 00335 ret = device_ptr->joining_device_cb_ptr(this->interface_id, &source_address[8], request_ptr->payload_ptr, request_ptr->payload_len); 00336 } 00337 00338 device_ptr->send_kek = true; 00339 } 00340 00341 if (ret == 0) { 00342 thci_trace("commissionerJoinerAccepted"); 00343 } 00344 00345 commission_finalisation_resp_send(service_id, device_ptr, request_ptr, ret == 0 ? COMMISSIONING_STATE_ACCEPT : COMMISSIONING_STATE_REJECT); 00346 coap_service_close_secure_connection(service_id, address, source_port); 00347 00348 return 0; 00349 } 00350 static int commission_application_provision_req_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00351 { 00352 commissioner_t *this = commissioner_find_by_service(service_id); 00353 uint8_t payload[11];// 4 + 1 + 4 + 2 00354 uint8_t *ptr; 00355 00356 (void) source_port; 00357 00358 tr_debug("joiner application provisioning recv addr %s", trace_ipv6(source_address)); 00359 if (!this || !source_address || !request_ptr) { 00360 return -1; 00361 } 00362 00363 thci_trace("Device - Comm|Direction - recv|EUI - %s|Type - JOIN_APP.req|Length - %d|Payload - %s",trace_array(&source_address[8],8), request_ptr->payload_len, trace_array(request_ptr->payload_ptr, request_ptr->payload_len)); 00364 00365 ptr = payload; 00366 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 1); 00367 00368 thci_trace("Device - Comm|Direction - sent|EUI - %s|Type - JOIN_APP.resp|Length - %d|Payload - %s",trace_array(&source_address[8],8), (int)(ptr - payload), trace_array(payload, ptr - payload)); 00369 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload); 00370 return 0; 00371 } 00372 00373 static int commission_dataset_changed_notify_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00374 { 00375 (void)source_address; 00376 (void)source_port; 00377 00378 tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address)); 00379 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0); 00380 00381 return 0; 00382 } 00383 00384 static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr,device_list_t device_list, int *steering_tlv_max_length) 00385 { 00386 memset(bloom_filter_ptr,0,*steering_tlv_max_length); 00387 ns_list_foreach(device_t, cur_ptr, &device_list) 00388 { 00389 if (memcmp(cur_ptr->EUI64, any_device, 8) != 0) 00390 { 00391 tr_debug("eui64 used on commissioning side = %s",trace_array(cur_ptr->EUI64,8)); 00392 cur_ptr->IID[0] |= 2; //Changed IID to MAC extended address for bloom filter calculation 00393 thread_beacon_calculate_bloom_filter(bloom_filter_ptr,*steering_tlv_max_length,cur_ptr->IID, 8); 00394 cur_ptr->IID[0] &= ~2;//Restore IID 00395 } 00396 else 00397 { 00398 bloom_filter_ptr[0] = 0xff; 00399 *steering_tlv_max_length = 1; 00400 break; 00401 } 00402 } 00403 00404 return bloom_filter_ptr; 00405 } 00406 00407 static int commission_steering_data_update(commissioner_t *this) 00408 { 00409 //variable for steering tlv length - maximum possible length is 16 bytes - section 8.10.1.9 Max length 00410 int steering_tlv_length = 16; 00411 uint8_t bloom_filter_ptr[16]; 00412 int ret; 00413 00414 //bloom filter calculation function call 00415 bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length); 00416 tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16)); 00417 ret = thread_management_set_steering_data(this->management_instance, this->session_id,bloom_filter_ptr, steering_tlv_length, NULL); 00418 if (ret) { 00419 tr_warn("Steering data set failed %d", ret); 00420 return -1; 00421 } 00422 00423 return 0; 00424 } 00425 00426 /* 00427 * These functions are the relay endpoint for commissioner device. 00428 * this can be either: 00429 * secure native commissioner 00430 * or unsecure native commissioner 00431 * */ 00432 static int commission_relay_rx_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00433 { 00434 commissioner_t *this = commissioner_find_by_service(service_id); 00435 uint8_t joiner_address[16] = { 0xfe, 0x80 }; 00436 uint8_t *joiner_iid_ptr; 00437 uint8_t *udp_ptr; 00438 uint16_t udp_len; 00439 uint16_t joiner_port; 00440 uint16_t joiner_router_rloc; 00441 device_t *device_ptr; 00442 (void) source_port; 00443 00444 if (!this || !source_address || !request_ptr) { 00445 return -1; // goto error response 00446 } 00447 00448 if ((0 == (udp_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_ptr))) || 00449 (8 > thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &joiner_iid_ptr)) || 00450 (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &joiner_port)) || 00451 (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, &joiner_router_rloc))) { 00452 tr_warn("Corrupted relay packet received"); 00453 return -1; 00454 } 00455 00456 memcpy(&joiner_address[8], joiner_iid_ptr, 8); 00457 tr_debug("Relay RX from (%x) addr %s, port %d, len:%d", joiner_router_rloc, trace_ipv6(joiner_address), joiner_port, udp_len); 00458 00459 device_ptr = device_find_by_iid(this, joiner_iid_ptr); 00460 if (!device_ptr) { 00461 tr_warn("unknown device connected"); 00462 //Interop HACK 00463 device_ptr = device_find(this, (uint8_t*)any_device); 00464 if (!device_ptr) { 00465 tr_warn("No catch all device added"); 00466 return -1; 00467 } 00468 00469 memcpy(device_ptr->IID, &joiner_address[8], 8); 00470 memcpy(device_ptr->EUI64, &joiner_address[8], 8); // This is wrong as we cannot reverse the SHA1 But ok For Any device 00471 device_ptr->EUI64[0] ^= 2;// We are searching for list of eui64 so need to flip 00472 if (commission_steering_data_update(this) != 0) { 00473 return -1; 00474 } 00475 tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8)); 00476 } 00477 device_ptr->joiner_router_rloc = joiner_router_rloc; 00478 coap_service_virtual_socket_recv(this->coap_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len); 00479 return -1; // no response sent 00480 } 00481 00482 static int commission_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len) 00483 { 00484 commissioner_t *this = commissioner_find_by_service(service_id); 00485 uint8_t destination_address[16]; 00486 uint16_t destination_port; 00487 device_t *device_ptr; 00488 uint8_t *payload_ptr; 00489 uint8_t *ptr; 00490 uint16_t payload_len; 00491 uint8_t destination_service_id; 00492 00493 tr_debug("Relay RX send addr %s, port %d, len:%d", trace_ipv6(destination_addr_ptr), port, data_len); 00494 if (!this || !destination_addr_ptr || !data_ptr) { 00495 return -1; 00496 } 00497 00498 device_ptr = device_find_by_iid(this, &destination_addr_ptr[8]); 00499 if (!device_ptr) { 00500 return -2; 00501 } 00502 payload_len = 4 + data_len + 4 + 8 + 4 + 2; 00503 00504 if (device_ptr->send_kek) { 00505 payload_len += 4 + 16; 00506 } 00507 00508 payload_ptr = ns_dyn_mem_alloc(payload_len); 00509 if (!payload_ptr) { 00510 return -3; 00511 } 00512 if (this->native_commissioner){ 00513 destination_service_id = this->coap_secure_service_id; 00514 memcpy(destination_address,this->destination_address,16); 00515 destination_port = this->destination_port; 00516 } else { 00517 memset(destination_address,0,16); 00518 destination_service_id = this->coap_service_id; 00519 thread_management_get_ml_prefix(this->interface_id, destination_address); 00520 common_write_16_bit(0xfffe, &destination_address[11]); 00521 common_write_16_bit(device_ptr->joiner_router_rloc, &destination_address[14]); 00522 destination_port = THREAD_MANAGEMENT_PORT; 00523 } 00524 00525 tr_debug("Relay destination %s:%d", trace_ipv6(destination_address), destination_port); 00526 00527 ptr = payload_ptr; 00528 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr); 00529 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &destination_addr_ptr[8]); 00530 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, port); 00531 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, device_ptr->joiner_router_rloc); 00532 00533 if (device_ptr->send_kek) { 00534 tr_debug("Relay RX Send KEK"); 00535 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ROUTER_KEK, 16, device_ptr->kek); 00536 device_ptr->send_kek = false; 00537 } 00538 00539 coap_service_request_send(destination_service_id, COAP_REQUEST_OPTIONS_NONE, destination_address, destination_port, 00540 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_RELAY_TRANSMIT, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); 00541 00542 ns_dyn_mem_free(payload_ptr); 00543 00544 return 0; 00545 } 00546 00547 static int commissioning_security_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]) 00548 { 00549 commissioner_t *this = commissioner_find_by_service(service_id); 00550 device_t *device_ptr; 00551 00552 if (!this) { 00553 return -1; 00554 } 00555 00556 tr_debug("Commissioner security done addr %s keyblock %s", trace_ipv6(address), trace_array(keyblock, 40)); 00557 device_ptr = device_find_by_iid(this, &address[8]); 00558 if (!device_ptr) { 00559 tr_debug("Commissioner device not found"); 00560 thci_trace("commissionerBrError"); 00561 return -1; 00562 } 00563 ns_sha256(keyblock, 40, device_ptr->kek); 00564 00565 return 0; 00566 } 00567 00568 static int joiner_commissioner_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len) 00569 { 00570 int ret = -1; 00571 (void)port; 00572 tr_info("commissionerJoinerDtlsSessionStarted"); 00573 00574 commissioner_t *this = commissioner_find_by_service(service_id); 00575 00576 if (!this) { 00577 return ret; 00578 } 00579 00580 device_t *device_ptr = device_find_by_iid(this, &address[8]); 00581 00582 if( device_ptr ){ 00583 memcpy(pw, device_ptr->PSKd, device_ptr->PSKd_len ); 00584 *pw_len = device_ptr->PSKd_len; 00585 ret = 0; 00586 // ret = coap_service_security_key_set( service_id, address, port, device_ptr->PSKd, device_ptr->PSKd_len ); 00587 } 00588 00589 return ret; 00590 } 00591 00592 static int commissioner_br_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len) 00593 { 00594 int ret = -1; 00595 (void)address; 00596 (void)port; 00597 tr_info("commissionerBrDtlsSessionStarted"); 00598 commissioner_t *this = commissioner_find_by_service(service_id); 00599 if(this){ 00600 memcpy(pw, this->PSKc_ptr, 16 ); 00601 *pw_len = 16; 00602 ret = 0; 00603 // ret = coap_service_security_key_set( service_id, address, port, this->PSKc_ptr, this->PSKc_len ); 00604 } 00605 00606 return ret; 00607 } 00608 00609 static int commissioner_br_security_done_cb(int8_t service_id, uint8_t address[16], uint8_t keyblock[static 40]) 00610 { 00611 (void)service_id; 00612 (void)address; 00613 (void)keyblock; 00614 thci_trace("commissionerBrAccepted"); 00615 thci_trace("commissionerPetitionStarted"); 00616 return 0; 00617 } 00618 00619 static int thread_commissioning_remote_addr_set(commissioner_t *this) 00620 { 00621 if (0 == thread_management_get_leader_address(this->interface_id, this->destination_address)) { 00622 tr_debug("on-mesh commissioner"); 00623 this->destination_port = THREAD_MANAGEMENT_PORT; 00624 this->native_commissioner = false; 00625 } else if (0 == thread_commissioning_native_commissioner_get_connection_info(this->interface_id, 00626 this->destination_address, &this->destination_port)) { 00627 tr_debug("native commissioner"); 00628 this->native_commissioner = true; 00629 } else { 00630 tr_error("No remote address"); 00631 return -1; 00632 } 00633 return 0; 00634 } 00635 00636 /* 00637 Public api functions 00638 */ 00639 int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) 00640 { 00641 if (commissioner_find(interface_id)) { 00642 return -1; 00643 } 00644 commissioner_t *this = commissioner_create(interface_id); 00645 if (!this) { 00646 return -2; 00647 } 00648 memcpy(this->PSKc_ptr,PSKc,16); 00649 00650 this->management_instance = thread_management_register(interface_id); 00651 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 00652 coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); 00653 coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb); 00654 coap_service_register_uri(this->coap_service_id, THREAD_URI_DATASET_CHANGED, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_dataset_changed_notify_recv_cb); 00655 00656 this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb); 00657 coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb); 00658 00659 this->coap_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb); 00660 coap_service_register_uri(this->coap_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb); 00661 coap_service_virtual_socket_set_cb(this->coap_virtual_service_id, commission_virtual_socket_send_cb); 00662 return 0; 00663 } 00664 00665 int thread_commissioning_unregister(int8_t interface_id) 00666 { 00667 commissioner_t *this = commissioner_find(interface_id); 00668 if (!this) { 00669 return -1; 00670 } 00671 if (this->registered) { 00672 // Unregister the commissioner 00673 thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT); 00674 } 00675 thread_management_unregister(this->management_instance); 00676 00677 coap_service_delete(this->coap_service_id); 00678 coap_service_delete(this->coap_secure_service_id); 00679 coap_service_delete(this->coap_virtual_service_id); 00680 00681 commissioner_delete(this); 00682 return 0; 00683 } 00684 00685 int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_id_ptr, thread_commissioning_status_cb *status_cb_ptr) 00686 { 00687 commissioner_t *this; 00688 uint8_t payload[68];// max length for commissioner id is 64 + 4 byte header 00689 uint8_t commissioner_id_length; 00690 uint8_t service_id; 00691 uint8_t *ptr; 00692 char *uri_ptr; 00693 00694 this = commissioner_find(interface_id); 00695 00696 if (!this) { 00697 return -1; 00698 } 00699 if (!commissioner_id_ptr) { 00700 return -2; 00701 } 00702 commissioner_id_length = strlen(commissioner_id_ptr); 00703 00704 if (commissioner_id_length > 64) { 00705 return -3; 00706 } 00707 00708 if (thread_commissioning_remote_addr_set(this)) { 00709 return -4; 00710 } 00711 00712 if (this->native_commissioner) { 00713 uri_ptr = THREAD_URI_COMMISSIONER_PETITION; 00714 service_id = this->coap_secure_service_id; 00715 } else { 00716 uri_ptr = THREAD_URI_LEADER_PETITION; 00717 service_id = this->coap_service_id; 00718 } 00719 00720 this->status_cb_ptr = status_cb_ptr; 00721 ptr = payload; 00722 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_COMMISSIONER_ID, commissioner_id_length, (uint8_t *) commissioner_id_ptr); 00723 00724 tr_debug("Thread Petition send to %s:%d id %s ", trace_ipv6(this->destination_address),this->destination_port, commissioner_id_ptr); 00725 00726 //TODO there must be way to set PSKc for request 00727 //TODO there must be way to make client transactions with security and no security 00728 coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, 00729 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, payload, ptr - payload, commissioning_leader_petition_recv_cb); 00730 return 0; 00731 } 00732 00733 int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_state_e state) 00734 { 00735 commissioner_t *this; 00736 uint8_t payload[7]; 00737 uint8_t *ptr; 00738 uint8_t service_id; 00739 char *uri_ptr; 00740 /* length is 00741 state tlv 3 00742 session id tlv 4 00743 */ 00744 this = commissioner_find(interface_id); 00745 00746 if (!this) { 00747 return -1; 00748 } 00749 00750 if (thread_commissioning_remote_addr_set(this)) { 00751 return -4; 00752 } 00753 00754 if (this->native_commissioner) { 00755 uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE; 00756 service_id = this->coap_secure_service_id; 00757 } else { 00758 uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE; 00759 service_id = this->coap_service_id; 00760 } 00761 00762 ptr = payload; 00763 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, (uint8_t)commissioning_meshcop_map_state(state)); 00764 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, this->session_id); 00765 00766 tr_debug("Commissioner keep alive send to %s:%d, session_id=%d, state=%d", 00767 trace_ipv6(this->destination_address), this->destination_port, 00768 this->session_id, state); 00769 thci_trace("commissionerKeepAliveSent"); 00770 if (state != COMMISSIONING_STATE_ACCEPT) { 00771 this->session_id = 0; 00772 } 00773 coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port, 00774 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, payload, ptr - payload, commissioning_keep_alive_recv_cb); 00775 return 0; 00776 } 00777 00778 /* 00779 * PSKD (Pre-Shared Key -Device). A PSKD can be a minimum of six (6) uppercase alphanumeric characters long 00780 * 00781 * */ 00782 int thread_commissioning_device_add(int8_t interface_id, bool short_eui64, uint8_t EUI64[static 8], uint8_t *PSKd_ptr, uint8_t PSKd_len, thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr) 00783 { 00784 commissioner_t *this; 00785 device_t *device_ptr = NULL; 00786 00787 this = commissioner_find(interface_id); 00788 if (!this || PSKd_len < 1 || PSKd_len > 32 || !PSKd_ptr ) { 00789 return -1; 00790 } 00791 00792 if (memcmp(EUI64, any_device, 8) == 0) { 00793 // always add 'any' device to allow multiple 'any' devices 00794 device_ptr = device_create(this); 00795 } 00796 00797 if (!device_ptr) { 00798 // try to find an existing device 00799 device_ptr = device_find(this, EUI64); 00800 } 00801 00802 if (!device_ptr) { 00803 // create device 00804 device_ptr = device_create(this); 00805 } 00806 00807 if (!device_ptr) { 00808 return -2; 00809 } 00810 00811 memcpy(device_ptr->EUI64, EUI64, 8); 00812 if (memcmp(EUI64, any_device, 8) != 0){ 00813 ns_sha256_nbits(EUI64, 8, device_ptr->IID, 64); 00814 device_ptr->IID[0] &= ~2; //local administered bit is set in MAC and flipped in IID 00815 } else { 00816 memcpy(device_ptr->IID, any_device, 8); 00817 } 00818 00819 memcpy(device_ptr->PSKd, PSKd_ptr, PSKd_len); 00820 device_ptr->PSKd_len = PSKd_len; 00821 device_ptr->short_eui64 = short_eui64; 00822 device_ptr->joining_device_cb_ptr = joining_device_cb_ptr; 00823 00824 if (commission_steering_data_update(this) != 0) { 00825 return -2; 00826 } 00827 thci_trace("commissionerNwkDataSynced"); 00828 return 0; 00829 } 00830 00831 int thread_commissioning_device_delete(int8_t interface_id, uint8_t EUI64[static 8]) 00832 { 00833 commissioner_t *this = commissioner_find(interface_id); 00834 00835 if (!this) { 00836 return -1; 00837 } 00838 00839 tr_debug("delete commissioned device EUI64:%s", trace_array(EUI64, 8)); 00840 device_delete(this, device_find(this, EUI64)); 00841 00842 if (commission_steering_data_update(this) != 0) { 00843 return -2; 00844 } 00845 return 0; 00846 } 00847 00848 00849 void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *short_eui64, uint8_t EUI64[8], uint8_t PSKd[32], uint8_t *PSKd_len) 00850 { 00851 commissioner_t *this = commissioner_find(interface_id); 00852 if (!this) { 00853 return NULL; 00854 } 00855 device_t *cur_ptr = (device_t*)ptr; 00856 if(cur_ptr == NULL) { 00857 cur_ptr = (device_t*)ns_list_get_first(&this->device_list); 00858 } else { 00859 cur_ptr = (device_t*)ns_list_get_next(&this->device_list, cur_ptr); 00860 } 00861 if(!cur_ptr) return NULL; 00862 if(short_eui64) *short_eui64 = cur_ptr->short_eui64; 00863 if(EUI64) memcpy(EUI64, cur_ptr->EUI64, 8); 00864 if(PSKd) memcpy(PSKd, cur_ptr->PSKd, 32); 00865 if(PSKd_len) *PSKd_len = cur_ptr->PSKd_len; 00866 00867 return cur_ptr; 00868 } 00869 00870 int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr) 00871 { 00872 protocol_interface_info_entry_t *cur; 00873 cur = protocol_stack_interface_info_get_by_id(interface_id); 00874 tr_debug("start native commissioner scanning"); 00875 if(!cur || !cur->thread_info) { 00876 return -1; 00877 } 00878 cur->thread_info->native_commissioner_link = NULL; 00879 cur->thread_info->native_commissioner_cb = cb_ptr; 00880 //TODO check if bootstrap is connected then we have to drop from old network and trigger scanning 00881 return 0; 00882 00883 } 00884 00885 int thread_commissioning_native_commissioner_stop(int8_t interface_id) 00886 { 00887 protocol_interface_info_entry_t *cur; 00888 cur = protocol_stack_interface_info_get_by_id(interface_id); 00889 tr_debug("stop native commissioner scanning"); 00890 if(!cur || !cur->thread_info) { 00891 return -1; 00892 } 00893 ns_dyn_mem_free(cur->thread_info->native_commissioner_link); 00894 cur->thread_info->native_commissioner_link = NULL; 00895 cur->thread_info->native_commissioner_cb = NULL; 00896 return 0; 00897 } 00898 00899 int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread_commissioning_link_configuration_s *link_ptr) 00900 { 00901 protocol_interface_info_entry_t *cur; 00902 cur = protocol_stack_interface_info_get_by_id(interface_id); 00903 tr_debug("connect native commissioner"); 00904 if(!cur || !cur->thread_info) { 00905 return -1; 00906 } 00907 cur->thread_info->native_commissioner_link = ns_dyn_mem_alloc(sizeof(thread_commissioning_link_configuration_s)); 00908 if(!cur->thread_info->native_commissioner_link) { 00909 return -2; 00910 } 00911 *cur->thread_info->native_commissioner_link = *link_ptr; 00912 //TODO check that we are scanning for networks and reset backup timers 00913 00914 return 0; 00915 } 00916 00917 int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port) 00918 { 00919 protocol_interface_info_entry_t *cur; 00920 cur = protocol_stack_interface_info_get_by_id(interface_id); 00921 tr_debug("get native connection info"); 00922 if(!cur || !cur->thread_info) { 00923 return -1; 00924 } 00925 00926 if (thread_attach_ready(cur) != 0) { 00927 return -2; 00928 } 00929 if (protocol_6lowpan_interface_get_link_local_cordinator_address(cur, address_ptr) != 0) { 00930 return -1; 00931 } 00932 if (port) { 00933 *port = cur->thread_info->native_commissioner_port; 00934 } 00935 return 0; 00936 } 00937 00938 int8_t thread_commissioning_get_management_id(int8_t interface_id) 00939 { 00940 commissioner_t *this = commissioner_find(interface_id); 00941 if (!this) { 00942 return -1; 00943 } 00944 00945 return this->management_instance; 00946 } 00947 00948 00949 #else 00950 int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16]) { 00951 (void)interface_id; 00952 (void)PSKc; 00953 return -1; 00954 } 00955 00956 int thread_commissioning_unregister(int8_t interface_id) 00957 { 00958 (void)interface_id; 00959 return -1; 00960 } 00961 00962 int thread_commissioning_device_add(int8_t interface_id, bool short_eui64, uint8_t EUI64[static 8], uint8_t *PSKd_ptr, uint8_t PSKd_len, thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr) 00963 { 00964 (void)interface_id; 00965 (void)short_eui64; 00966 (void)EUI64; 00967 (void)PSKd_ptr; 00968 (void)PSKd_len; 00969 (void)joining_device_cb_ptr; 00970 return -1; 00971 } 00972 00973 int thread_commissioning_device_delete(int8_t interface_id, uint8_t EUI64[8]) 00974 { 00975 (void)interface_id; 00976 (void)EUI64; 00977 return -1; 00978 } 00979 void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *short_eui64, uint8_t EUI64[8], uint8_t PSKd[32], uint8_t *PSKd_len) 00980 { 00981 (void)ptr; 00982 (void)interface_id; 00983 (void)short_eui64; 00984 (void)EUI64; 00985 (void)PSKd; 00986 (void)PSKd_len; 00987 return NULL; 00988 } 00989 00990 int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_state_e state) 00991 { 00992 (void)interface_id; 00993 (void)state; 00994 return -1; 00995 } 00996 00997 int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_id_ptr, thread_commissioning_status_cb *status_cb_ptr) 00998 { 00999 (void)interface_id; 01000 (void)commissioner_id_ptr; 01001 (void)status_cb_ptr; 01002 return -1; 01003 } 01004 01005 int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port) { 01006 (void)interface_id; 01007 (void)address_ptr; 01008 (void)port; 01009 return -1; 01010 } 01011 01012 int8_t thread_commissioning_get_management_id(int8_t interface_id) { 01013 (void)interface_id; 01014 return -1; 01015 } 01016 01017 int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr) { 01018 (void)interface_id; 01019 (void)cb_ptr; 01020 return -1; 01021 } 01022 01023 int thread_commissioning_native_commissioner_stop(int8_t interface_id) { 01024 (void)interface_id; 01025 return -1; 01026 } 01027 01028 int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread_commissioning_link_configuration_s *link_ptr) { 01029 (void)interface_id; 01030 (void)link_ptr; 01031 return -1; 01032 } 01033 01034 #endif
Generated on Tue Jul 12 2022 18:18:53 by
