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_management_server.c
00001 /* 00002 * Copyright (c) 2014-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 00031 #include "nsconfig.h" 00032 #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_extension.h" 00044 #include "6LoWPAN/Thread/thread_discovery.h" 00045 #include "6LoWPAN/Thread/thread_bbr_api_internal.h" 00046 #include "6LoWPAN/Thread/thread_border_router_api_internal.h" 00047 #include "6LoWPAN/MAC/mac_helper.h" 00048 00049 #define TRACE_GROUP "TMFs" 00050 00051 #include "eventOS_event_timer.h" 00052 #include "coap_service_api.h" 00053 00054 #include "net_interface.h" 00055 #include "socket_api.h" 00056 #include "thread_common.h" 00057 #include "thread_config.h" 00058 #include "thread_tmfcop_lib.h" 00059 #include "thread_meshcop_lib.h" 00060 #include "thread_management_if.h" 00061 #include "thread_management_internal.h" 00062 #include "thread_commissioning_if.h" 00063 #include "thread_joiner_application.h" 00064 #include "thread_beacon.h" 00065 #include "thread_bootstrap.h" 00066 #include "thread_management_server.h" 00067 #include "mac_api.h" 00068 #include "6LoWPAN/MAC/mac_data_poll.h" 00069 #include "mlme.h" 00070 00071 #ifdef HAVE_THREAD 00072 00073 typedef struct scan_query { 00074 int8_t coap_service_id; 00075 uint8_t channel_mask[6]; //<!** first byte is channel page 00076 uint16_t channel_mask_len; 00077 uint8_t *energy_list_ptr; 00078 uint8_t energy_list_length; 00079 uint8_t scan_count; 00080 timeout_t *timer; 00081 uint8_t address[16]; 00082 uint16_t port; 00083 uint16_t panid; 00084 uint8_t count; 00085 uint16_t period; 00086 uint16_t duration; 00087 bool panid_scan: 1; 00088 bool energy_scan: 1; 00089 } scan_query_t; 00090 00091 typedef struct announce { 00092 uint8_t channel_mask[6]; //<!** first byte is channel page support only channel page 0 00093 uint16_t channel_mask_len; 00094 timeout_t *timer; 00095 uint8_t count; 00096 uint16_t period; 00097 uint16_t channel; 00098 } announce_t; 00099 00100 typedef struct thread_management_server { 00101 scan_query_t *scan_ptr; 00102 announce_t *announce_ptr; 00103 uint16_t relay_port_joiner; 00104 uint16_t external_commissioner_port; 00105 int8_t interface_id; 00106 int8_t coap_service_id; 00107 int8_t listen_socket_joiner; 00108 bool joiner_router_enabled: 1; 00109 ns_list_link_t link; 00110 } thread_management_server_t; 00111 00112 static NS_LIST_DEFINE(instance_list, thread_management_server_t, link); 00113 void thread_energy_scan_timeout_cb(void* arg); 00114 00115 static bool thread_channel_mask_is_channel_set(uint8_t *mask_ptr, uint8_t channel) 00116 { 00117 uint8_t n; 00118 uint8_t bit; 00119 00120 n = (channel) / 8; 00121 bit = 1 << (7 - (channel) % 8); 00122 00123 if (n > 5 || channel > 27) 00124 return false; 00125 if( mask_ptr[n+2] & bit ) 00126 return true; 00127 return false; 00128 } 00129 00130 00131 static uint8_t thread_channel_mask_count(uint8_t *mask_ptr) 00132 { 00133 uint8_t n; 00134 uint8_t result = 0; 00135 uint32_t bits; 00136 00137 bits = common_read_32_bit(mask_ptr+2); 00138 bits = bits >> 5;// five lover bits are not used 00139 for (n= 0; n < 27;n++) { 00140 if((bits & 1)== 1) 00141 result++; 00142 bits = bits >> 1; 00143 } 00144 tr_debug ("Channel mask count = %d ", result); 00145 return result; 00146 } 00147 00148 /*This method identifies the channels to be scanned based on the bits set in the channel mask 00149 * */ 00150 static uint8_t thread_channels_to_be_scanned(uint8_t *mask_ptr) 00151 { 00152 uint8_t result = 0; 00153 uint8_t val = 1; 00154 uint8_t *ptr = mask_ptr + 2; // first two bytes do not contain the channels to be scanned 00155 uint8_t j = 0; 00156 while (j<4){ 00157 00158 // one channel for every bit that is set in the mask ptr 00159 for (int i = 0; i<8 ; i++){ 00160 if (val & (*ptr)){ 00161 result++; 00162 } 00163 val = val << 1; 00164 } 00165 val = 1; 00166 ptr++; 00167 j++; 00168 } 00169 return result; 00170 } 00171 00172 static thread_management_server_t *thread_management_server_find(int8_t interface_id) 00173 { 00174 thread_management_server_t *this = NULL; 00175 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00176 if (cur_ptr->interface_id == interface_id) { 00177 this = cur_ptr; 00178 break; 00179 } 00180 } 00181 return this; 00182 } 00183 static thread_management_server_t *thread_management_find_by_service(int8_t service_id) 00184 { 00185 thread_management_server_t *this = NULL; 00186 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00187 if (cur_ptr->coap_service_id == service_id) { 00188 this = cur_ptr; 00189 break; 00190 } 00191 } 00192 return this; 00193 } 00194 00195 static thread_management_server_t *thread_management_find_by_sckt_id(int8_t sckt_id) 00196 { 00197 thread_management_server_t *this = NULL; 00198 ns_list_foreach(thread_management_server_t, cur_ptr, &instance_list) { 00199 if (cur_ptr->listen_socket_joiner == sckt_id) { 00200 this = cur_ptr; 00201 break; 00202 } 00203 } 00204 return this; 00205 } 00206 00207 static bool tlv_is_requested(uint8_t *tlv_list, uint16_t list_len, uint8_t tlv) 00208 { 00209 if (!list_len || !tlv_list) { 00210 return true; 00211 } 00212 for(uint16_t n = 0; n<list_len; n++) { 00213 if (tlv_list[n] == tlv ) 00214 return true; 00215 } 00216 return false; 00217 } 00218 00219 static int thread_management_server_management_get_respond(int8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00220 { 00221 uint8_t *ptr = NULL; 00222 int response_len; 00223 uint8_t *response_ptr = NULL; 00224 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00225 link_configuration_s *link_configuration; 00226 device_configuration_s *device_configuration; 00227 00228 link_configuration = thread_joiner_application_get_config(interface_id); 00229 device_configuration = thread_joiner_application_get_device_config(interface_id); 00230 00231 if(!link_configuration || !device_configuration){ 00232 return -1; 00233 } 00234 00235 tr_debug("Recv MGMT_GET request"); 00236 00237 response_len = thread_joiner_application_device_configuration_length(device_configuration); 00238 response_ptr = ptr = ns_dyn_mem_alloc(response_len); 00239 if (!ptr) { 00240 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00241 tr_error("Out of resources"); 00242 goto send_response; 00243 } 00244 ptr = thread_joiner_application_device_configuration_build(ptr, device_configuration); 00245 return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00246 00247 send_response: 00248 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, response_ptr, ptr -response_ptr); 00249 ns_dyn_mem_free(response_ptr); 00250 return 0; 00251 } 00252 00253 static int thread_management_server_active_get_respond(uint8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00254 { 00255 link_configuration_s *link_configuration; 00256 uint8_t *request_tlv_ptr = NULL; 00257 uint8_t *request_tlv_copy = NULL; 00258 uint16_t request_tlv_len; 00259 uint8_t *ptr = NULL; 00260 uint8_t *payload_ptr = NULL; 00261 uint8_t *response_ptr = NULL; 00262 uint8_t error_msg[3]; 00263 int response_len; 00264 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00265 00266 link_configuration = thread_joiner_application_get_config(interface_id); 00267 if(!link_configuration){ 00268 return -1; 00269 } 00270 00271 tr_debug("Recv MGMT_ACTIVE_GET request"); 00272 00273 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00274 00275 if(!request_tlv_len){ 00276 request_tlv_copy = request_tlv_ptr = thread_joiner_application_active_config_tlv_list_get(interface_id, &request_tlv_len); 00277 } 00278 00279 if(!request_tlv_ptr){ 00280 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00281 goto send_response; 00282 } 00283 00284 if(request_tlv_len && !(link_configuration->securityPolicy & SECURITY_POLICY_OUT_OF_BAND_COMMISSIONING_ALLOWED)){ 00285 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_NETWORK_MASTER_KEY); 00286 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_SECURITY_POLICY); 00287 } 00288 00289 if (!request_tlv_len) { 00290 goto send_response; 00291 } 00292 00293 response_len = thread_joiner_application_active_config_length(interface_id, request_tlv_ptr, request_tlv_len, NULL, 0); 00294 00295 payload_ptr = ptr = error_msg; 00296 if(response_len < 1){ 00297 //Error in message is responded with Thread status or if we have access rights problem 00298 goto send_response; 00299 } 00300 payload_ptr = ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00301 if (!response_ptr) { 00302 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00303 goto send_response; 00304 } 00305 memset(response_ptr, 0, response_len); 00306 00307 ptr = thread_joiner_application_active_config_write(interface_id, ptr, request_tlv_ptr, request_tlv_len, NULL, 0); 00308 00309 send_response: 00310 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE,request_ptr, return_code, COAP_CT_OCTET_STREAM,payload_ptr, ptr - payload_ptr); 00311 ns_dyn_mem_free(response_ptr); 00312 ns_dyn_mem_free(request_tlv_copy); 00313 return 0; 00314 } 00315 00316 static int thread_management_server_pending_get_respond(int8_t interface_id, int8_t coap_service_id, sn_coap_hdr_s *request_ptr) 00317 { 00318 link_configuration_s *link_configuration; 00319 uint8_t *request_tlv_ptr = NULL; 00320 uint8_t *request_tlv_copy = NULL; 00321 uint16_t request_tlv_len; 00322 uint8_t *ptr; 00323 uint8_t *payload_ptr; 00324 uint8_t *response_ptr = NULL; 00325 uint8_t error_msg[3]; 00326 int response_len; 00327 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00328 00329 tr_debug("Recv MGMT_PENDING_GET request"); 00330 payload_ptr = ptr = error_msg; 00331 link_configuration = thread_joiner_application_get_config(interface_id); 00332 00333 if (!link_configuration) { 00334 return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00335 goto send_response; 00336 } 00337 if (!thread_joiner_application_pending_config_exists(interface_id)) { 00338 goto send_response; 00339 } 00340 00341 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00342 00343 if(!request_tlv_len){ 00344 request_tlv_copy = request_tlv_ptr = thread_joiner_application_pending_config_tlv_list_get(interface_id, &request_tlv_len); 00345 } 00346 00347 if(!request_tlv_ptr){ 00348 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00349 goto send_response; 00350 } 00351 00352 if(request_tlv_len && !(link_configuration->securityPolicy & SECURITY_POLICY_OUT_OF_BAND_COMMISSIONING_ALLOWED)){ 00353 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_NETWORK_MASTER_KEY); 00354 request_tlv_len = thread_meshcop_tlv_list_remove(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_SECURITY_POLICY); 00355 } 00356 00357 if (!request_tlv_len) { 00358 goto send_response; 00359 } 00360 00361 response_len = thread_joiner_application_pending_config_length(interface_id, request_tlv_ptr, request_tlv_len, NULL, 0); 00362 00363 payload_ptr = ptr = response_ptr = ns_dyn_mem_alloc(response_len); 00364 if (!response_ptr) { 00365 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00366 goto send_response; 00367 } 00368 memset(response_ptr, 0, response_len); 00369 00370 ptr = thread_joiner_application_pending_config_build(interface_id, ptr,request_tlv_ptr, request_tlv_len, NULL, 0); 00371 00372 send_response: 00373 coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE,request_ptr, return_code, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr); 00374 ns_dyn_mem_free(response_ptr); 00375 ns_dyn_mem_free(request_tlv_copy); 00376 return 0; 00377 } 00378 00379 /** 00380 * Thread management GET command callback. 00381 * Handle messages: 00382 * -MGMT_GET (uri = /c/mg), 00383 * -MGMT_ACTIVE_GET (uri = /c/ag), 00384 * -MGMT_PENDING_GET (uri = /c/pg) 00385 */ 00386 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) 00387 { 00388 (void) source_port; 00389 00390 thread_management_server_t *this = thread_management_find_by_service(service_id); 00391 00392 if (!this) { 00393 return -1; 00394 } 00395 00396 if (!thread_management_server_source_address_check(this->interface_id, source_address)) { 00397 // request is coming from illegal address, return error immediately 00398 coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_BAD_REQUEST, COAP_CT_OCTET_STREAM, NULL, 0); 00399 return 0; 00400 } 00401 00402 return thread_management_server_tmf_get_request_handler(this->interface_id, service_id, request_ptr); 00403 00404 } 00405 00406 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) 00407 { 00408 (void) source_address; 00409 (void) source_port; 00410 protocol_interface_info_entry_t *cur; 00411 thread_management_server_t *this = thread_management_find_by_service(service_id); 00412 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00413 uint8_t response_msg[2+2 + 2+2 + 2+16 +2+2]; 00414 uint8_t *request_tlv_ptr = NULL; 00415 uint16_t request_tlv_len; 00416 uint8_t *ptr; 00417 uint8_t *payload_ptr = NULL; 00418 if (!this) { 00419 return -1; 00420 } 00421 tr_debug("Thread management commission get request"); 00422 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00423 if (!cur || !cur->thread_info) { 00424 return -1; 00425 } 00426 payload_ptr = ptr = response_msg; 00427 00428 if (!thread_management_server_source_address_check(this->interface_id, source_address)) { 00429 return_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00430 goto send_response; 00431 } 00432 00433 if (!cur->thread_info->registered_commissioner.commissioner_valid) { 00434 //Error in message is responded with Thread status or if we have access rights problem 00435 tr_warn("No registered commissioner"); 00436 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00437 goto send_response; 00438 } 00439 uint16_t border_router_locator = common_read_16_bit( &cur->thread_info->registered_commissioner.border_router_address[14]); 00440 request_tlv_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_GET, &request_tlv_ptr); 00441 00442 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_BORDER_ROUTER_LOCATOR)) 00443 ptr = thread_meshcop_tlv_data_write_uint16(ptr,MESHCOP_TLV_BORDER_ROUTER_LOCATOR, border_router_locator); 00444 00445 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID)) 00446 ptr = thread_meshcop_tlv_data_write_uint16(ptr,MESHCOP_TLV_COMMISSIONER_SESSION_ID, cur->thread_info->registered_commissioner.session_id); 00447 00448 if (tlv_is_requested(request_tlv_ptr, request_tlv_len, MESHCOP_TLV_STEERING_DATA)) 00449 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); 00450 00451 if (payload_ptr == ptr) { 00452 tr_warn("No TLVs found"); 00453 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 0xff); 00454 goto send_response; 00455 } 00456 send_response: 00457 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE,request_ptr, return_code, COAP_CT_OCTET_STREAM,payload_ptr, ptr - payload_ptr); 00458 return 0; 00459 } 00460 00461 static int thread_start_mac_with_link_configuration(protocol_interface_info_entry_t *cur, link_configuration_s *linkConfiguration) 00462 { 00463 mlme_start_t start_req; 00464 memset(&start_req, 0, sizeof(mlme_start_t)); 00465 /*Enable RF interface */ 00466 if (!(cur->lowpan_info & INTERFACE_NWK_CONF_MAC_RX_OFF_IDLE)) { 00467 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, true); 00468 } else { 00469 mac_helper_pib_boolean_set(cur, macRxOnWhenIdle, false); 00470 } 00471 00472 mac_helper_default_security_level_set(cur, SEC_ENC_MIC32); 00473 mac_helper_default_security_key_id_mode_set(cur,MAC_KEY_ID_MODE_IDX); 00474 00475 cur->mac_parameters->mac_channel = linkConfiguration->rfChannel; 00476 cur->mac_parameters->pan_id = linkConfiguration->panId; 00477 cur->mac_parameters->mac_channel = linkConfiguration->rfChannel; 00478 00479 start_req.PANId = linkConfiguration->panId; 00480 start_req.LogicalChannel = linkConfiguration->rfChannel; 00481 start_req.ChannelPage = 0; 00482 start_req.BeaconOrder = 0x0f; 00483 start_req.SuperframeOrder = 0x0f; 00484 00485 cur->interface_mode = INTERFACE_UP; 00486 thread_discovery_responser_enable(cur->id, false); 00487 if( cur->mac_api ){ 00488 cur->mac_api->mlme_req(cur->mac_api, MLME_START, (void*)&start_req); 00489 } 00490 if (cur->thread_info->sleepy_host_poll_time != 0) { 00491 mac_data_poll_host_mode_set(cur,NET_HOST_SLOW_POLL_MODE,cur->thread_info->sleepy_host_poll_time); 00492 } else { 00493 mac_data_poll_init(cur); 00494 } 00495 00496 return 0; 00497 } 00498 00499 00500 static void thread_panid_conflict_timeout_cb(void* arg) 00501 { 00502 uint8_t payload[12];// 2+6 + 2+2 00503 uint8_t *ptr; 00504 thread_management_server_t *this = arg; 00505 if(!this || !this->scan_ptr) 00506 { 00507 tr_error("panid conflict scan ptr missing"); 00508 return; 00509 } 00510 00511 this->scan_ptr->timer = NULL; 00512 00513 ptr = payload; 00514 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_PANID, this->scan_ptr->panid); 00515 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_CHANNEL_MASK, this->scan_ptr->channel_mask_len, this->scan_ptr->channel_mask); 00516 //Send pan id conflict coap 00517 coap_service_request_send(this->scan_ptr->coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->scan_ptr->address, this->scan_ptr->port, 00518 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_PANID_CONFLICT, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL); 00519 ns_dyn_mem_free(this->scan_ptr); 00520 this->scan_ptr = NULL; 00521 } 00522 00523 //style = 0 means thread style, style = anything else means zigbee style 00524 // for thread style the bit is set from left to right and for zigbee style it is set from right to left 00525 static void set_channel_mask(uint8_t *channel_mask,uint8_t channel_number, uint8_t style) 00526 { 00527 uint8_t byte_position; 00528 uint8_t bit_position; 00529 if (0 == style){ 00530 byte_position = channel_number / 8; 00531 bit_position = 7 - (channel_number % 8); 00532 channel_mask[byte_position + 2] |= (1 << bit_position); 00533 return; 00534 } 00535 else { 00536 byte_position = 3 - (channel_number / 8); 00537 bit_position = channel_number % 8; 00538 channel_mask[byte_position + 2] |= (1 << bit_position); 00539 return; 00540 } 00541 } 00542 static uint32_t reverse_bits(uint32_t num) 00543 { 00544 uint32_t NO_OF_BITS = sizeof(num) * 8; 00545 uint32_t reversed_value = 0, i, temp; 00546 for (i = 0; i < NO_OF_BITS; i++){ 00547 temp = (num & (1 << i)); 00548 if(temp) 00549 reversed_value |= (1 << ((NO_OF_BITS - 1) - i)); 00550 } 00551 return reversed_value; 00552 } 00553 static void thread_panid_scan_response(int8_t if_id, const mlme_scan_conf_t* conf) 00554 { 00555 bool conflict_occured = false; 00556 nwk_scan_params_t *scan_parameters_ptr; 00557 nwk_pan_descriptor_t *result; 00558 protocol_interface_info_entry_t *interface; 00559 link_configuration_s *linkConfiguration; 00560 00561 if (conf->ScanType != MAC_ACTIVE_SCAN) { 00562 tr_error("Not active scan"); 00563 return; 00564 } 00565 00566 interface = protocol_stack_interface_info_get_by_id(if_id); 00567 if (!interface) { 00568 tr_error("Mac scan confirm:Unknow Interface"); 00569 return; 00570 } 00571 00572 linkConfiguration = thread_joiner_application_get_config(if_id); 00573 if (!linkConfiguration) { 00574 return; 00575 } 00576 00577 scan_parameters_ptr = &interface->mac_parameters->nwk_scan_params; //mac_mlme_get_scan_params(interface); 00578 if (!scan_parameters_ptr ||!scan_parameters_ptr->nwk_response_info || !conf->ResultListSize) { 00579 tr_debug("Mac scan confirm:No Beacons"); 00580 thread_start_mac_with_link_configuration(interface,linkConfiguration); 00581 return; 00582 } 00583 scan_parameters_ptr->active_scan_active = false; 00584 00585 thread_management_server_t *this = thread_management_server_find(if_id); 00586 00587 if (!this) { 00588 return; 00589 } 00590 00591 result = scan_parameters_ptr->nwk_response_info; 00592 // reset all channel masks 00593 this->scan_ptr->channel_mask[2] = 0x00; 00594 this->scan_ptr->channel_mask[3] = 0x00; 00595 this->scan_ptr->channel_mask[4] = 0x00; 00596 this->scan_ptr->channel_mask[5] = 0x00; 00597 do { 00598 tr_debug("Mac scan confirm:scanning results"); 00599 if(result->pan_descriptor->CoordPANId == this->scan_ptr->panid) { //if pan id matches then send a conflict message 00600 tr_debug("Same pan id was found on channel %d", result->pan_descriptor->LogicalChannel); 00601 set_channel_mask(this->scan_ptr->channel_mask,result->pan_descriptor->LogicalChannel,0); 00602 conflict_occured = true; 00603 } 00604 result = result->next; 00605 } while (result); 00606 if (conflict_occured){ 00607 tr_debug("conflict occured"); 00608 this->scan_ptr->timer = eventOS_timeout_ms(thread_panid_conflict_timeout_cb, 2000, this); 00609 } 00610 thread_start_mac_with_link_configuration(interface,linkConfiguration); 00611 //TODO if no conflict scan again after delay seconds 00612 } 00613 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) 00614 { 00615 // Dummy response handler needed as otherwise retransmissions dont work in coap service. 00616 (void)service_id; 00617 (void)source_address; 00618 (void)source_port; 00619 (void)response_ptr; 00620 return 0; 00621 } 00622 00623 static void thread_energy_scan_coap(thread_management_server_t *arg) 00624 { 00625 uint8_t *ptr; 00626 thread_management_server_t *this = arg; 00627 link_configuration_s *linkConfiguration; 00628 protocol_interface_info_entry_t *interface; 00629 00630 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 00631 if (!linkConfiguration) { 00632 return; 00633 } 00634 00635 interface = protocol_stack_interface_info_get_by_id(this->interface_id); 00636 if (!interface) { 00637 tr_error("Mac scan confirm:Unknow Interface"); 00638 return; 00639 } 00640 00641 thread_start_mac_with_link_configuration(interface,linkConfiguration); 00642 uint8_t channel_count = thread_channels_to_be_scanned(this->scan_ptr->channel_mask); 00643 tr_debug("energy scan result mask %s, result %s, count %d",trace_array(this->scan_ptr->channel_mask,6), 00644 trace_array(this->scan_ptr->energy_list_ptr,channel_count* this->scan_ptr->count),channel_count); 00645 00646 00647 uint8_t *payload_ptr = ns_dyn_mem_alloc( 2 + 6 + 2 + channel_count * this->scan_ptr->count); 00648 if (!payload_ptr) { 00649 tr_error("out of resources"); 00650 return; 00651 } 00652 ptr = payload_ptr; 00653 00654 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_CHANNEL_MASK, this->scan_ptr->channel_mask_len, this->scan_ptr->channel_mask); 00655 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_ENERGY_LIST, channel_count * this->scan_ptr->count, this->scan_ptr->energy_list_ptr); 00656 00657 coap_service_request_send(this->scan_ptr->coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->scan_ptr->address, this->scan_ptr->port, 00658 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); 00659 ns_dyn_mem_free(payload_ptr); 00660 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 00661 ns_dyn_mem_free(this->scan_ptr); 00662 this->scan_ptr = NULL; 00663 } 00664 00665 static void energy_scan_confirm_cb(int8_t if_id, const mlme_scan_conf_t* conf) 00666 { 00667 if (conf->ScanType != MAC_ED_SCAN_TYPE) { 00668 tr_error("Not energy scan"); 00669 return; 00670 } 00671 00672 if (conf->ResultListSize < 1){ 00673 tr_error("No scan responses"); 00674 return; 00675 } 00676 00677 protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(if_id); 00678 if (!interface) { 00679 tr_error("could not get interface"); 00680 return; 00681 } 00682 00683 thread_management_server_t *this = thread_management_server_find(if_id); 00684 if (!this) { 00685 tr_error("could not find thread management server"); 00686 return; 00687 } 00688 // reduce the scan_count by one since one scan has been performed and results are also obtained 00689 this->scan_ptr->scan_count--; 00690 00691 for( int i=0; i < conf->ResultListSize; i++){ 00692 *this->scan_ptr->energy_list_ptr++ = conf->ED_values[i]; 00693 } 00694 00695 link_configuration_s *linkConfiguration = thread_joiner_application_get_config(this->interface_id); 00696 if (!linkConfiguration) { 00697 return; 00698 } 00699 00700 //the energy list has now the response_size set of responses so increase the length of energy_list_length 00701 this->scan_ptr->energy_list_length += conf->ResultListSize; 00702 00703 // if all scans have been completed then, move the energy_list_ptr back to the beginning 00704 if (this->scan_ptr->scan_count == 0){ 00705 this->scan_ptr->energy_list_ptr-=this->scan_ptr->energy_list_length; 00706 thread_energy_scan_coap(this); 00707 } 00708 else{ 00709 // if all scans have not been completed, enable RF, wait for scan period and call energy scan method again 00710 thread_start_mac_with_link_configuration(interface,linkConfiguration); 00711 if (this->scan_ptr->timer) { 00712 eventOS_timeout_cancel(this->scan_ptr->timer); 00713 } 00714 this->scan_ptr->timer = eventOS_timeout_ms(thread_energy_scan_timeout_cb, this->scan_ptr->period, this); 00715 } 00716 } 00717 00718 void thread_energy_scan_timeout_cb(void* arg) 00719 { 00720 link_configuration_s *linkConfiguration; 00721 thread_management_server_t *this = arg; 00722 if(!this || !this->scan_ptr || !this->scan_ptr->energy_list_ptr){ 00723 tr_error("Invalid query"); 00724 return; 00725 } 00726 00727 this->scan_ptr->timer = NULL; 00728 00729 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 00730 if (!linkConfiguration) { 00731 return; 00732 } 00733 00734 protocol_interface_info_entry_t *s; 00735 s = protocol_stack_interface_info_get_by_id(this->interface_id); 00736 00737 if (!s) { 00738 return; 00739 } 00740 00741 uint32_t channel_mask = 0; 00742 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]); 00743 //Modify reversed_mask after the right way to interpret channel mask is obtained 00744 uint32_t reversed_mask = reverse_bits(channel_mask); 00745 channel_mask = reversed_mask; 00746 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0] = channel_mask; 00747 //Channel page is 0 for thread 00748 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_page = CHANNEL_PAGE_0; 00749 00750 // Convert duration in ms to MAC exponent value 00751 uint8_t duration_n; 00752 if(this->scan_ptr->duration <= (CHANNEL_PAGE_0_SUPERFRAME_DURATION * 2)) { 00753 duration_n = 0; 00754 } else { 00755 duration_n = thread_log2_aprx((this->scan_ptr->duration / CHANNEL_PAGE_0_SUPERFRAME_DURATION) - 1); 00756 } 00757 00758 // 10 == 15.7s 00759 // 11 == 31.5s 00760 // 12 == 62.9s 00761 // 13 == 125.8s (maximum when duration is 65535 and result of log2 is rounded up) 00762 // 14 == 251.6s (not possible) 00763 tr_debug("Start Energy scan duration:%d", duration_n); 00764 mac_data_poll_disable(s); 00765 mlme_scan_t req; 00766 mac_create_scan_request(MAC_ED_SCAN_TYPE, &s->mac_parameters->nwk_scan_params.stack_chan_list, duration_n, &req); 00767 if( s->mac_api ){ 00768 s->scan_cb = energy_scan_confirm_cb; 00769 s->mac_api->mlme_req(s->mac_api, MLME_SCAN, &req); 00770 } 00771 } 00772 00773 00774 static void thread_panid_scan_timeout_cb(void* arg) 00775 { 00776 thread_management_server_t *this = arg; 00777 if(!this || !this->scan_ptr) 00778 return; 00779 00780 this->scan_ptr->timer = NULL; 00781 00782 00783 protocol_interface_info_entry_t *s; 00784 s = protocol_stack_interface_info_get_by_id(this->interface_id); 00785 00786 if (!s || !s->mac_api) { 00787 return; 00788 } 00789 00790 uint32_t channel_mask = 0; 00791 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]); 00792 //Modify reversed_mask after the right way to interpret channel mask is obtained 00793 uint32_t reversed_mask = reverse_bits(channel_mask); 00794 channel_mask = reversed_mask; 00795 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_mask[0] = channel_mask; 00796 //Channel page is 0 for thread 00797 s->mac_parameters->nwk_scan_params.stack_chan_list.channel_page = CHANNEL_PAGE_0; 00798 mac_data_poll_disable(s); 00799 mlme_scan_t req; 00800 mac_create_scan_request(MAC_ACTIVE_SCAN, &s->mac_parameters->nwk_scan_params.stack_chan_list, 5, &req); 00801 /* 00802 Before commencing an active or passive scan, the MAC sub-layer shall store the value of macPANId and 00803 then set it to 0xffff for the duration of the scan. This enables the receive filter to accept all beacons rather 00804 than just the beacons from its current PAN, as described in 5.1.6.2. On completion of the scan, the MAC 00805 sub-layer shall restore the value of macPANId to the value stored before the scan began. 00806 */ 00807 mac_helper_panid_set(s,0xffff); 00808 00809 s->scan_cb = thread_panid_scan_response; 00810 s->mac_parameters->nwk_scan_params.active_scan_active = true; 00811 s->mac_api->mlme_req(s->mac_api, MLME_SCAN, &req); 00812 } 00813 00814 00815 /** 00816 * Thread PANID scan request 00817 */ 00818 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) 00819 { 00820 thread_management_server_t *this = thread_management_find_by_service(service_id); 00821 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00822 uint16_t session_id; 00823 uint16_t panid; 00824 uint8_t *mask_ptr; 00825 uint8_t mask_len; 00826 00827 if (!this) { 00828 return -1; 00829 } 00830 tr_debug("thread management panid query"); 00831 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 00832 tr_warn("Missing Session id TLV"); 00833 goto error_exit; 00834 } 00835 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PANID, &panid)) { 00836 tr_warn("Missing PANID TLV"); 00837 goto error_exit; 00838 } 00839 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 00840 if (mask_len < 6 ) { 00841 tr_warn("Missing channel mask TLV"); 00842 goto error_exit; 00843 } 00844 tr_info("PANID TLV %02x, session_id %d, Channel mask TLV %s", panid, session_id, trace_array(mask_ptr, 5)); 00845 00846 if (!this->scan_ptr) { 00847 this->scan_ptr = ns_dyn_mem_alloc(sizeof(scan_query_t)); 00848 memset(this->scan_ptr,0,sizeof(scan_query_t)); 00849 } else { 00850 eventOS_timeout_cancel(this->scan_ptr->timer); 00851 this->scan_ptr->timer = NULL; 00852 } 00853 if (!this->scan_ptr) { 00854 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00855 goto error_exit; 00856 } 00857 this->scan_ptr->timer = eventOS_timeout_ms(thread_panid_scan_timeout_cb, 500, this);// Delay for the confirm response message 00858 if (!this->scan_ptr->timer) { 00859 ns_dyn_mem_free(this->scan_ptr); 00860 this->scan_ptr = NULL; 00861 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00862 goto error_exit; 00863 } 00864 00865 this->scan_ptr->coap_service_id = service_id; 00866 memcpy(this->scan_ptr->channel_mask,mask_ptr,mask_len); 00867 this->scan_ptr->channel_mask_len = mask_len; 00868 this->scan_ptr->port = source_port; 00869 memcpy(this->scan_ptr->address,source_address,16); 00870 this->scan_ptr->panid = panid; 00871 this->scan_ptr->panid_scan = true; 00872 00873 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ){ 00874 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); 00875 return 0; 00876 } 00877 return -1; 00878 error_exit: 00879 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ){ 00880 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 00881 return 0; 00882 } 00883 00884 return -1; 00885 } 00886 /** 00887 * Thread PANID scan request 00888 */ 00889 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) 00890 { 00891 thread_management_server_t *this = thread_management_find_by_service(service_id); 00892 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00893 uint16_t period; 00894 uint16_t session_id; 00895 uint8_t count; 00896 uint16_t duration; 00897 uint8_t *mask_ptr; 00898 uint8_t mask_len; 00899 00900 00901 if (!this) { 00902 return -1; 00903 } 00904 tr_debug("thread management energy scan"); 00905 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PERIOD, &period)) { 00906 tr_warn("Missing PERIOD TLV"); 00907 goto error_exit; 00908 } 00909 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 00910 tr_warn("Missing Session id TLV"); 00911 goto error_exit; 00912 } 00913 if (1 > thread_meshcop_tlv_data_get_uint8(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COUNT, &count)) { 00914 tr_warn("Missing COUNT TLV"); 00915 goto error_exit; 00916 } 00917 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_DURATION, &duration)) { 00918 tr_warn("Missing DURATION TLV"); 00919 goto error_exit; 00920 } 00921 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 00922 if (mask_len < 6 ) { 00923 tr_warn("Missing channel mask TLV"); 00924 goto error_exit; 00925 } 00926 tr_info("Channel mask TLV %s, period %d, count %d, duration %d", trace_array(mask_ptr, mask_len), period, count, duration); 00927 00928 if (count < 1 || thread_channel_mask_count(mask_ptr) < 1 ) { 00929 // Sanity checks 00930 response_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 00931 goto error_exit; 00932 } 00933 if (!this->scan_ptr) { 00934 this->scan_ptr = ns_dyn_mem_alloc(sizeof(scan_query_t)); 00935 memset(this->scan_ptr,0,sizeof(scan_query_t)); 00936 } else { 00937 eventOS_timeout_cancel(this->scan_ptr->timer); 00938 this->scan_ptr->timer = NULL; 00939 } 00940 if (!this->scan_ptr) { 00941 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00942 goto error_exit; 00943 } 00944 uint16_t channel_count = thread_channels_to_be_scanned(mask_ptr); 00945 00946 this->scan_ptr->energy_list_length = 0; 00947 this->scan_ptr->scan_count = count; 00948 00949 // allocate memory for the energy scan results 00950 this->scan_ptr->energy_list_ptr = ns_dyn_mem_temporary_alloc(channel_count * this->scan_ptr->scan_count); 00951 if(!this->scan_ptr->energy_list_ptr){ 00952 response_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 00953 tr_debug ("Exiting after no energy list ptr was allocated"); 00954 goto error_exit; 00955 } 00956 00957 memset(this->scan_ptr->energy_list_ptr,0,(channel_count* this->scan_ptr->scan_count)); 00958 00959 this->scan_ptr->timer = eventOS_timeout_ms(thread_energy_scan_timeout_cb, 500, this); 00960 00961 if (!this->scan_ptr->timer) { 00962 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00963 goto error_exit; 00964 } 00965 00966 this->scan_ptr->coap_service_id = service_id; 00967 memcpy(this->scan_ptr->channel_mask,mask_ptr,mask_len); 00968 this->scan_ptr->channel_mask_len = mask_len; 00969 this->scan_ptr->port = source_port; 00970 memcpy(this->scan_ptr->address,source_address,16); 00971 this->scan_ptr->count = count; 00972 this->scan_ptr->duration = duration; 00973 this->scan_ptr->period = period; 00974 this->scan_ptr->energy_scan = true; 00975 00976 00977 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ){ 00978 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); 00979 return 0; 00980 } 00981 return -1; 00982 error_exit: 00983 if(this->scan_ptr) { 00984 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 00985 ns_dyn_mem_free(this->scan_ptr); 00986 } 00987 this->scan_ptr = NULL; 00988 00989 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ){ 00990 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 00991 return 0; 00992 } 00993 00994 return -1; 00995 } 00996 00997 00998 static void thread_announce_timeout_cb(void* arg) 00999 { 01000 link_configuration_s *linkConfiguration; 01001 thread_management_server_t *this = arg; 01002 protocol_interface_info_entry_t *cur; 01003 01004 if(!this || !this->announce_ptr) { 01005 return; 01006 } 01007 01008 this->announce_ptr->timer = NULL; 01009 01010 cur = protocol_stack_interface_info_get_by_id(this->interface_id); 01011 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01012 if (!cur || !linkConfiguration) { 01013 return; 01014 } 01015 while (this->announce_ptr->channel < 27) { 01016 if(thread_channel_mask_is_channel_set(this->announce_ptr->channel_mask, this->announce_ptr->channel)) { 01017 break; 01018 } 01019 this->announce_ptr->channel++; 01020 } 01021 if(this->announce_ptr->channel > 26) { 01022 tr_debug("Announce done"); 01023 ns_dyn_mem_free(this->announce_ptr); 01024 this->announce_ptr = NULL; 01025 return; 01026 } 01027 tr_debug("Announce to channel %d",this->announce_ptr->channel); 01028 01029 thread_bootstrap_announcement_start(cur,this->announce_ptr->channel_mask[0],this->announce_ptr->channel, this->announce_ptr->count, this->announce_ptr->period); 01030 01031 this->announce_ptr->channel++; // Next time we start the next channel 01032 this->announce_ptr->timer = eventOS_timeout_ms(thread_announce_timeout_cb, 5000, this); 01033 if (!this->announce_ptr->timer) { 01034 tr_warn("Announce failed"); 01035 ns_dyn_mem_free(this->announce_ptr); 01036 this->announce_ptr = NULL; 01037 return; 01038 } 01039 } 01040 01041 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) 01042 { 01043 thread_management_server_t *this = thread_management_find_by_service(service_id); 01044 link_configuration_s *linkConfiguration; 01045 sn_coap_msg_code_e response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 01046 uint16_t period; 01047 uint16_t session_id; 01048 uint8_t count; 01049 uint8_t *mask_ptr; 01050 uint8_t mask_len; 01051 01052 (void)source_address; 01053 (void)source_port; 01054 01055 if (!this) { 01056 return -1; 01057 } 01058 linkConfiguration = thread_joiner_application_get_config(this->interface_id); 01059 if (!linkConfiguration) { 01060 return -1; 01061 } 01062 01063 tr_debug("thread management announce begin"); 01064 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) { 01065 tr_warn("Missing Session id TLV"); 01066 goto error_exit; 01067 } 01068 if (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_PERIOD, &period)) { 01069 tr_warn("Missing PERIOD TLV"); 01070 goto error_exit; 01071 } 01072 if (1 > thread_meshcop_tlv_data_get_uint8(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_COUNT, &count)) { 01073 tr_warn("Missing COUNT TLV"); 01074 goto error_exit; 01075 } 01076 mask_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_CHANNEL_MASK, &mask_ptr); 01077 if (mask_len < 6 ) { 01078 tr_warn("Missing channel mask TLV"); 01079 goto error_exit; 01080 } 01081 // TODO validity checks session id must be validated 01082 tr_info("start announcing session id %d, mask TLV %s, period %d, count %d",session_id, trace_array(mask_ptr, mask_len), period, count); 01083 01084 if (!this->announce_ptr) { 01085 this->announce_ptr = ns_dyn_mem_alloc(sizeof(announce_t)); 01086 } else { 01087 eventOS_timeout_cancel(this->announce_ptr->timer); 01088 this->announce_ptr->timer = NULL; 01089 } 01090 if (!this->announce_ptr) { 01091 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01092 goto error_exit; 01093 } 01094 this->announce_ptr->timer = eventOS_timeout_ms(thread_announce_timeout_cb, 500, this); 01095 if (!this->announce_ptr->timer) { 01096 ns_dyn_mem_free(this->announce_ptr); 01097 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 01098 goto error_exit; 01099 } 01100 memcpy(this->announce_ptr->channel_mask,mask_ptr,mask_len); 01101 this->announce_ptr->channel_mask_len = mask_len; 01102 this->announce_ptr->count = count; 01103 this->announce_ptr->period = period; 01104 this->announce_ptr->channel = 0; 01105 // Set own information to announce 01106 response_code = COAP_MSG_CODE_RESPONSE_CHANGED; 01107 01108 error_exit: 01109 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, response_code, COAP_CT_OCTET_STREAM, NULL, 0); 01110 return 0; 01111 } 01112 01113 /** 01114 * Public interface functions 01115 */ 01116 int thread_management_server_init(int8_t interface_id) 01117 { 01118 01119 thread_management_server_t *this = thread_management_server_find(interface_id); 01120 if (this) { 01121 return 0; 01122 } 01123 01124 this = ns_dyn_mem_alloc(sizeof(thread_management_server_t)); 01125 if (!this) { 01126 return -2; 01127 } 01128 01129 this->joiner_router_enabled = false; 01130 this->interface_id = interface_id; 01131 this->listen_socket_joiner = -1; 01132 this->relay_port_joiner = 0; 01133 this->scan_ptr = NULL; 01134 this->announce_ptr = NULL; 01135 this->external_commissioner_port = THREAD_COMMISSIONING_PORT; 01136 01137 #ifdef HAVE_THREAD_ROUTER 01138 if (thread_border_router_init(this->interface_id) != 0) { 01139 ns_dyn_mem_free(this); 01140 return -5; 01141 } 01142 01143 if (thread_bbr_init(this->interface_id, this->external_commissioner_port) != 0) { 01144 ns_dyn_mem_free(this); 01145 return -5; 01146 } 01147 #endif 01148 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 01149 if (this->coap_service_id < 0) { 01150 tr_warn("Thread management init failed"); 01151 ns_dyn_mem_free(this); 01152 return -3; 01153 } 01154 #ifdef HAVE_THREAD_ROUTER 01155 if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { 01156 tr_warn("Thread leader service init failed"); 01157 ns_dyn_mem_free(this); 01158 return -3; 01159 } 01160 #endif 01161 thread_extension_init(interface_id, this->coap_service_id); 01162 01163 // All thread devices 01164 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01165 01166 // Full functioning devices(Router,reed,fed) 01167 coap_service_register_uri(this->coap_service_id, THREAD_URI_ACTIVE_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01168 coap_service_register_uri(this->coap_service_id, THREAD_URI_PENDING_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01169 coap_service_register_uri(this->coap_service_id, THREAD_URI_COMMISSIONER_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_commissioner_get_cb); 01170 01171 coap_service_register_uri(this->coap_service_id, THREAD_URI_PANID_QUERY, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_panid_query_cb); 01172 coap_service_register_uri(this->coap_service_id, THREAD_URI_ED_SCAN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_energy_scan_cb); 01173 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_ANNOUNCE_BEGIN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_announce_begin_cb); 01174 01175 ns_list_add_to_start(&instance_list, this); 01176 return 0; 01177 } 01178 01179 void thread_management_server_delete(int8_t interface_id) 01180 { 01181 thread_management_server_t *this = thread_management_server_find(interface_id); 01182 if (!this) { 01183 return; 01184 } 01185 01186 thread_leader_service_delete(interface_id); 01187 01188 if (this->joiner_router_enabled) { 01189 thread_management_server_joiner_router_deinit(interface_id); 01190 } 01191 //TODO move uri deletion to delete 01192 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); 01193 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); 01194 coap_service_delete(this->coap_service_id); 01195 ns_list_remove(&instance_list, this); 01196 if (this->announce_ptr) { 01197 if (this->announce_ptr->timer) { 01198 eventOS_timeout_cancel(this->announce_ptr->timer); 01199 } 01200 ns_dyn_mem_free(this->announce_ptr); 01201 } 01202 if (this->scan_ptr) { 01203 if (this->scan_ptr->timer) { 01204 eventOS_timeout_cancel(this->scan_ptr->timer); 01205 } 01206 if (this->scan_ptr->energy_list_ptr) { 01207 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 01208 } 01209 ns_dyn_mem_free(this->scan_ptr); 01210 } 01211 01212 ns_dyn_mem_free(this); 01213 01214 thread_border_router_delete(interface_id); 01215 thread_bbr_delete(interface_id); 01216 return; 01217 } 01218 01219 int8_t thread_management_server_interface_id_get(int8_t coap_service_id) 01220 { 01221 thread_management_server_t *this = thread_management_find_by_service(coap_service_id); 01222 if (!this) { 01223 return -1; 01224 } 01225 return this->interface_id; 01226 } 01227 01228 #ifdef THREAD_THCI_SUPPORT 01229 static uint8_t Joiner_iid[8]; 01230 #endif 01231 01232 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) 01233 { 01234 thread_management_server_t *this = thread_management_find_by_service(service_id); 01235 (void)source_address; 01236 (void)source_port; 01237 01238 if (response_ptr) { 01239 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)); 01240 } else { 01241 thci_trace("Device - Joiner Router|Direction - recv|IID - %s|Type - JOIN_ent.resp|Payload - NULL", Joiner_iid); 01242 } 01243 tr_debug("Joiner entrust response received"); 01244 if (!this) { 01245 tr_warn("commissioner service missing!"); 01246 return -1; 01247 } 01248 01249 thread_commissioning_if_pairwise_key_del(this->interface_id, &source_address[8]); 01250 01251 return 0; 01252 } 01253 static int thread_management_server_entrust_send(thread_management_server_t *this, uint8_t destination_address[16], uint8_t one_time_key[16]) 01254 { 01255 uint8_t *response_ptr; 01256 uint16_t response_len; 01257 uint8_t *ptr; 01258 link_configuration_s *link_configuration_ptr; 01259 //int ret; 01260 if (!this || !destination_address || !one_time_key) { 01261 tr_err("entrust send fail"); 01262 return -1; 01263 } 01264 01265 tr_debug("Joiner_entrust_send Pairwise key %s address %s", trace_array(one_time_key, 16), trace_ipv6(destination_address)); 01266 01267 link_configuration_ptr = thread_management_configuration_get(this->interface_id); 01268 if (!link_configuration_ptr) { 01269 tr_err("Entrust sending failed no configuration"); 01270 return -2; 01271 } 01272 int ret; 01273 uint8_t options = COAP_REQUEST_OPTIONS_NONE; 01274 ret = thread_commissioning_if_pairwise_key_add(this->interface_id, 10000, &destination_address[8], one_time_key); 01275 01276 if (ret) { 01277 tr_err("Pairwise key set failed"); 01278 return -3; 01279 } 01280 response_len = 6 + thread_joiner_application_active_config_length(this->interface_id, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01281 01282 ptr = response_ptr = ns_dyn_mem_alloc(response_len); 01283 if(!response_ptr) { 01284 tr_warn("Out of mem"); 01285 return -2; 01286 } 01287 ptr = thread_joiner_application_active_config_write(this->interface_id, ptr, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01288 ptr = thread_meshcop_tlv_data_write_uint32(ptr,MESHCOP_TLV_NETWORK_KEY_SEQUENCE, link_configuration_ptr->key_sequence); 01289 01290 thci_trace("joinerrouterJoinerAccepted"); 01291 /*We must null out the master secret*/ 01292 #ifdef THREAD_THCI_SUPPORT 01293 uint8_t *master_secret_ptr; 01294 uint8_t *pskc_ptr; 01295 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_NETWORK_MASTER_KEY, &master_secret_ptr) >= 16) { 01296 memset(master_secret_ptr,0,16); 01297 } 01298 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_PSKC, &pskc_ptr) >= 16) { 01299 memset(pskc_ptr,0,16); 01300 } 01301 01302 memcpy(Joiner_iid, &destination_address[8], 8); 01303 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)); 01304 if (master_secret_ptr) { 01305 memcpy(master_secret_ptr,link_configuration_ptr->master_key,16); 01306 } 01307 if (pskc_ptr) { 01308 memcpy(pskc_ptr,link_configuration_ptr->PSKc,16); 01309 } 01310 #endif 01311 coap_service_request_send(this->coap_service_id, options, destination_address, THREAD_MANAGEMENT_PORT, 01312 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); 01313 ns_dyn_mem_free(response_ptr); 01314 return 0; 01315 } 01316 void joiner_router_recv_commission_msg(void *cb_res) 01317 { 01318 socket_callback_t *sckt_data = 0; 01319 ns_address_t source_address; 01320 uint8_t rloc16[16]; 01321 uint8_t relay_destination_address[16]; 01322 uint8_t *data_ptr = NULL; 01323 uint16_t data_len = 0; 01324 uint8_t *ptr; 01325 uint8_t *payload_ptr; 01326 uint16_t payload_len; 01327 char *destination_uri_ptr = THREAD_URI_RELAY_RECEIVE; 01328 sckt_data = cb_res; 01329 int ret MAYBE_UNUSED = -1; 01330 01331 thread_management_server_t *this = thread_management_find_by_sckt_id(sckt_data->socket_id); 01332 01333 if (!this) { 01334 return; 01335 } 01336 01337 if (0 != thread_management_get_ml16_address(this->interface_id, rloc16)) { 01338 return; 01339 } 01340 // Specification issue needs hack to make one concurrent relay working 01341 if (0 != (ret = thread_commissioning_if_border_router_locator_get(this->interface_id, relay_destination_address))) { 01342 tr_err("invalid commissioner address ret %d", ret); 01343 return; 01344 } 01345 01346 if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) { 01347 data_ptr = ns_dyn_mem_alloc(sckt_data->d_len); 01348 if (!data_ptr) { 01349 tr_err("Out of memory"); 01350 return; 01351 } 01352 data_len = socket_read(sckt_data->socket_id, &source_address, data_ptr, sckt_data->d_len); 01353 } 01354 if (!data_ptr || data_len < 1) { 01355 tr_err("No data received"); 01356 return; 01357 } 01358 01359 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 01360 payload_ptr = ns_dyn_mem_alloc(payload_len); 01361 01362 if (!payload_ptr) { 01363 tr_err("Out of memory"); 01364 ns_dyn_mem_free(data_ptr); 01365 return; 01366 } 01367 tr_debug("Relay TX recvfrom addr: %s, port:%d len:%d", trace_ipv6(source_address.address), source_address.identifier, data_len); 01368 thci_trace("joinerrouterJoinerDataRelayedInbound"); 01369 ptr = payload_ptr; 01370 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr); 01371 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &source_address.address[8]); 01372 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, source_address.identifier); 01373 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, 2, &rloc16[14]); 01374 01375 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, relay_destination_address, THREAD_MANAGEMENT_PORT, 01376 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, destination_uri_ptr, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); 01377 ns_dyn_mem_free(payload_ptr); 01378 ns_dyn_mem_free(data_ptr); 01379 } 01380 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) 01381 { 01382 thread_management_server_t *this = thread_management_find_by_service(service_id); 01383 ns_address_t destination_address = { .address = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; 01384 uint8_t *kek_ptr; 01385 uint8_t *udp_data_ptr; 01386 uint16_t udp_data_len; 01387 uint8_t *iid_ptr; 01388 uint16_t port; 01389 (void)source_address; 01390 (void)source_port; 01391 01392 if (!this) { 01393 return -1; 01394 } 01395 01396 // unwrap message and send to joiner socket. 01397 if (8 > thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &iid_ptr) || 01398 2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &port) || 01399 0 == (udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_data_ptr)) 01400 ) { 01401 tr_err("Relay TX invalid message"); 01402 return -1; 01403 } 01404 memcpy(&destination_address.address[8], iid_ptr, 8); 01405 destination_address.identifier = port; 01406 destination_address.type = ADDRESS_IPV6; 01407 int8_t err = socket_sendto(this->listen_socket_joiner, &destination_address, udp_data_ptr, udp_data_len); 01408 if (err < 0) { 01409 tr_err("Relay TX sendto failed %d", err); 01410 } 01411 01412 //if KEK present set pairwise key to joiner and send entrust method 01413 if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { 01414 // KEK present in relay set pairwise key and send entrust 01415 tr_debug("Kek received"); 01416 thread_management_server_entrust_send(this, destination_address.address, kek_ptr); 01417 } 01418 tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); 01419 thci_trace("joinerrouterJoinerDataRelayedOutbound"); 01420 01421 return -1; // OK no response sent 01422 } 01423 01424 int thread_management_server_joiner_router_init(int8_t interface_id) 01425 { 01426 thread_management_server_t *this = thread_management_server_find(interface_id); 01427 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01428 int8_t securityLinkLayer = 0; 01429 bool enable = false; 01430 01431 if (!this || !cur) { 01432 return -1; 01433 } 01434 01435 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01436 // Thread 1.1 commissioner is present 01437 enable = true; 01438 } 01439 if(this->joiner_router_enabled == enable && 01440 this->relay_port_joiner == thread_joiner_port) { 01441 // Joiner router is in correct state 01442 return 0; 01443 } 01444 if(this->joiner_router_enabled) { 01445 // Need to disable Joiner router either because port changed or moving to disabled 01446 thread_management_server_joiner_router_deinit(interface_id); 01447 } 01448 if (!enable) { 01449 // Joiner router should be disabled 01450 tr_info("Joiner router Disable joining"); 01451 return 0; 01452 } 01453 01454 tr_info("Joiner router Enable joining"); 01455 01456 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01457 // Thread 1.1 commissioner is present 01458 this->relay_port_joiner = thread_joiner_port; 01459 01460 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01461 if (this->listen_socket_joiner < 0) { 01462 // Try other ports 01463 while((this->listen_socket_joiner < 0) && (this->relay_port_joiner < thread_joiner_port + 10)) { 01464 // We try 10 ports after default port 01465 this->relay_port_joiner++; 01466 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01467 } 01468 } 01469 if (this->listen_socket_joiner < 0) { 01470 this->joiner_router_enabled = false; 01471 this->relay_port_joiner = 0; 01472 tr_error("Joiner router init failed"); 01473 return -2; 01474 } 01475 socket_setsockopt(this->listen_socket_joiner, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); 01476 tr_debug("init joiner router port:%d", this->relay_port_joiner); 01477 } 01478 01479 coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_relay_tx_cb); 01480 this->joiner_router_enabled = true; 01481 return 0; 01482 } 01483 01484 void thread_management_server_joiner_router_deinit(int8_t interface_id) 01485 { 01486 thread_management_server_t *this = thread_management_server_find(interface_id); 01487 01488 if (!this) { 01489 return; 01490 } 01491 01492 tr_debug("deinit joiner router"); 01493 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT); 01494 socket_close(this->listen_socket_joiner); 01495 this->listen_socket_joiner = -1; 01496 this->relay_port_joiner = 0; 01497 this->joiner_router_enabled = false; 01498 return; 01499 } 01500 01501 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 01502 { 01503 thread_management_server_t *this = thread_management_server_find(interface_id); 01504 01505 if (!this) { 01506 return -1; 01507 } 01508 01509 server_data->joiner_router_enabled = this->joiner_router_enabled; 01510 server_data->joiner_router_port = this->relay_port_joiner; 01511 server_data->commissioner_port = this->external_commissioner_port; 01512 return 0; 01513 } 01514 01515 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 01516 { 01517 link_configuration_s *linkConfiguration; 01518 linkConfiguration = thread_joiner_application_get_config(interface_id); 01519 01520 if (!linkConfiguration) { 01521 tr_error("No link configuration."); 01522 return false; 01523 } 01524 01525 if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 && 01526 memcmp(source_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0 ) { 01527 // Source address is RLOC or ALOC 01528 } else if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0) { 01529 // Source address is ML64 TODO this should check that destination address is ALOC or RLOC CoaP Service does not support 01530 } else if (memcmp(ADDR_LINK_LOCAL_PREFIX, source_address, 8)) { 01531 // Source address is from Link local address 01532 } else { 01533 tr_error("Message out of thread network; ML prefix: %s, src addr: %s", 01534 trace_ipv6_prefix(linkConfiguration->mesh_local_ula_prefix, 64), 01535 trace_ipv6(source_address)); 01536 return false; 01537 } 01538 // TODO: Add other (security) related checks here 01539 01540 return true; 01541 } 01542 01543 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 01544 { 01545 int ret_val = -1; 01546 01547 if (strncmp(THREAD_URI_ACTIVE_GET, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 01548 ret_val = thread_management_server_active_get_respond(interface_id, coap_service_id, request_ptr); 01549 } else if (strncmp(THREAD_URI_PENDING_GET,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len) == 0) { 01550 ret_val = thread_management_server_pending_get_respond(interface_id, coap_service_id, request_ptr); 01551 } else if (strncmp(THREAD_URI_MANAGEMENT_GET,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len) == 0) { 01552 ret_val = thread_management_server_management_get_respond(interface_id, coap_service_id, request_ptr); 01553 } else { 01554 // unrecognized message 01555 tr_warn("Unrecognized tmf msg"); 01556 } 01557 01558 return ret_val; 01559 } 01560 01561 #else // HAVE_THREAD 01562 01563 int thread_management_server_init(int8_t interface_id) 01564 { 01565 (void) interface_id; 01566 return 0; 01567 } 01568 01569 void thread_management_server_delete(int8_t interface_id) 01570 { 01571 (void) interface_id; 01572 } 01573 01574 int thread_management_server_joiner_router_init(int8_t interface_id) 01575 { 01576 (void)interface_id; 01577 return 0; 01578 } 01579 01580 void thread_management_server_joiner_router_deinit(int8_t interface_id) 01581 { 01582 (void) interface_id; 01583 } 01584 01585 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 01586 { 01587 (void) interface_id; 01588 (void) server_data; 01589 return -1; 01590 } 01591 01592 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 01593 { 01594 (void)interface_id; 01595 (void)source_address; 01596 return false; 01597 } 01598 01599 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 01600 { 01601 (void)interface_id; 01602 (void)coap_service_id; 01603 (void)request_ptr; 01604 return -1; 01605 } 01606 #endif //HAVE_THREAD
Generated on Tue Jul 12 2022 12:45:59 by
