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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
thread_management_server.c
00001 /* 00002 * Copyright (c) 2014-2019, 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 #include <string.h> 00033 #include <ns_types.h> 00034 #include <ns_list.h> 00035 #include <ns_trace.h> 00036 #include "nsdynmemLIB.h" 00037 #include "common_functions.h" 00038 #include "NWK_INTERFACE/Include/protocol.h" 00039 #include "6LoWPAN/Thread/thread_common.h" 00040 #include "6LoWPAN/Thread/thread_management_server.h" 00041 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00042 #include "6LoWPAN/Thread/thread_leader_service.h" 00043 #include "6LoWPAN/Thread/thread_discovery.h" 00044 #include "6LoWPAN/Thread/thread_bbr_api_internal.h" 00045 #include "6LoWPAN/Thread/thread_border_router_api_internal.h" 00046 #include "6LoWPAN/MAC/mac_helper.h" 00047 00048 #define TRACE_GROUP "TMFs" 00049 00050 #include "eventOS_event_timer.h" 00051 #include "coap_service_api.h" 00052 00053 #include "net_interface.h" 00054 #include "socket_api.h" 00055 #include "thread_common.h" 00056 #include "thread_config.h" 00057 #include "thread_tmfcop_lib.h" 00058 #include "thread_meshcop_lib.h" 00059 #include "thread_management_if.h" 00060 #include "thread_management_internal.h" 00061 #include "thread_commissioning_if.h" 00062 #include "thread_joiner_application.h" 00063 #include "thread_beacon.h" 00064 #include "thread_bootstrap.h" 00065 #include "thread_management_server.h" 00066 #include "thread_management_client.h" 00067 #include "thread_ccm.h" 00068 #include "thread_nvm_store.h" 00069 #include "mac_api.h" 00070 #include "6LoWPAN/MAC/mac_data_poll.h" 00071 #include "Common_Protocols/ipv6_constants.h" 00072 #include "Core/include/ns_address_internal.h" 00073 #include "mlme.h" 00074 00075 #ifdef HAVE_THREAD 00076 00077 //#define TRACE_DEEP 00078 #ifdef TRACE_DEEP 00079 #define tr_deep tr_debug 00080 #else 00081 #define tr_deep(...) 00082 #endif 00083 00084 typedef struct scan_query { 00085 int8_t coap_service_id; 00086 uint8_t channel_mask[6]; //<!** first byte is channel page 00087 uint16_t channel_mask_len; 00088 uint8_t *energy_list_ptr; 00089 uint8_t energy_list_length; 00090 uint8_t scan_count; 00091 timeout_t *timer; 00092 uint8_t address[16]; 00093 uint16_t port; 00094 uint16_t panid; 00095 uint8_t count; 00096 uint16_t period; 00097 uint16_t duration; 00098 bool panid_scan: 1; 00099 bool energy_scan: 1; 00100 } scan_query_t; 00101 00102 typedef struct announce { 00103 uint8_t channel_mask[6]; //<!** first byte is channel page support only channel page 0 00104 uint16_t channel_mask_len; 00105 timeout_t *timer; 00106 uint8_t count; 00107 uint16_t period; 00108 uint16_t channel; 00109 } announce_t; 00110 00111 typedef struct thread_management_server { 00112 scan_query_t *scan_ptr; 00113 announce_t *announce_ptr; 00114 timeout_t *join_ent_timer; 00115 uint8_t destination_address[16]; 00116 uint8_t one_time_key[16]; 00117 uint16_t relay_port_joiner; 00118 uint16_t external_commissioner_port; 00119 int8_t interface_id; 00120 int8_t coap_service_id; 00121 int8_t listen_socket_joiner; 00122 bool joiner_router_enabled: 1; 00123 ns_list_link_t link; 00124 } thread_management_server_t; 00125 00126 static NS_LIST_DEFINE(instance_list, thread_management_server_t, link); 00127 void thread_energy_scan_timeout_cb(void *arg); 00128 00129 static bool thread_channel_mask_is_channel_set(uint8_t *mask_ptr, uint8_t channel) 00130 { 00131 uint8_t n; 00132 uint8_t bit; 00133 00134 n = (channel) / 8; 00135 bit = 1 << (7 - (channel) % 8); 00136 00137 if (n > 5 || channel > 27) { 00138 return false; 00139 } 00140 if (mask_ptr[n + 2] & bit) { 00141 return true; 00142 } 00143 return false; 00144 } 00145 00146 00147 static uint8_t thread_channel_mask_count(uint8_t *mask_ptr) 00148 { 00149 uint8_t n; 00150 uint8_t result = 0; 00151 uint32_t bits; 00152 00153 bits = common_read_32_bit(mask_ptr + 2); 00154 bits = bits >> 5;// five lover bits are not used 00155 for (n = 0; n < 27; n++) { 00156 if ((bits & 1) == 1) { 00157 result++; 00158 } 00159 bits = bits >> 1; 00160 } 00161 tr_debug("Channel mask count = %d ", result); 00162 return result; 00163 } 00164 00165 /*This method identifies the channels to be scanned based on the bits set in the channel mask 00166 * */ 00167 static uint8_t thread_channels_to_be_scanned(uint8_t *mask_ptr) 00168 { 00169 uint8_t result = 0; 00170 uint8_t val = 1; 00171 uint8_t *ptr = mask_ptr + 2; // first two bytes do not contain the channels to be scanned 00172 uint8_t j = 0; 00173 while (j < 4) { 00174 00175 // one channel for every bit that is set in the mask ptr 00176 for (int i = 0; i < 8 ; i++) { 00177 if (val & (*ptr)) { 00178 result++; 00179 } 00180 val = val << 1; 00181 } 00182 val = 1; 00183 ptr++; 00184 j++; 00185 } 00186 return result; 00187 } 00188 00189 static thread_management_server_t *thread_management_server_find(int8_t interface_id) 00190 { 00191 thread_management_server_t *this = NULL; 00192 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00193 if (cur_ptr->interface_id == interface_id) { 00194 this = cur_ptr; 00195 break; 00196 } 00197 } 00198 return this; 00199 } 00200 static thread_management_server_t *thread_management_find_by_service(int8_t service_id) 00201 { 00202 thread_management_server_t *this = NULL; 00203 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00204 if (cur_ptr->coap_service_id == service_id) { 00205 this = cur_ptr; 00206 break; 00207 } 00208 } 00209 return this; 00210 } 00211 00212 static thread_management_server_t *thread_management_find_by_sckt_id(int8_t sckt_id) 00213 { 00214 thread_management_server_t *this = NULL; 00215 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00216 if (cur_ptr->listen_socket_joiner == sckt_id) { 00217 this = cur_ptr; 00218 break; 00219 } 00220 } 00221 return this; 00222 } 00223 00224 static bool tlv_is_requested(uint8_t *tlv_list, uint16_t list_len, uint8_t tlv) 00225 { 00226 if (!list_len || !tlv_list) { 00227 return true; 00228 } 00229 for (uint16_t n = 0; n < list_len; n++) { 00230 if (tlv_list[n] == tlv) { 00231 return true; 00232 } 00233 } 00234 return false; 00235 } 00236 00237 static int thread_management_server_management_get_respond(int8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00238 { 00239 uint8_t *ptr = NULL; 00240 int response_len; 00241 uint8_t *response_ptr = NULL; 00242 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00243 link_configuration_s *link_configuration; 00244 device_configuration_s *device_configuration; 00245 00246 link_configuration = thread_joiner_application_get_config(interface_id); 00247 device_configuration = thread_joiner_application_get_device_config(interface_id); 00248 00249 if (!link_configuration || !device_configuration) { 00250 return -1; 00251 } 00252 00253 tr_debug("Recv MGMT_GET request"); 00254 00255 response_len = thread_joiner_application_device_configuration_length(device_configuration); 00256 response_ptr = ptr = ns_dyn_mem_alloc(response_len); 00257 if (!ptr) { 00258 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00259 tr_error("Out of resources"); 00260 goto send_response; 00261 } 00262 ptr = thread_joiner_application_device_configuration_build(ptr, device_configuration); 00263 return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00264 00265 send_response: 00266 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, response_ptr, ptr - response_ptr); 00267 ns_dyn_mem_free(response_ptr); 00268 return 0; 00269 } 00270 00271 static int thread_management_server_active_get_respond(uint8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00272 { 00273 link_configuration_s *link_configuration; 00274 uint8_t *request_tlv_ptr = NULL; 00275 uint8_t *request_tlv_copy = NULL; 00276 uint16_t request_tlv_len; 00277 uint8_t *ptr = NULL; 00278 uint8_t *payload_ptr = NULL; 00279 uint8_t *response_ptr = NULL; 00280 uint8_t error_msg[3]; 00281 int response_len; 00282 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00283 00284 link_configuration = thread_joiner_application_get_config(interface_id); 00285 if (!link_configuration) { 00286 return -1; 00287 } 00288 00289 tr_debug("Recv MGMT_ACTIVE_GET request"); 00290 00291 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00292 00293 if (!request_tlv_len) { 00294 request_tlv_copy = request_tlv_ptr = thread_joiner_application_active_config_tlv_list_get(interface_id, &request_tlv_len); 00295 } 00296 00297 if (!request_tlv_ptr) { 00298 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00299 goto send_response; 00300 } 00301 00302 if (request_tlv_len && !(link_configuration->securityPolicy & SECURITY_POLICY_OUT_OF_BAND_COMMISSIONING_ALLOWED)) { 00303 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_NETWORK_MASTER_KEY); 00304 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_SECURITY_POLICY); 00305 } 00306 00307 if (!request_tlv_len) { 00308 goto send_response; 00309 } 00310 00311 response_len = thread_joiner_application_active_config_length(interface_id, request_tlv_ptr, request_tlv_len, NULL, 0); 00312 00313 payload_ptr = ptr = error_msg; 00314 if (response_len < 1) { 00315 //Error in message is responded with Thread status or if we have access rights problem 00316 goto send_response; 00317 } 00318 payload_ptr = ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00319 if (!response_ptr) { 00320 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00321 goto send_response; 00322 } 00323 memset(response_ptr, 0, response_len); 00324 00325 ptr = thread_joiner_application_active_config_write(interface_id, ptr, request_tlv_ptr, request_tlv_len, NULL, 0); 00326 00327 send_response: 00328 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr); 00329 ns_dyn_mem_free(response_ptr); 00330 ns_dyn_mem_free(request_tlv_copy); 00331 return 0; 00332 } 00333 00334 static int thread_management_server_pending_get_respond(int8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00335 { 00336 link_configuration_s *link_configuration; 00337 uint8_t *request_tlv_ptr = NULL; 00338 uint8_t *request_tlv_copy = NULL; 00339 uint16_t request_tlv_len; 00340 uint8_t *ptr; 00341 uint8_t *payload_ptr; 00342 uint8_t *response_ptr = NULL; 00343 uint8_t error_msg[3]; 00344 int response_len; 00345 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00346 00347 tr_debug("Recv MGMT_PENDING_GET request"); 00348 payload_ptr = ptr = error_msg; 00349 link_configuration = thread_joiner_application_get_config(interface_id); 00350 00351 if (!link_configuration) { 00352 return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00353 goto send_response; 00354 } 00355 if (!thread_joiner_application_pending_config_exists(interface_id)) { 00356 goto send_response; 00357 } 00358 00359 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00360 00361 if (!request_tlv_len) { 00362 request_tlv_copy = request_tlv_ptr = thread_joiner_application_pending_config_tlv_list_get(interface_id, &request_tlv_len); 00363 } 00364 00365 if (!request_tlv_ptr) { 00366 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00367 goto send_response; 00368 } 00369 00370 if (request_tlv_len && !(link_configuration->securityPolicy & SECURITY_POLICY_OUT_OF_BAND_COMMISSIONING_ALLOWED)) { 00371 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_NETWORK_MASTER_KEY); 00372 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_SECURITY_POLICY); 00373 } 00374 00375 if (!request_tlv_len) { 00376 goto send_response; 00377 } 00378 00379 response_len = thread_joiner_application_pending_config_length(interface_id, request_tlv_ptr, request_tlv_len, NULL, 0); 00380 00381 payload_ptr = ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00382 if (!response_ptr) { 00383 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00384 goto send_response; 00385 } 00386 memset(response_ptr, 0, response_len); 00387 00388 ptr = thread_joiner_application_pending_config_build(interface_id, ptr, request_tlv_ptr, request_tlv_len, NULL, 0); 00389 00390 send_response: 00391 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr); 00392 ns_dyn_mem_free(response_ptr); 00393 ns_dyn_mem_free(request_tlv_copy); 00394 return 0; 00395 } 00396 00397 /** 00398 * Thread management GET command callback. 00399 * Handle messages: 00400 * -MGMT_GET (uri = /c/mg), 00401 * -MGMT_ACTIVE_GET (uri = /c/ag), 00402 * -MGMT_PENDING_GET (uri = /c/pg) 00403 */ 00404 static int thread_management_server_get_command_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00405 { 00406 (void) source_port; 00407 (void) source_address; 00408 00409 thread_management_server_t *this = thread_management_find_by_service(service_id); 00410 00411 if (!this) { 00412 return -1; 00413 } 00414 00415 return thread_management_server_tmf_get_request_handler(this->interface_id, service_id, request_ptr); 00416 00417 } 00418 00419 static int thread_management_server_commissioner_get_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00420 { 00421 (void) source_address; 00422 (void) source_port; 00423 protocol_interface_info_entry_t *cur; 00424 thread_management_server_t *this = thread_management_find_by_service(service_id); 00425 uint8_t response_msg[2 + 2 + 2 + 2 + 2 + 16 + 2 + 2]; 00426 uint8_t *request_tlv_ptr = NULL; 00427 uint16_t request_tlv_len; 00428 uint8_t *ptr; 00429 uint8_t *payload_ptr = NULL; 00430 if (!this) { 00431 return -1; 00432 } 00433 tr_debug("Thread management commission get request"); 00434 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00435 if (!cur || !cur->thread_info) { 00436 return -1; 00437 } 00438 payload_ptr = ptr = response_msg; 00439 00440 if (!cur->thread_info->registered_commissioner.commissioner_valid) { 00441 //Error in message is responded with Thread status or if we have access rights problem 00442 tr_warn("No registered commissioner"); 00443 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00444 goto send_response; 00445 } 00446 uint16_t border_router_locator = common_read_16_bit(&cur->thread_info->registered_commissioner.border_router_address[14]); 00447 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00448 00449 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_BORDER_ROUTER_LOCATOR)) { 00450 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_BORDER_ROUTER_LOCATOR, border_router_locator); 00451 } 00452 00453 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID)) { 00454 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, cur->thread_info->registered_commissioner.session_id); 00455 } 00456 00457 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_STEERING_DATA)) { 00458 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_STEERING_DATA, cur->thread_info->registered_commissioner.steering_data_len, cur->thread_info->registered_commissioner.steering_data); 00459 } 00460 00461 if (payload_ptr == ptr) { 00462 tr_warn("No TLVs found"); 00463 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00464 goto send_response; 00465 } 00466 send_response: 00467 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr); 00468 return 0; 00469 } 00470 00471 #ifdef HAVE_THREAD_V2 00472 00473 static int thread_management_server_mtd_dua_ntf_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00474 { 00475 (void) service_id; 00476 (void) source_address; 00477 (void) source_port; 00478 (void) response_ptr; 00479 uint16_t addr_len; 00480 uint8_t *addr_data_ptr; 00481 uint8_t dua_status = THREAD_ST_DUA_SUCCESS; 00482 tr_debug("Thread MTD n/dn callback"); 00483 00484 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_client_get_interface_id_by_service_id(service_id)); 00485 if (!cur) { 00486 return -1; 00487 } 00488 addr_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_TARGET_EID, &addr_data_ptr); 00489 00490 if (addr_len < 16) { 00491 tr_warn("Invalid target eid in DUA.ntf cb message"); 00492 return -2; 00493 } 00494 00495 thread_tmfcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_STATUS, &dua_status); 00496 00497 if (dua_status == THREAD_ST_DUA_DUPLICATE) { 00498 // generate new dua address 00499 cur->dad_failures++; 00500 thread_bootstrap_dua_address_generate(cur, addr_data_ptr, 64); 00501 } 00502 00503 return 0; 00504 } 00505 00506 static void thread_management_server_reset_timeout_cb(void *arg) 00507 { 00508 protocol_interface_info_entry_t *cur = (protocol_interface_info_entry_t *)arg; 00509 00510 if (!cur) { 00511 return; 00512 } 00513 00514 // Delete all domain stuff and start discovery. 00515 thread_ccm_network_certificate_set(cur, NULL, 0); 00516 thread_ccm_network_private_key_set(cur, NULL, 0); 00517 thread_nvm_store_mleid_rloc_map_remove(); 00518 thread_nvm_store_link_info_clear(); 00519 thread_joiner_application_link_configuration_delete(cur->id); 00520 thread_bootstrap_connection_error(cur->id, CON_ERROR_NETWORK_KICK, NULL); 00521 } 00522 00523 /* 00524 * Commissioner requests to leave this domain 00525 */ 00526 static int thread_management_server_reset_req_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00527 { 00528 (void) source_address; 00529 (void) source_port; 00530 00531 uint8_t payload[3] = {0}; 00532 uint8_t *ptr = payload; 00533 uint8_t *signature_ptr = NULL; 00534 uint16_t session_id = 0; 00535 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id)); 00536 00537 if (!cur || !request_ptr) { 00538 return -1; 00539 } 00540 00541 tr_debug("Received MGMT_RESET.req"); 00542 00543 // Verify request TLV's: Commissioner Session ID TLV - Commissioner Token TLV (optional) - Commissioner Signature TLV 00544 thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id); 00545 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMM_SIGNATURE, &signature_ptr); 00546 00547 if ((session_id != thread_info(cur)->registered_commissioner.session_id) /*|| (signature_ptr == NULL)*/) { // todo: signature may not come in this early phase of implementors 00548 tr_debug("Request parse failed"); 00549 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00550 } 00551 00552 // Downgrade if router 00553 if (thread_am_router(cur)) { 00554 thread_bootstrap_attached_downgrade_router(cur); 00555 } 00556 00557 // Delete all data and start reattach 00558 // Get some time to send response and keep the Commissioner happy 00559 cur->thread_info->ccm_info->reset_timeout = eventOS_timeout_ms(thread_management_server_reset_timeout_cb, 5000, cur); 00560 00561 // Send response 00562 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, payload, ptr - payload); 00563 00564 return 0; 00565 } 00566 00567 00568 /* 00569 * Commissioner requests to get new certificate from Registrar, but to stay in the same domain 00570 */ 00571 static int thread_management_server_reenroll_req_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00572 { 00573 (void) source_address; 00574 (void) source_port; 00575 00576 uint8_t pbbr_addr[16] = {0}; 00577 uint8_t status_tlv[3] = {0}; 00578 uint8_t *ptr = status_tlv; 00579 uint8_t *signature_ptr = NULL; 00580 uint16_t session_id = 0; 00581 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id)); 00582 00583 if (!cur || !request_ptr) { 00584 return -1; 00585 } 00586 00587 tr_debug("Received MGMT_REENROLL.req"); 00588 00589 // Verify request TLV's: Commissioner Session ID TLV - Commissioner Token TLV (optional) - Commissioner Signature TLV 00590 thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id); 00591 thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMM_SIGNATURE, &signature_ptr); 00592 00593 if ((session_id != thread_info(cur)->registered_commissioner.session_id) ||/* (signature_ptr == NULL) || */ 00594 thread_common_primary_bbr_get(cur, pbbr_addr, NULL, NULL, NULL)) { 00595 tr_debug("Request parse failed"); 00596 ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00597 goto send_response; 00598 } 00599 00600 thread_ccm_reenrollment_start(cur, service_id, pbbr_addr); 00601 00602 send_response: 00603 00604 // send response 00605 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, status_tlv, ptr - status_tlv); 00606 return 0; 00607 } 00608 static void thread_management_server_ccm_register(int8_t interface_id, int8_t coap_service_id) 00609 { 00610 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00611 00612 if (!cur || !cur->thread_info->ccm_info) { 00613 return; 00614 } 00615 cur->thread_info->ccm_info->coap_service_id = coap_service_id; 00616 coap_service_register_uri(thread_info(cur)->ccm_info->coap_service_id, THREAD_URI_RESET_REQ, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_reset_req_cb); 00617 coap_service_register_uri(thread_info(cur)->ccm_info->coap_service_id, THREAD_URI_REENROLL_REQ, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_reenroll_req_cb); 00618 } 00619 static void thread_management_server_mtd_service_register(protocol_interface_info_entry_t *cur) 00620 { 00621 coap_service_register_uri(thread_management_server_service_id_get(cur->id), THREAD_URI_BBR_DOMAIN_ADDRESS_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_mtd_dua_ntf_cb); 00622 } 00623 00624 #ifdef HAVE_THREAD_ROUTER 00625 00626 static int thread_management_server_ccm_relay_tx_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00627 { 00628 ns_address_t destination_address = { .address = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; 00629 uint8_t *udp_data_ptr; 00630 uint16_t udp_data_len; 00631 uint8_t *iid_ptr; 00632 uint8_t iid_len; 00633 uint16_t port; 00634 uint8_t port_len; 00635 int8_t socket_id; 00636 (void)source_address; 00637 (void)source_port; 00638 00639 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(thread_management_server_interface_id_get(service_id)); 00640 if (!cur) { 00641 return -1; 00642 } 00643 iid_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &iid_ptr); 00644 port_len = thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &port); 00645 udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_data_ptr); 00646 // unwrap message and send to joiner socket. 00647 if (8 > iid_len || 2 > port_len || 0 == udp_data_len) { 00648 tr_err("Relay TX invalid message iid:%d, port:%d data_len:%d", iid_len, port_len, udp_data_len); 00649 return -1; 00650 } 00651 if (strncmp(THREAD_URI_BBR_NMK_TX_NTF, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 00652 socket_id = cur->thread_info->ccm_info->listen_socket_nmkp; 00653 } else if (strncmp(THREAD_URI_BBR_TRI_TX_NTF, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 00654 socket_id = cur->thread_info->ccm_info->listen_socket_ae; 00655 } else { 00656 return -1; 00657 } 00658 00659 memcpy(&destination_address.address[8], iid_ptr, 8); 00660 destination_address.identifier = port; 00661 destination_address.type = ADDRESS_IPV6; 00662 int8_t err = socket_sendto(socket_id, &destination_address, udp_data_ptr, udp_data_len); 00663 if (err < 0) { 00664 tr_err("Relay TX sendto failed %d", err); 00665 } 00666 00667 tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); 00668 00669 return -1; // OK no response sent 00670 } 00671 00672 static void thread_management_server_relay_socket_cb(void *cb_res) 00673 { 00674 socket_callback_t *sckt_data = 0; 00675 ns_address_t source_address; 00676 uint8_t relay_destination_address[16]; 00677 uint8_t *data_ptr = NULL; 00678 uint16_t data_len = 0; 00679 uint8_t *ptr; 00680 uint8_t *payload_ptr; 00681 uint16_t payload_len; 00682 char *destination_uri_ptr = THREAD_URI_RELAY_RECEIVE; 00683 sckt_data = cb_res; 00684 00685 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(sckt_data->interface_id); 00686 00687 if (!cur) { 00688 return; 00689 } 00690 if (sckt_data->socket_id == cur->thread_info->ccm_info->listen_socket_nmkp) { 00691 destination_uri_ptr = THREAD_URI_BBR_NMK_RX_NTF; 00692 } else if (sckt_data->socket_id == cur->thread_info->ccm_info->listen_socket_ae) { 00693 destination_uri_ptr = THREAD_URI_BBR_TRI_RX_NTF; 00694 } else { 00695 return; 00696 } 00697 00698 00699 if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) { 00700 data_ptr = ns_dyn_mem_alloc(sckt_data->d_len); 00701 if (!data_ptr) { 00702 tr_err("Out of memory"); 00703 return; 00704 } 00705 data_len = socket_read(sckt_data->socket_id, &source_address, data_ptr, sckt_data->d_len); 00706 } 00707 if (!data_ptr || data_len < 1) { 00708 tr_err("No data received"); 00709 return; 00710 } 00711 00712 thread_addr_write_mesh_local_16(relay_destination_address, 0xfc38, cur->thread_info); 00713 00714 payload_len = 4 + data_len + 4 + 8 + 4 + 2 + 4 + 2; //Joiner DTLS Encapsulation TLV Joiner UDP Port TLV Joiner IID TLV Joiner Router Locator TLV 00715 payload_ptr = ns_dyn_mem_alloc(payload_len); 00716 00717 if (!payload_ptr) { 00718 tr_err("Out of memory"); 00719 ns_dyn_mem_free(data_ptr); 00720 return; 00721 } 00722 tr_debug("Relay TX recvfrom addr: %s, port:%d len:%d", trace_ipv6(source_address.address), source_address.identifier, data_len); 00723 thci_trace("joinerrouterJoinerDataRelayedInbound"); 00724 ptr = payload_ptr; 00725 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr); 00726 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &source_address.address[8]); 00727 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, source_address.identifier); 00728 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, mac_helper_mac16_address_get(cur)); 00729 00730 coap_service_request_send(cur->thread_info->ccm_info->coap_service_id, COAP_REQUEST_OPTIONS_NONE, relay_destination_address, THREAD_MANAGEMENT_PORT, 00731 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, destination_uri_ptr, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); 00732 ns_dyn_mem_free(payload_ptr); 00733 ns_dyn_mem_free(data_ptr); 00734 } 00735 00736 static void thread_management_server_joiner_router_ae_deinit(protocol_interface_info_entry_t *cur) 00737 { 00738 if (cur->thread_info->ccm_info->relay_port_ae > 0) { 00739 tr_debug("deinit AE"); 00740 coap_service_unregister_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_TRI_TX_NTF); 00741 socket_close(cur->thread_info->ccm_info->listen_socket_ae); 00742 cur->thread_info->ccm_info->listen_socket_ae = -1; 00743 cur->thread_info->ccm_info->relay_port_ae = 0; 00744 } 00745 } 00746 00747 static void thread_management_server_joiner_router_nmkp_deinit(protocol_interface_info_entry_t *cur) 00748 { 00749 if (cur->thread_info->ccm_info->relay_port_nmkp > 0) { 00750 tr_debug("deinit NMKP"); 00751 coap_service_unregister_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_NMK_TX_NTF); 00752 socket_close(cur->thread_info->ccm_info->listen_socket_nmkp); 00753 cur->thread_info->ccm_info->listen_socket_nmkp = -1; 00754 cur->thread_info->ccm_info->relay_port_nmkp = 0; 00755 } 00756 } 00757 00758 static int thread_management_server_ccm_joiner_router_init(protocol_interface_info_entry_t *cur) 00759 { 00760 00761 int8_t securityLinkLayer = 0; 00762 00763 if (!cur->thread_info->ccm_info || thread_info(cur)->version < THREAD_VERSION_1_2) { 00764 return -1; 00765 } 00766 00767 if (0 != thread_common_primary_bbr_get(cur, NULL, NULL, NULL, NULL)) { 00768 // Need to disable Joiner router either because port changed or moving to disabled 00769 thread_management_server_joiner_router_ae_deinit(cur); 00770 thread_management_server_joiner_router_nmkp_deinit(cur); 00771 // Joiner router should be disabled 00772 return 0; 00773 } 00774 00775 // Is this a CCM network? 00776 uint16_t securityPolicy = thread_joiner_application_security_policy_get(cur->id); 00777 if (securityPolicy & THREAD_SECURITY_POLICY_CCM_DISABLED) { 00778 // Not a CCM network, de-initialize 00779 thread_management_server_joiner_router_ae_deinit(cur); 00780 thread_management_server_joiner_router_nmkp_deinit(cur); 00781 return 0; 00782 } 00783 00784 if (thread_ccm_network_certificate_available(cur) == false) { 00785 // No domain certificate available 00786 return 0; 00787 } 00788 00789 if (!(securityPolicy & THREAD_SECURITY_POLICY_AE_DISABLED)) { 00790 if (cur->thread_info->ccm_info->listen_socket_ae < 0) { 00791 // Start AE relay 00792 cur->thread_info->ccm_info->listen_socket_ae = socket_open(SOCKET_UDP, THREAD_DEFAULT_AE_PORT, thread_management_server_relay_socket_cb); 00793 if (cur->thread_info->ccm_info->listen_socket_ae >= 0) { 00794 cur->thread_info->ccm_info->relay_port_ae = THREAD_DEFAULT_AE_PORT; 00795 socket_setsockopt(cur->thread_info->ccm_info->listen_socket_ae, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); 00796 // The regular TX is usable from joiner router, because it is stateless, but it neds to be forced on 00797 coap_service_register_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_TRI_TX_NTF, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_ccm_relay_tx_cb); 00798 } else { 00799 tr_warn("Joiner AE failed"); 00800 cur->thread_info->ccm_info->relay_port_ae = 0; 00801 } 00802 } 00803 } else { 00804 thread_management_server_joiner_router_ae_deinit(cur); 00805 } 00806 00807 if (!(securityPolicy & THREAD_SECURITY_POLICY_NMP_DISABLED)) { 00808 if (cur->thread_info->ccm_info->listen_socket_nmkp < 0) { 00809 // Start nmkp relay 00810 cur->thread_info->ccm_info->listen_socket_nmkp = socket_open(SOCKET_UDP, THREAD_DEFAULT_NMKP_PORT, thread_management_server_relay_socket_cb); 00811 if (cur->thread_info->ccm_info->listen_socket_nmkp >= 0) { 00812 cur->thread_info->ccm_info->relay_port_nmkp = THREAD_DEFAULT_NMKP_PORT; 00813 socket_setsockopt(cur->thread_info->ccm_info->listen_socket_nmkp, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); 00814 // The regular TX is usable from joiner router, because it is stateless, but it neds to be forced on 00815 coap_service_register_uri(cur->thread_info->ccm_info->coap_service_id, THREAD_URI_BBR_NMK_TX_NTF, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_ccm_relay_tx_cb); 00816 } else { 00817 tr_warn("Joiner NMKP failed"); 00818 cur->thread_info->ccm_info->relay_port_nmkp = 0; 00819 } 00820 } 00821 } else { 00822 thread_management_server_joiner_router_nmkp_deinit(cur); 00823 } 00824 00825 tr_info("init commercial joiner router ae:%d nmkp:%d", cur->thread_info->ccm_info->relay_port_ae, cur->thread_info->ccm_info->relay_port_nmkp); 00826 00827 return 0; 00828 } 00829 #endif // HAVE_THREAD_ROUTER 00830 00831 #else 00832 #define thread_management_server_ccm_register(interface_id, coap_service_id) ((void)0) 00833 #endif // HAVE_THREAD_V2 00834 00835 #ifdef HAVE_THREAD_V2 00836 /* Public APIs */ 00837 00838 int thread_management_server_ccm_service_init(int8_t interface_id) 00839 { 00840 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00841 00842 if (!cur || !cur->thread_info->ccm_info || !cur->thread_info->ccm_info->coap_service_id) { 00843 return -1; 00844 } 00845 00846 if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_END_DEVICE || 00847 cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_SLEEPY_END_DEVICE) { 00848 thread_management_server_mtd_service_register(cur); 00849 #ifdef HAVE_THREAD_ROUTER 00850 } else if (cur->thread_info->thread_device_mode == THREAD_DEVICE_MODE_ROUTER) { 00851 thread_management_server_ccm_joiner_router_init(cur); 00852 #endif 00853 } 00854 00855 return 0; 00856 } 00857 #endif // HAVE_THREAD_V2 00858 00859 static int thread_start_mac_with_link_configuration(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00860 { 00861 mlme_start_t start_req; 00862 memset(&start_req, 0, sizeof(mlme_start_t)); 00863 /*Enable RF interface */ 00864 if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) { 00865 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); 00866 } else { 00867 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false); 00868 } 00869 00870 mac_helper_default_security_level_set(cur, SEC_ENC_MIC32); 00871 mac_helper_default_security_key_id_mode_set(cur, MAC_KEY_ID_MODE_IDX); 00872 00873 cur->mac_parameters->mac_channel = linkConfiguration->rfChannel; 00874 cur->mac_parameters->pan_id = linkConfiguration->panId; 00875 cur->mac_parameters->mac_channel = linkConfiguration->rfChannel; 00876 00877 start_req.PANId = linkConfiguration->panId; 00878 start_req.LogicalChannel = linkConfiguration->rfChannel; 00879 start_req.ChannelPage = 0; 00880 start_req.BeaconOrder = 0x0f; 00881 start_req.SuperframeOrder = 0x0f; 00882 00883 cur->interface_mode = INTERFACE_UP; 00884 thread_discovery_responser_enable(cur->id, false); 00885 if (cur->mac_api) { 00886 cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void *)&start_req); 00887 } 00888 if (cur->thread_info->sleepy_host_poll_time != 0) { 00889 mac_data_poll_host_mode_set(cur, NET_HOST_SLOW_POLL_MODE, cur->thread_info->sleepy_host_poll_time); 00890 } else { 00891 mac_data_poll_init(cur); 00892 } 00893 00894 return 0; 00895 } 00896 00897 00898 static void thread_panid_conflict_timeout_cb(void *arg) 00899 { 00900 uint8_t payload[12];// 2+6 + 2+2 00901 uint8_t *ptr; 00902 thread_management_server_t *this = arg; 00903 if (!this || !this->scan_ptr) { 00904 tr_error("panid conflict scan ptr missing"); 00905 return; 00906 } 00907 00908 this->scan_ptr->timer = NULL; 00909 00910 ptr = payload; 00911 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_PANID, this->scan_ptr->panid); 00912 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_CHANNEL_MASK, this->scan_ptr->channel_mask_len, this->scan_ptr->channel_mask); 00913 //Send pan id conflict coap 00914 coap_service_request_send(this->scan_ptr->coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->scan_ptr->address, this->scan_ptr->port, 00915 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_PANID_CONFLICT, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL); 00916 ns_dyn_mem_free(this->scan_ptr); 00917 this->scan_ptr = NULL; 00918 } 00919 00920 //style = 0 means thread style, style = anything else means zigbee style 00921 // for thread style the bit is set from left to right and for zigbee style it is set from right to left 00922 static void set_channel_mask(uint8_t *channel_mask, uint8_t channel_number, uint8_t style) 00923 { 00924 uint8_t byte_position; 00925 uint8_t bit_position; 00926 if (0 == style) { 00927 byte_position = channel_number / 8; 00928 bit_position = 7 - (channel_number % 8); 00929 channel_mask[byte_position + 2] |= (1 << bit_position); 00930 return; 00931 } else { 00932 byte_position = 3 - (channel_number / 8); 00933 bit_position = channel_number % 8; 00934 channel_mask[byte_position + 2] |= (1 << bit_position); 00935 return; 00936 } 00937 } 00938 static uint32_t reverse_bits(uint32_t num) 00939 { 00940 uint32_t NO_OF_BITS = sizeof(num) * 8; 00941 uint32_t reversed_value = 0, i, temp; 00942 for (i = 0; i < NO_OF_BITS; i++) { 00943 temp = (num & (1 << i)); 00944 if (temp) { 00945 reversed_value |= (1 << ((NO_OF_BITS - 1) - i)); 00946 } 00947 } 00948 return reversed_value; 00949 } 00950 static void thread_panid_scan_response(int8_t if_id, const mlme_scan_conf_t *conf) 00951 { 00952 bool conflict_occured = false; 00953 nwk_scan_params_t *scan_parameters_ptr; 00954 nwk_pan_descriptor_t *result; 00955 protocol_interface_info_entry_t *interface; 00956 link_configuration_s *linkConfiguration; 00957 00958 if (conf->ScanType != MAC_ACTIVE_SCAN) { 00959 tr_error("Not active scan"); 00960 return; 00961 } 00962 00963 interface = protocol_stack_interface_info_get_by_id(if_id); 00964 if (!interface) { 00965 tr_error("Mac scan confirm:Unknow Interface"); 00966 return; 00967 } 00968 00969 linkConfiguration = thread_joiner_application_get_config(if_id); 00970 if (!linkConfiguration) { 00971 return; 00972 } 00973 00974 scan_parameters_ptr = &interface->mac_parameters->nwk_scan_params; //mac_mlme_get_scan_params(interface); 00975 if (!scan_parameters_ptr || !scan_parameters_ptr->nwk_response_info || !conf->ResultListSize) { 00976 tr_debug("Mac scan confirm:No Beacons"); 00977 thread_start_mac_with_link_configuration(interface, linkConfiguration); 00978 return; 00979 } 00980 scan_parameters_ptr->active_scan_active = false; 00981 00982 thread_management_server_t *this = thread_management_server_find(if_id); 00983 00984 if (!this) { 00985 return; 00986 } 00987 00988 result = scan_parameters_ptr->nwk_response_info; 00989 // reset all channel masks 00990 this->scan_ptr->channel_mask[2] = 0x00; 00991 this->scan_ptr->channel_mask[3] = 0x00; 00992 this->scan_ptr->channel_mask[4] = 0x00; 00993 this->scan_ptr->channel_mask[5] = 0x00; 00994 do { 00995 tr_debug("Mac scan confirm:scanning results"); 00996 if (result->pan_descriptor->CoordPANId == this->scan_ptr->panid) { //if pan id matches then send a conflict message 00997 tr_debug("Same pan id was found on channel %d", result->pan_descriptor->LogicalChannel); 00998 set_channel_mask(this->scan_ptr->channel_mask, result->pan_descriptor->LogicalChannel, 0); 00999 conflict_occured = true; 01000 } 01001 result = result->next; 01002 } while (result); 01003 if (conflict_occured) { 01004 tr_debug("conflict occured"); 01005 this->scan_ptr->timer = eventOS_timeout_ms(thread_panid_conflict_timeout_cb, 2000, this); 01006 } 01007 thread_start_mac_with_link_configuration(interface, linkConfiguration); 01008 //TODO if no conflict scan again after delay seconds 01009 } 01010 static int thread_management_server_energy_scan_response_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 01011 { 01012 // Dummy response handler needed as otherwise retransmissions dont work in coap service. 01013 (void)service_id; 01014 (void)source_address; 01015 (void)source_port; 01016 (void)response_ptr; 01017 return 0; 01018 } 01019 01020 static void thread_energy_scan_coap(thread_management_server_t *arg) 01021 { 01022 uint8_t *ptr; 01023 thread_management_server_t *this = arg; 01024 link_configuration_s *linkConfiguration; 01025 protocol_interface_info_entry_t *interface; 01026 01027 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01028 if (!linkConfiguration) { 01029 return; 01030 } 01031 01032 interface = protocol_stack_interface_info_get_by_id(this->interface_id); 01033 if (!interface) { 01034 tr_error("Mac scan confirm:Unknow Interface"); 01035 return; 01036 } 01037 01038 thread_start_mac_with_link_configuration(interface, linkConfiguration); 01039 uint8_t channel_count = thread_channels_to_be_scanned(this->scan_ptr->channel_mask); 01040 tr_debug("energy scan result mask %s, result %s, count %d", trace_array(this->scan_ptr->channel_mask, 6), 01041 trace_array(this->scan_ptr->energy_list_ptr, channel_count * this->scan_ptr->count), channel_count); 01042 01043 01044 uint8_t *payload_ptr = ns_dyn_mem_alloc(2 + 6 + 2 + channel_count * this->scan_ptr->count); 01045 if (!payload_ptr) { 01046 tr_error("out of resources"); 01047 return; 01048 } 01049 ptr = payload_ptr; 01050 01051 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_CHANNEL_MASK, this->scan_ptr->channel_mask_len, this->scan_ptr->channel_mask); 01052 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_ENERGY_LIST, channel_count * this->scan_ptr->count, this->scan_ptr->energy_list_ptr); 01053 01054 coap_service_request_send(this->scan_ptr->coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->scan_ptr->address, this->scan_ptr->port, 01055 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ED_REPORT, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, thread_management_server_energy_scan_response_resp_cb); 01056 ns_dyn_mem_free(payload_ptr); 01057 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 01058 ns_dyn_mem_free(this->scan_ptr); 01059 this->scan_ptr = NULL; 01060 } 01061 01062 static void energy_scan_confirm_cb(int8_t if_id, const mlme_scan_conf_t *conf) 01063 { 01064 if (conf->ScanType != MAC_ED_SCAN_TYPE) { 01065 tr_error("Not energy scan"); 01066 return; 01067 } 01068 01069 if (conf->ResultListSize < 1) { 01070 tr_error("No scan responses"); 01071 return; 01072 } 01073 01074 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(if_id); 01075 if (!interface) { 01076 tr_error("could not get interface"); 01077 return; 01078 } 01079 01080 thread_management_server_t *this = thread_management_server_find(if_id); 01081 if (!this) { 01082 tr_error("could not find thread management server"); 01083 return; 01084 } 01085 // reduce the scan_count by one since one scan has been performed and results are also obtained 01086 this->scan_ptr->scan_count--; 01087 01088 for (int i = 0; i < conf->ResultListSize; i++) { 01089 *this->scan_ptr->energy_list_ptr++ = conf->ED_values[i]; 01090 } 01091 01092 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01093 if (!linkConfiguration) { 01094 return; 01095 } 01096 01097 //the energy list has now the response_size set of responses so increase the length of energy_list_length 01098 this->scan_ptr->energy_list_length += conf->ResultListSize; 01099 01100 // if all scans have been completed then, move the energy_list_ptr back to the beginning 01101 if (this->scan_ptr->scan_count == 0) { 01102 this->scan_ptr->energy_list_ptr -= this->scan_ptr->energy_list_length; 01103 thread_energy_scan_coap(this); 01104 } else { 01105 // if all scans have not been completed, enable RF, wait for scan period and call energy scan method again 01106 thread_start_mac_with_link_configuration(interface, linkConfiguration); 01107 if (this->scan_ptr->timer) { 01108 eventOS_timeout_cancel(this->scan_ptr->timer); 01109 } 01110 this->scan_ptr->timer = eventOS_timeout_ms(thread_energy_scan_timeout_cb, this->scan_ptr->period, this); 01111 } 01112 } 01113 01114 void thread_energy_scan_timeout_cb(void *arg) 01115 { 01116 link_configuration_s *linkConfiguration; 01117 thread_management_server_t *this = arg; 01118 if (!this || !this->scan_ptr || !this->scan_ptr->energy_list_ptr) { 01119 tr_error("Invalid query"); 01120 return; 01121 } 01122 01123 this->scan_ptr->timer = NULL; 01124 01125 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01126 if (!linkConfiguration) { 01127 return; 01128 } 01129 01130 protocol_interface_info_entry_t *s; 01131 s = protocol_stack_interface_info_get_by_id(this->interface_id); 01132 01133 if (!s) { 01134 return; 01135 } 01136 01137 uint32_t channel_mask = 0; 01138 channel_mask = (this->scan_ptr->channel_mask[2] << 24) | (this->scan_ptr->channel_mask[3] << 16) | (this->scan_ptr->channel_mask[4] << 8) | (this->scan_ptr->channel_mask[5]); 01139 //Modify reversed_mask after the right way to interpret channel mask is obtained 01140 uint32_t reversed_mask = reverse_bits(channel_mask); 01141 channel_mask = reversed_mask; 01142 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0] = channel_mask; 01143 //Channel page is 0 for thread 01144 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_page = CHANNEL_PAGE_0; 01145 01146 // Convert duration in ms to MAC exponent value 01147 uint8_t duration_n; 01148 if (this->scan_ptr->duration <= (CHANNEL_PAGE_0_SUPERFRAME_DURATION * 2)) { 01149 duration_n = 0; 01150 } else { 01151 duration_n = thread_log2_aprx((this->scan_ptr->duration / CHANNEL_PAGE_0_SUPERFRAME_DURATION) - 1); 01152 } 01153 01154 // 10 == 15.7s 01155 // 11 == 31.5s 01156 // 12 == 62.9s 01157 // 13 == 125.8s (maximum when duration is 65535 and result of log2 is rounded up) 01158 // 14 == 251.6s (not possible) 01159 tr_debug("Start Energy scan duration:%d", duration_n); 01160 mac_data_poll_disable(s); 01161 mlme_scan_t req; 01162 mac_create_scan_request(MAC_ED_SCAN_TYPE, &s->mac_parameters->nwk_scan_params.stack_chan_list, duration_n, &req); 01163 if (s->mac_api) { 01164 s->scan_cb = energy_scan_confirm_cb; 01165 s->mac_api->mlme_req(s->mac_api, MLME_SCAN, &req); 01166 } 01167 } 01168 01169 01170 static void thread_panid_scan_timeout_cb(void *arg) 01171 { 01172 thread_management_server_t *this = arg; 01173 if (!this || !this->scan_ptr) { 01174 return; 01175 } 01176 01177 this->scan_ptr->timer = NULL; 01178 01179 01180 protocol_interface_info_entry_t *s; 01181 s = protocol_stack_interface_info_get_by_id(this->interface_id); 01182 01183 if (!s || !s->mac_api) { 01184 return; 01185 } 01186 01187 uint32_t channel_mask = 0; 01188 channel_mask = (this->scan_ptr->channel_mask[2] << 24) | (this->scan_ptr->channel_mask[3] << 16) | (this->scan_ptr->channel_mask[4] << 8) | (this->scan_ptr->channel_mask[5]); 01189 //Modify reversed_mask after the right way to interpret channel mask is obtained 01190 uint32_t reversed_mask = reverse_bits(channel_mask); 01191 channel_mask = reversed_mask; 01192 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0] = channel_mask; 01193 //Channel page is 0 for thread 01194 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_page = CHANNEL_PAGE_0; 01195 mac_data_poll_disable(s); 01196 mlme_scan_t req; 01197 mac_create_scan_request(MAC_ACTIVE_SCAN, &s->mac_parameters->nwk_scan_params.stack_chan_list, 5, &req); 01198 /* 01199 Before commencing an active or passive scan, the MAC sub-layer shall store the value of macPANId and 01200 then set it to 0xffff for the duration of the scan. This enables the receive filter to accept all beacons rather 01201 than just the beacons from its current PAN, as described in 5.1.6.2. On completion of the scan, the MAC 01202 sub-layer shall restore the value of macPANId to the value stored before the scan began. 01203 */ 01204 mac_helper_panid_set(s, 0xffff); 01205 01206 s->scan_cb = thread_panid_scan_response; 01207 s->mac_parameters->nwk_scan_params.active_scan_active = true; 01208 s->mac_api->mlme_req(s->mac_api, MLME_SCAN, &req); 01209 } 01210 01211 01212 /** 01213 * Thread PANID scan request 01214 */ 01215 static int thread_management_server_panid_query_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 01216 { 01217 thread_management_server_t *this = thread_management_find_by_service(service_id); 01218 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 01219 uint16_t session_id; 01220 uint16_t panid; 01221 uint8_t *mask_ptr; 01222 uint8_t mask_len; 01223 01224 if (!this) { 01225 return -1; 01226 } 01227 tr_debug("thread management panid query"); 01228 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 01229 tr_warn("Missing Session id TLV"); 01230 goto error_exit; 01231 } 01232 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PANID, &panid)) { 01233 tr_warn("Missing PANID TLV"); 01234 goto error_exit; 01235 } 01236 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 01237 if (mask_len < 6) { 01238 tr_warn("Missing channel mask TLV"); 01239 goto error_exit; 01240 } 01241 tr_info("PANID TLV %02x, session_id %d, Channel mask TLV %s", panid, session_id, trace_array(mask_ptr, 5)); 01242 01243 if (!this->scan_ptr) { 01244 this->scan_ptr = ns_dyn_mem_alloc(sizeof(scan_query_t)); 01245 memset(this->scan_ptr, 0, sizeof(scan_query_t)); 01246 } else { 01247 eventOS_timeout_cancel(this->scan_ptr->timer); 01248 this->scan_ptr->timer = NULL; 01249 } 01250 if (!this->scan_ptr) { 01251 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01252 goto error_exit; 01253 } 01254 this->scan_ptr->timer = eventOS_timeout_ms(thread_panid_scan_timeout_cb, 500, this);// Delay for the confirm response message 01255 if (!this->scan_ptr->timer) { 01256 ns_dyn_mem_free(this->scan_ptr); 01257 this->scan_ptr = NULL; 01258 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01259 goto error_exit; 01260 } 01261 01262 this->scan_ptr->coap_service_id = service_id; 01263 memcpy(this->scan_ptr->channel_mask, mask_ptr, mask_len); 01264 this->scan_ptr->channel_mask_len = mask_len; 01265 this->scan_ptr->port = source_port; 01266 memcpy(this->scan_ptr->address, source_address, 16); 01267 this->scan_ptr->panid = panid; 01268 this->scan_ptr->panid_scan = true; 01269 01270 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 01271 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); 01272 return 0; 01273 } 01274 return -1; 01275 error_exit: 01276 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 01277 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 01278 return 0; 01279 } 01280 01281 return -1; 01282 } 01283 /** 01284 * Thread PANID scan request 01285 */ 01286 static int thread_management_server_energy_scan_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 01287 { 01288 thread_management_server_t *this = thread_management_find_by_service(service_id); 01289 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 01290 uint16_t period; 01291 uint16_t session_id; 01292 uint8_t count; 01293 uint16_t duration; 01294 uint8_t *mask_ptr; 01295 uint8_t mask_len; 01296 01297 01298 if (!this) { 01299 return -1; 01300 } 01301 tr_debug("thread management energy scan"); 01302 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PERIOD, &period)) { 01303 tr_warn("Missing PERIOD TLV"); 01304 goto error_exit; 01305 } 01306 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 01307 tr_warn("Missing Session id TLV"); 01308 goto error_exit; 01309 } 01310 if (1 > thread_meshcop_tlv_data_get_uint8(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COUNT, &count)) { 01311 tr_warn("Missing COUNT TLV"); 01312 goto error_exit; 01313 } 01314 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_DURATION, &duration)) { 01315 tr_warn("Missing DURATION TLV"); 01316 goto error_exit; 01317 } 01318 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 01319 if (mask_len < 6) { 01320 tr_warn("Missing channel mask TLV"); 01321 goto error_exit; 01322 } 01323 tr_info("Channel mask TLV %s, period %d, count %d, duration %d", trace_array(mask_ptr, mask_len), period, count, duration); 01324 01325 if (count < 1 || thread_channel_mask_count(mask_ptr) < 1) { 01326 // Sanity checks 01327 response_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 01328 goto error_exit; 01329 } 01330 if (!this->scan_ptr) { 01331 this->scan_ptr = ns_dyn_mem_alloc(sizeof(scan_query_t)); 01332 memset(this->scan_ptr, 0, sizeof(scan_query_t)); 01333 } else { 01334 eventOS_timeout_cancel(this->scan_ptr->timer); 01335 this->scan_ptr->timer = NULL; 01336 } 01337 if (!this->scan_ptr) { 01338 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01339 goto error_exit; 01340 } 01341 uint16_t channel_count = thread_channels_to_be_scanned(mask_ptr); 01342 01343 this->scan_ptr->energy_list_length = 0; 01344 this->scan_ptr->scan_count = count; 01345 01346 // allocate memory for the energy scan results 01347 this->scan_ptr->energy_list_ptr = ns_dyn_mem_temporary_alloc(channel_count * this->scan_ptr->scan_count); 01348 if (!this->scan_ptr->energy_list_ptr) { 01349 response_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 01350 tr_debug("Exiting after no energy list ptr was allocated"); 01351 goto error_exit; 01352 } 01353 01354 memset(this->scan_ptr->energy_list_ptr, 0, (channel_count * this->scan_ptr->scan_count)); 01355 01356 this->scan_ptr->timer = eventOS_timeout_ms(thread_energy_scan_timeout_cb, 500, this); 01357 01358 if (!this->scan_ptr->timer) { 01359 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01360 goto error_exit; 01361 } 01362 01363 this->scan_ptr->coap_service_id = service_id; 01364 memcpy(this->scan_ptr->channel_mask, mask_ptr, mask_len); 01365 this->scan_ptr->channel_mask_len = mask_len; 01366 this->scan_ptr->port = source_port; 01367 memcpy(this->scan_ptr->address, source_address, 16); 01368 this->scan_ptr->count = count; 01369 this->scan_ptr->duration = duration; 01370 this->scan_ptr->period = period; 01371 this->scan_ptr->energy_scan = true; 01372 01373 01374 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 01375 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); 01376 return 0; 01377 } 01378 return -1; 01379 error_exit: 01380 if (this->scan_ptr) { 01381 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 01382 ns_dyn_mem_free(this->scan_ptr); 01383 } 01384 this->scan_ptr = NULL; 01385 01386 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) { 01387 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 01388 return 0; 01389 } 01390 01391 return -1; 01392 } 01393 01394 static void thread_announce_timeout_cb(void *arg) 01395 { 01396 link_configuration_s *linkConfiguration; 01397 thread_management_server_t *this = arg; 01398 protocol_interface_info_entry_t *cur; 01399 01400 if (!this || !this->announce_ptr) { 01401 return; 01402 } 01403 01404 this->announce_ptr->timer = NULL; 01405 01406 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 01407 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01408 if (!cur || !linkConfiguration) { 01409 return; 01410 } 01411 while (this->announce_ptr->channel < 27) { 01412 if (thread_channel_mask_is_channel_set(this->announce_ptr->channel_mask, this->announce_ptr->channel)) { 01413 break; 01414 } 01415 this->announce_ptr->channel++; 01416 } 01417 if (this->announce_ptr->channel > 26) { 01418 tr_debug("Announce done"); 01419 ns_dyn_mem_free(this->announce_ptr); 01420 this->announce_ptr = NULL; 01421 return; 01422 } 01423 tr_debug("Announce to channel %d", this->announce_ptr->channel); 01424 01425 thread_bootstrap_announcement_start(cur, this->announce_ptr->channel_mask[0], this->announce_ptr->channel, this->announce_ptr->count, this->announce_ptr->period); 01426 01427 this->announce_ptr->channel++; // Next time we start the next channel 01428 this->announce_ptr->timer = eventOS_timeout_ms(thread_announce_timeout_cb, 5000, this); 01429 if (!this->announce_ptr->timer) { 01430 tr_warn("Announce failed"); 01431 ns_dyn_mem_free(this->announce_ptr); 01432 this->announce_ptr = NULL; 01433 return; 01434 } 01435 } 01436 01437 static int thread_management_server_announce_begin_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 01438 { 01439 thread_management_server_t *this = thread_management_find_by_service(service_id); 01440 link_configuration_s *linkConfiguration; 01441 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 01442 uint16_t period; 01443 uint16_t session_id; 01444 uint8_t count; 01445 uint8_t *mask_ptr; 01446 uint8_t mask_len; 01447 01448 (void)source_address; 01449 (void)source_port; 01450 01451 if (!this) { 01452 return -1; 01453 } 01454 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01455 if (!linkConfiguration) { 01456 return -1; 01457 } 01458 01459 tr_debug("thread management announce begin"); 01460 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 01461 tr_warn("Missing Session id TLV"); 01462 goto error_exit; 01463 } 01464 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PERIOD, &period)) { 01465 tr_warn("Missing PERIOD TLV"); 01466 goto error_exit; 01467 } 01468 if (1 > thread_meshcop_tlv_data_get_uint8(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COUNT, &count)) { 01469 tr_warn("Missing COUNT TLV"); 01470 goto error_exit; 01471 } 01472 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 01473 if (mask_len < 6) { 01474 tr_warn("Missing channel mask TLV"); 01475 goto error_exit; 01476 } 01477 // TODO validity checks session id must be validated 01478 tr_info("start announcing session id %d, mask TLV %s, period %d, count %d", session_id, trace_array(mask_ptr, mask_len), period, count); 01479 01480 if (!this->announce_ptr) { 01481 this->announce_ptr = ns_dyn_mem_alloc(sizeof(announce_t)); 01482 } else { 01483 eventOS_timeout_cancel(this->announce_ptr->timer); 01484 this->announce_ptr->timer = NULL; 01485 } 01486 if (!this->announce_ptr) { 01487 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01488 goto error_exit; 01489 } 01490 this->announce_ptr->timer = eventOS_timeout_ms(thread_announce_timeout_cb, 500, this); 01491 if (!this->announce_ptr->timer) { 01492 ns_dyn_mem_free(this->announce_ptr); 01493 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01494 goto error_exit; 01495 } 01496 memcpy(this->announce_ptr->channel_mask, mask_ptr, mask_len); 01497 this->announce_ptr->channel_mask_len = mask_len; 01498 this->announce_ptr->count = count; 01499 this->announce_ptr->period = period; 01500 this->announce_ptr->channel = 0; 01501 // Set own information to announce 01502 response_code = COAP_MSG_CODE_RESPONSE_CHANGED; 01503 01504 error_exit: 01505 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 01506 return 0; 01507 } 01508 01509 static int coap_msg_prevalidate_cb(int8_t local_interface_id, uint8_t local_address[static 16], uint16_t local_port, int8_t recv_interface_id, uint8_t source_address[static 16], uint16_t source_port, char *coap_uri) 01510 { 01511 protocol_interface_info_entry_t *cur_local, *cur_source; 01512 uint_fast8_t addr_scope; 01513 01514 (void) source_address; 01515 (void) source_port; 01516 (void) coap_uri; 01517 01518 cur_local = protocol_stack_interface_info_get_by_id(local_interface_id); 01519 01520 if (!cur_local) { 01521 tr_error("No interface for %d", local_interface_id); 01522 return -1; 01523 } 01524 01525 if (local_port != THREAD_MANAGEMENT_PORT) { 01526 // Message not sent to THREAD_MANAGEMENT_PORT, let it come through 01527 tr_deep("Message %s port %d is not mgmt port", coap_uri, local_port); 01528 return 0; 01529 } 01530 01531 // check message source address 01532 if (!thread_management_server_source_address_check(local_interface_id, source_address)) { 01533 tr_deep("Drop CoAP msg %s from %s", coap_uri, trace_ipv6(source_address)); 01534 return 3; 01535 } 01536 01537 /* check our local address scope */ 01538 addr_scope = addr_ipv6_scope(local_address, cur_local); 01539 if (addr_scope > IPV6_SCOPE_REALM_LOCAL) { 01540 tr_deep("Drop CoAP msg %s to %s due %d", coap_uri, trace_ipv6(local_address), addr_scope); 01541 return 1; 01542 } 01543 01544 if (local_interface_id != recv_interface_id) { 01545 // message received from different interface 01546 cur_source = protocol_stack_interface_info_get_by_id(recv_interface_id); 01547 if (!cur_source) { 01548 tr_deep("No cur for if %d", recv_interface_id); 01549 return -1; 01550 } 01551 addr_scope = addr_ipv6_scope(source_address, cur_source); 01552 if (addr_scope < IPV6_SCOPE_REALM_LOCAL) { 01553 tr_deep("Drop CoAP msg %s from %s to %s due %d", coap_uri, trace_ipv6(source_address), trace_ipv6(local_address), addr_scope); 01554 return 2; 01555 } 01556 } 01557 01558 return 0; 01559 } 01560 01561 /** 01562 * Public interface functions 01563 */ 01564 int thread_management_server_init(int8_t interface_id) 01565 { 01566 01567 thread_management_server_t *this = thread_management_server_find(interface_id); 01568 if (this) { 01569 return 0; 01570 } 01571 01572 this = ns_dyn_mem_alloc(sizeof(thread_management_server_t)); 01573 if (!this) { 01574 return -2; 01575 } 01576 01577 this->joiner_router_enabled = false; 01578 this->interface_id = interface_id; 01579 this->listen_socket_joiner = -1; 01580 this->relay_port_joiner = 0; 01581 this->scan_ptr = NULL; 01582 this->announce_ptr = NULL; 01583 this->join_ent_timer = NULL; 01584 memset(this->destination_address, 0, 16); 01585 memset(this->one_time_key, 0, 16); 01586 this->external_commissioner_port = THREAD_COMMISSIONING_PORT; 01587 01588 #ifdef HAVE_THREAD_ROUTER 01589 if (thread_border_router_init(this->interface_id) != 0) { 01590 ns_dyn_mem_free(this); 01591 return -5; 01592 } 01593 01594 if (thread_bbr_init(this->interface_id, this->external_commissioner_port) != 0) { 01595 ns_dyn_mem_free(this); 01596 return -5; 01597 } 01598 #endif 01599 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 01600 if (this->coap_service_id < 0) { 01601 tr_error("Thread management init failed"); 01602 ns_dyn_mem_free(this); 01603 return -3; 01604 } 01605 coap_service_msg_prevalidate_callback_set(THREAD_MANAGEMENT_PORT, coap_msg_prevalidate_cb); 01606 #ifdef HAVE_THREAD_ROUTER 01607 if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { 01608 tr_error("Thread leader service init failed"); 01609 ns_dyn_mem_free(this); 01610 return -3; 01611 } 01612 #endif 01613 thread_management_server_ccm_register(interface_id, this->coap_service_id); 01614 // All thread devices 01615 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01616 01617 // Full functioning devices(Router,reed,fed) 01618 coap_service_register_uri(this->coap_service_id, THREAD_URI_ACTIVE_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01619 coap_service_register_uri(this->coap_service_id, THREAD_URI_PENDING_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01620 coap_service_register_uri(this->coap_service_id, THREAD_URI_COMMISSIONER_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_commissioner_get_cb); 01621 01622 coap_service_register_uri(this->coap_service_id, THREAD_URI_PANID_QUERY, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_panid_query_cb); 01623 coap_service_register_uri(this->coap_service_id, THREAD_URI_ED_SCAN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_energy_scan_cb); 01624 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_ANNOUNCE_BEGIN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_announce_begin_cb); 01625 01626 ns_list_add_to_start(&instance_list, this); 01627 return 0; 01628 } 01629 01630 void thread_management_server_delete(int8_t interface_id) 01631 { 01632 thread_management_server_t *this = thread_management_server_find(interface_id); 01633 if (!this) { 01634 return; 01635 } 01636 01637 thread_leader_service_delete(interface_id); 01638 01639 if (this->joiner_router_enabled) { 01640 thread_management_server_joiner_router_deinit(interface_id); 01641 } 01642 //TODO move uri deletion to delete 01643 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); 01644 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); 01645 coap_service_delete(this->coap_service_id); 01646 01647 ns_list_remove(&instance_list, this); 01648 if (this->announce_ptr) { 01649 if (this->announce_ptr->timer) { 01650 eventOS_timeout_cancel(this->announce_ptr->timer); 01651 } 01652 ns_dyn_mem_free(this->announce_ptr); 01653 } 01654 if (this->scan_ptr) { 01655 if (this->scan_ptr->timer) { 01656 eventOS_timeout_cancel(this->scan_ptr->timer); 01657 } 01658 if (this->scan_ptr->energy_list_ptr) { 01659 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 01660 } 01661 ns_dyn_mem_free(this->scan_ptr); 01662 } 01663 01664 ns_dyn_mem_free(this); 01665 01666 thread_border_router_delete(interface_id); 01667 thread_bbr_delete(interface_id); 01668 return; 01669 } 01670 01671 int8_t thread_management_server_service_id_get(int8_t interface_id) 01672 { 01673 thread_management_server_t *this = thread_management_server_find(interface_id); 01674 if (!this) { 01675 return -1; 01676 } 01677 return this->coap_service_id; 01678 } 01679 01680 int8_t thread_management_server_interface_id_get(int8_t coap_service_id) 01681 { 01682 thread_management_server_t *this = thread_management_find_by_service(coap_service_id); 01683 if (!this) { 01684 return -1; 01685 } 01686 return this->interface_id; 01687 } 01688 01689 #ifdef THREAD_THCI_SUPPORT 01690 static uint8_t Joiner_iid[8]; 01691 #endif 01692 01693 static int thread_management_server_entrust_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 01694 { 01695 thread_management_server_t *this = thread_management_find_by_service(service_id); 01696 (void)source_address; 01697 (void)source_port; 01698 01699 if (response_ptr) { 01700 thci_trace("Device - Joiner Router|Direction - recv|IID - %s|Type - JOIN_ent.resp|Length - %d|Payload - %s", trace_array(Joiner_iid, 8), response_ptr->payload_len, trace_array(response_ptr->payload_ptr, response_ptr->payload_len)); 01701 } else { 01702 thci_trace("Device - Joiner Router|Direction - recv|IID - %s|Type - JOIN_ent.resp|Payload - NULL", Joiner_iid); 01703 } 01704 tr_debug("Joiner entrust response received"); 01705 if (!this) { 01706 tr_warn("commissioner service missing!"); 01707 return -1; 01708 } 01709 01710 thread_commissioning_if_pairwise_key_del(this->interface_id, &source_address[8]); 01711 01712 return 0; 01713 } 01714 static int thread_management_server_entrust_send(thread_management_server_t *this, uint8_t destination_address[16], uint8_t one_time_key[16]) 01715 { 01716 uint8_t *response_ptr; 01717 uint16_t response_len; 01718 uint8_t *ptr; 01719 link_configuration_s *link_configuration_ptr; 01720 //int ret; 01721 if (!this || !destination_address || !one_time_key) { 01722 tr_err("entrust send fail"); 01723 return -1; 01724 } 01725 01726 tr_debug("Joiner_entrust_send Pairwise key %s address %s", trace_array(one_time_key, 16), trace_ipv6(destination_address)); 01727 01728 link_configuration_ptr = thread_management_configuration_get(this->interface_id); 01729 if (!link_configuration_ptr) { 01730 tr_err("Entrust sending failed no configuration"); 01731 return -2; 01732 } 01733 int ret; 01734 uint8_t options = COAP_REQUEST_OPTIONS_NONE; 01735 ret = thread_commissioning_if_pairwise_key_add(this->interface_id, 10000, &destination_address[8], one_time_key); 01736 01737 if (ret) { 01738 tr_err("Pairwise key set failed"); 01739 return -3; 01740 } 01741 response_len = 6 + thread_joiner_application_active_config_length(this->interface_id, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01742 01743 ptr = response_ptr = ns_dyn_mem_alloc(response_len); 01744 if (!response_ptr) { 01745 tr_warn("Out of mem"); 01746 return -2; 01747 } 01748 ptr = thread_joiner_application_active_config_write(this->interface_id, ptr, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01749 ptr = thread_meshcop_tlv_data_write_uint32(ptr, MESHCOP_TLV_NETWORK_KEY_SEQUENCE, link_configuration_ptr->key_sequence); 01750 01751 thci_trace("joinerrouterJoinerAccepted"); 01752 /*We must null out the master secret*/ 01753 #ifdef THREAD_THCI_SUPPORT 01754 uint8_t *master_secret_ptr; 01755 uint8_t *pskc_ptr; 01756 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_NETWORK_MASTER_KEY, &master_secret_ptr) >= 16) { 01757 memset(master_secret_ptr, 0, 16); 01758 } 01759 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_PSKC, &pskc_ptr) >= 16) { 01760 memset(pskc_ptr, 0, 16); 01761 } 01762 01763 memcpy(Joiner_iid, &destination_address[8], 8); 01764 thci_trace("Device - Joiner Router|Direction - sent|IID - %s|Type - JOIN_ent.req|Length - %d|Payload - %s", trace_array(Joiner_iid, 8), (int)(ptr - response_ptr), trace_array(response_ptr, ptr - response_ptr)); 01765 if (master_secret_ptr) { 01766 memcpy(master_secret_ptr, link_configuration_ptr->master_key, 16); 01767 } 01768 if (pskc_ptr) { 01769 memcpy(pskc_ptr, link_configuration_ptr->PSKc, 16); 01770 } 01771 #endif 01772 coap_service_request_send(this->coap_service_id, options, destination_address, THREAD_MANAGEMENT_PORT, 01773 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_JOINER_ENTRUST, COAP_CT_OCTET_STREAM, response_ptr, ptr - response_ptr, thread_management_server_entrust_resp_cb); 01774 ns_dyn_mem_free(response_ptr); 01775 return 0; 01776 } 01777 01778 static void thread_join_ent_timeout_cb(void *arg) 01779 { 01780 thread_management_server_t *this = arg; 01781 if (!this || !this->join_ent_timer) { 01782 return; 01783 } 01784 01785 this->join_ent_timer = NULL; 01786 thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); 01787 return; 01788 } 01789 01790 void joiner_router_recv_commission_msg(void *cb_res) 01791 { 01792 socket_callback_t *sckt_data = 0; 01793 ns_address_t source_address; 01794 uint8_t rloc16[16]; 01795 uint8_t relay_destination_address[16]; 01796 uint8_t *data_ptr = NULL; 01797 uint16_t data_len = 0; 01798 uint8_t *ptr; 01799 uint8_t *payload_ptr; 01800 uint16_t payload_len; 01801 char *destination_uri_ptr = THREAD_URI_RELAY_RECEIVE; 01802 sckt_data = cb_res; 01803 int ret MAYBE_UNUSED = -1; 01804 01805 thread_management_server_t *this = thread_management_find_by_sckt_id(sckt_data->socket_id); 01806 01807 if (!this) { 01808 return; 01809 } 01810 01811 if (0 != thread_management_get_ml16_address(this->interface_id, rloc16)) { 01812 return; 01813 } 01814 // Specification issue needs hack to make one concurrent relay working 01815 if (0 != (ret = thread_commissioning_if_border_router_locator_get(this->interface_id, relay_destination_address))) { 01816 tr_err("invalid commissioner address ret %d", ret); 01817 return; 01818 } 01819 01820 if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) { 01821 data_ptr = ns_dyn_mem_alloc(sckt_data->d_len); 01822 if (!data_ptr) { 01823 tr_err("Out of memory"); 01824 return; 01825 } 01826 data_len = socket_read(sckt_data->socket_id, &source_address, data_ptr, sckt_data->d_len); 01827 } 01828 if (!data_ptr || data_len < 1) { 01829 tr_err("No data received"); 01830 return; 01831 } 01832 01833 payload_len = 4 + data_len + 4 + 8 + 4 + 2 + 4 + 2; //Joiner DTLS Encapsulation TLV Joiner UDP Port TLV Joiner IID TLV Joiner Router Locator TLV 01834 payload_ptr = ns_dyn_mem_alloc(payload_len); 01835 01836 if (!payload_ptr) { 01837 tr_err("Out of memory"); 01838 ns_dyn_mem_free(data_ptr); 01839 return; 01840 } 01841 tr_debug("Relay TX recvfrom addr: %s, port:%d len:%d", trace_ipv6(source_address.address), source_address.identifier, data_len); 01842 thci_trace("joinerrouterJoinerDataRelayedInbound"); 01843 ptr = payload_ptr; 01844 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr); 01845 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &source_address.address[8]); 01846 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, source_address.identifier); 01847 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, 2, &rloc16[14]); 01848 01849 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, relay_destination_address, THREAD_MANAGEMENT_PORT, 01850 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, destination_uri_ptr, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); 01851 ns_dyn_mem_free(payload_ptr); 01852 ns_dyn_mem_free(data_ptr); 01853 } 01854 static int thread_management_server_relay_tx_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 01855 { 01856 thread_management_server_t *this = thread_management_find_by_service(service_id); 01857 ns_address_t destination_address = { .address = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; 01858 uint8_t *kek_ptr; 01859 uint8_t *udp_data_ptr; 01860 uint16_t udp_data_len; 01861 uint8_t *iid_ptr; 01862 uint16_t port; 01863 (void)source_address; 01864 (void)source_port; 01865 01866 if (!this) { 01867 return -1; 01868 } 01869 01870 // unwrap message and send to joiner socket. 01871 if (8 > thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &iid_ptr) || 01872 2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &port) || 01873 0 == (udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_data_ptr)) 01874 ) { 01875 tr_err("Relay TX invalid message"); 01876 return -1; 01877 } 01878 memcpy(&destination_address.address[8], iid_ptr, 8); 01879 destination_address.identifier = port; 01880 destination_address.type = ADDRESS_IPV6; 01881 int8_t err = socket_sendto(this->listen_socket_joiner, &destination_address, udp_data_ptr, udp_data_len); 01882 if (err < 0) { 01883 tr_err("Relay TX sendto failed %d", err); 01884 } 01885 01886 //if KEK present set pairwise key to joiner and send entrust method 01887 if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { 01888 // KEK present in relay set pairwise key and send entrust 01889 tr_debug("Kek received"); 01890 if (this->join_ent_timer) { 01891 eventOS_timeout_cancel(this->join_ent_timer); 01892 thread_management_server_entrust_send(this, this->destination_address, this->one_time_key); 01893 } 01894 memcpy(this->destination_address, destination_address.address, 16); 01895 memcpy(this->one_time_key, kek_ptr, 16); 01896 this->join_ent_timer = eventOS_timeout_ms(thread_join_ent_timeout_cb, THREAD_DELAY_JOIN_ENT, this); 01897 } 01898 tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); 01899 thci_trace("joinerrouterJoinerDataRelayedOutbound"); 01900 01901 return -1; // OK no response sent 01902 } 01903 01904 int thread_management_server_joiner_router_init(int8_t interface_id) 01905 { 01906 thread_management_server_t *this = thread_management_server_find(interface_id); 01907 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01908 int8_t securityLinkLayer = 0; 01909 bool enable = false; 01910 01911 if (!this || !cur) { 01912 return -1; 01913 } 01914 01915 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01916 // Thread 1.1 commissioner is present 01917 enable = true; 01918 } 01919 if (this->joiner_router_enabled == enable && 01920 this->relay_port_joiner == thread_joiner_port) { 01921 // Joiner router is in correct state 01922 return 0; 01923 } 01924 if (this->joiner_router_enabled) { 01925 // Need to disable Joiner router either because port changed or moving to disabled 01926 thread_management_server_joiner_router_deinit(interface_id); 01927 } 01928 if (!enable) { 01929 // Joiner router should be disabled 01930 tr_info("Joiner router Disable joining"); 01931 return 0; 01932 } 01933 01934 tr_info("Joiner router Enable joining"); 01935 01936 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01937 // Thread 1.1 commissioner is present 01938 this->relay_port_joiner = thread_joiner_port; 01939 01940 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01941 if (this->listen_socket_joiner < 0) { 01942 // Try other ports 01943 while ((this->listen_socket_joiner < 0) && (this->relay_port_joiner < thread_joiner_port + 10)) { 01944 // We try 10 ports after default port 01945 this->relay_port_joiner++; 01946 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01947 } 01948 } 01949 if (this->listen_socket_joiner < 0) { 01950 this->joiner_router_enabled = false; 01951 this->relay_port_joiner = 0; 01952 tr_error("Joiner router init failed"); 01953 return -2; 01954 } 01955 socket_setsockopt(this->listen_socket_joiner, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); 01956 tr_debug("init joiner router port:%d", this->relay_port_joiner); 01957 } 01958 01959 coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_relay_tx_cb); 01960 this->joiner_router_enabled = true; 01961 return 0; 01962 } 01963 01964 void thread_management_server_joiner_router_deinit(int8_t interface_id) 01965 { 01966 thread_management_server_t *this = thread_management_server_find(interface_id); 01967 01968 if (!this) { 01969 return; 01970 } 01971 01972 tr_debug("deinit joiner router"); 01973 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT); 01974 socket_close(this->listen_socket_joiner); 01975 this->listen_socket_joiner = -1; 01976 this->relay_port_joiner = 0; 01977 this->joiner_router_enabled = false; 01978 return; 01979 } 01980 01981 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 01982 { 01983 thread_management_server_t *this = thread_management_server_find(interface_id); 01984 01985 if (!this) { 01986 return -1; 01987 } 01988 01989 server_data->joiner_router_enabled = this->joiner_router_enabled; 01990 server_data->joiner_router_port = this->relay_port_joiner; 01991 server_data->commissioner_port = this->external_commissioner_port; 01992 return 0; 01993 } 01994 01995 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 01996 { 01997 link_configuration_s *linkConfiguration; 01998 01999 if (memcmp(ADDR_LINK_LOCAL_PREFIX, source_address, 8) == 0) { 02000 // Source address is from Link local address 02001 return true; 02002 } 02003 02004 linkConfiguration = thread_joiner_application_get_config(interface_id); 02005 if (!linkConfiguration) { 02006 tr_error("No link cfg for if %d", interface_id); 02007 return false; 02008 } 02009 02010 if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 && 02011 memcmp(source_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0) { 02012 // Source address is RLOC or ALOC 02013 } else if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0) { 02014 // Source address is ML64 TODO this should check that destination address is ALOC or RLOC CoaP Service does not support 02015 } else { 02016 tr_deep("Message out of thread network; ML prefix: %s, src addr: %s", 02017 trace_ipv6_prefix(linkConfiguration->mesh_local_ula_prefix, 64), 02018 trace_ipv6(source_address)); 02019 return false; 02020 } 02021 02022 return true; 02023 } 02024 02025 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 02026 { 02027 int ret_val = -1; 02028 02029 if (strncmp(THREAD_URI_ACTIVE_GET, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 02030 ret_val = thread_management_server_active_get_respond(interface_id, coap_service_id, request_ptr); 02031 } else if (strncmp(THREAD_URI_PENDING_GET, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 02032 ret_val = thread_management_server_pending_get_respond(interface_id, coap_service_id, request_ptr); 02033 } else if (strncmp(THREAD_URI_MANAGEMENT_GET, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 02034 ret_val = thread_management_server_management_get_respond(interface_id, coap_service_id, request_ptr); 02035 } else { 02036 // unrecognized message 02037 tr_warn("Unrecognized tmf msg"); 02038 } 02039 02040 return ret_val; 02041 } 02042 02043 #else // HAVE_THREAD 02044 02045 int thread_management_server_init(int8_t interface_id) 02046 { 02047 (void) interface_id; 02048 return 0; 02049 } 02050 02051 void thread_management_server_delete(int8_t interface_id) 02052 { 02053 (void) interface_id; 02054 } 02055 02056 int thread_management_server_joiner_router_init(int8_t interface_id) 02057 { 02058 (void)interface_id; 02059 return 0; 02060 } 02061 02062 void thread_management_server_joiner_router_deinit(int8_t interface_id) 02063 { 02064 (void) interface_id; 02065 } 02066 02067 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 02068 { 02069 (void) interface_id; 02070 (void) server_data; 02071 return -1; 02072 } 02073 02074 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 02075 { 02076 (void)interface_id; 02077 (void)source_address; 02078 return false; 02079 } 02080 02081 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 02082 { 02083 (void)interface_id; 02084 (void)coap_service_id; 02085 (void)request_ptr; 02086 return -1; 02087 } 02088 #endif //HAVE_THREAD
Generated on Tue Jul 12 2022 13:54:59 by
1.7.2