Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
thread_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_ROUTER 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 response_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00861 goto error_exit; 00862 } 00863 00864 this->scan_ptr->coap_service_id = service_id; 00865 memcpy(this->scan_ptr->channel_mask,mask_ptr,mask_len); 00866 this->scan_ptr->channel_mask_len = mask_len; 00867 this->scan_ptr->port = source_port; 00868 memcpy(this->scan_ptr->address,source_address,16); 00869 this->scan_ptr->panid = panid; 00870 this->scan_ptr->panid_scan = true; 00871 00872 if (request_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ){ 00873 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); 00874 return 0; 00875 } 00876 return -1; 00877 error_exit: 00878 this->scan_ptr = NULL; 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 if (thread_border_router_init(this->interface_id) != 0) { 01138 ns_dyn_mem_free(this); 01139 return -5; 01140 } 01141 01142 if (thread_bbr_init(this->interface_id, this->external_commissioner_port) != 0) { 01143 ns_dyn_mem_free(this); 01144 return -5; 01145 } 01146 01147 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 01148 if (this->coap_service_id < 0) { 01149 tr_warn("Thread management init failed"); 01150 ns_dyn_mem_free(this); 01151 return -3; 01152 } 01153 01154 if (thread_leader_service_init(interface_id, this->coap_service_id) != 0) { 01155 tr_warn("Thread leader service init failed"); 01156 ns_dyn_mem_free(this); 01157 return -3; 01158 } 01159 thread_extension_init(interface_id, this->coap_service_id); 01160 01161 // All thread devices 01162 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01163 01164 // Full functioning devices(Router,reed,fed) 01165 coap_service_register_uri(this->coap_service_id, THREAD_URI_ACTIVE_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01166 coap_service_register_uri(this->coap_service_id, THREAD_URI_PENDING_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_get_command_cb); 01167 coap_service_register_uri(this->coap_service_id, THREAD_URI_COMMISSIONER_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_management_server_commissioner_get_cb); 01168 01169 coap_service_register_uri(this->coap_service_id, THREAD_URI_PANID_QUERY, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_panid_query_cb); 01170 coap_service_register_uri(this->coap_service_id, THREAD_URI_ED_SCAN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_energy_scan_cb); 01171 coap_service_register_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_ANNOUNCE_BEGIN, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_announce_begin_cb); 01172 01173 ns_list_add_to_start(&instance_list, this); 01174 return 0; 01175 } 01176 01177 void thread_management_server_delete(int8_t interface_id) 01178 { 01179 thread_management_server_t *this = thread_management_server_find(interface_id); 01180 if (!this) { 01181 return; 01182 } 01183 01184 thread_leader_service_delete(interface_id); 01185 01186 if (this->joiner_router_enabled) { 01187 thread_management_server_joiner_router_deinit(interface_id); 01188 } 01189 //TODO move uri deletion to delete 01190 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_GET); 01191 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_MANAGEMENT_SET); 01192 coap_service_delete(this->coap_service_id); 01193 ns_list_remove(&instance_list, this); 01194 if (this->announce_ptr) { 01195 if (this->announce_ptr->timer) { 01196 eventOS_timeout_cancel(this->announce_ptr->timer); 01197 } 01198 ns_dyn_mem_free(this->announce_ptr); 01199 } 01200 if (this->scan_ptr) { 01201 if (this->scan_ptr->timer) { 01202 eventOS_timeout_cancel(this->scan_ptr->timer); 01203 } 01204 if (this->scan_ptr->energy_list_ptr) { 01205 ns_dyn_mem_free(this->scan_ptr->energy_list_ptr); 01206 } 01207 ns_dyn_mem_free(this->scan_ptr); 01208 } 01209 01210 ns_dyn_mem_free(this); 01211 01212 thread_border_router_delete(interface_id); 01213 thread_bbr_delete(interface_id); 01214 return; 01215 } 01216 01217 int8_t thread_management_server_interface_id_get(int8_t coap_service_id) 01218 { 01219 thread_management_server_t *this = thread_management_find_by_service(coap_service_id); 01220 if (!this) { 01221 return -1; 01222 } 01223 return this->interface_id; 01224 } 01225 01226 #ifdef THREAD_THCI_SUPPORT 01227 static uint8_t Joiner_iid[8]; 01228 #endif 01229 01230 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) 01231 { 01232 thread_management_server_t *this = thread_management_find_by_service(service_id); 01233 (void)source_address; 01234 (void)source_port; 01235 01236 if (response_ptr) { 01237 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)); 01238 } else { 01239 thci_trace("Device - Joiner Router|Direction - recv|IID - %s|Type - JOIN_ent.resp|Payload - NULL", Joiner_iid); 01240 } 01241 tr_debug("Joiner entrust response received"); 01242 if (!this) { 01243 tr_warn("commissioner service missing!"); 01244 return -1; 01245 } 01246 01247 thread_commissioning_if_pairwise_key_del(this->interface_id, &source_address[8]); 01248 01249 return 0; 01250 } 01251 static int thread_management_server_entrust_send(thread_management_server_t *this, uint8_t destination_address[16], uint8_t one_time_key[16]) 01252 { 01253 uint8_t *response_ptr; 01254 uint16_t response_len; 01255 uint8_t *ptr; 01256 link_configuration_s *link_configuration_ptr; 01257 //int ret; 01258 if (!this || !destination_address || !one_time_key) { 01259 tr_err("entrust send fail"); 01260 return -1; 01261 } 01262 01263 tr_debug("Joiner_entrust_send Pairwise key %s address %s", trace_array(one_time_key, 16), trace_ipv6(destination_address)); 01264 01265 link_configuration_ptr = thread_management_configuration_get(this->interface_id); 01266 if (!link_configuration_ptr) { 01267 tr_err("Entrust sending failed no configuration"); 01268 return -2; 01269 } 01270 int ret; 01271 uint8_t options = COAP_REQUEST_OPTIONS_NONE; 01272 ret = thread_commissioning_if_pairwise_key_add(this->interface_id, 10000, &destination_address[8], one_time_key); 01273 01274 if (ret) { 01275 tr_err("Pairwise key set failed"); 01276 return -3; 01277 } 01278 response_len = 6 + thread_joiner_application_active_config_length(this->interface_id, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01279 01280 ptr = response_ptr = ns_dyn_mem_alloc(response_len); 01281 if(!response_ptr) { 01282 tr_warn("Out of mem"); 01283 return -2; 01284 } 01285 ptr = thread_joiner_application_active_config_write(this->interface_id, ptr, entrust_dataset_tlvs, entrust_dataset_tlvs_size(), NULL, 0); 01286 ptr = thread_meshcop_tlv_data_write_uint32(ptr,MESHCOP_TLV_NETWORK_KEY_SEQUENCE, link_configuration_ptr->key_sequence); 01287 01288 thci_trace("joinerrouterJoinerAccepted"); 01289 /*We must null out the master secret*/ 01290 #ifdef THREAD_THCI_SUPPORT 01291 uint8_t *master_secret_ptr; 01292 uint8_t *pskc_ptr; 01293 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_NETWORK_MASTER_KEY, &master_secret_ptr) >= 16) { 01294 memset(master_secret_ptr,0,16); 01295 } 01296 if (thread_meshcop_tlv_find(response_ptr, ptr - response_ptr, MESHCOP_TLV_PSKC, &pskc_ptr) >= 16) { 01297 memset(pskc_ptr,0,16); 01298 } 01299 01300 memcpy(Joiner_iid, &destination_address[8], 8); 01301 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)); 01302 if (master_secret_ptr) { 01303 memcpy(master_secret_ptr,link_configuration_ptr->master_key,16); 01304 } 01305 if (pskc_ptr) { 01306 memcpy(pskc_ptr,link_configuration_ptr->PSKc,16); 01307 } 01308 #endif 01309 coap_service_request_send(this->coap_service_id, options, destination_address, THREAD_MANAGEMENT_PORT, 01310 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); 01311 ns_dyn_mem_free(response_ptr); 01312 return 0; 01313 } 01314 void joiner_router_recv_commission_msg(void *cb_res) 01315 { 01316 socket_callback_t *sckt_data = 0; 01317 ns_address_t source_address; 01318 uint8_t rloc16[16]; 01319 uint8_t relay_destination_address[16]; 01320 uint8_t *data_ptr = NULL; 01321 uint16_t data_len = 0; 01322 uint8_t *ptr; 01323 uint8_t *payload_ptr; 01324 uint16_t payload_len; 01325 char *destination_uri_ptr = THREAD_URI_RELAY_RECEIVE; 01326 sckt_data = cb_res; 01327 int ret MAYBE_UNUSED = -1; 01328 01329 thread_management_server_t *this = thread_management_find_by_sckt_id(sckt_data->socket_id); 01330 01331 if (!this) { 01332 return; 01333 } 01334 01335 if (0 != thread_management_get_ml16_address(this->interface_id, rloc16)) { 01336 return; 01337 } 01338 // Specification issue needs hack to make one concurrent relay working 01339 if (0 != (ret = thread_commissioning_if_border_router_locator_get(this->interface_id, relay_destination_address))) { 01340 tr_err("invalid commissioner address ret %d", ret); 01341 return; 01342 } 01343 01344 if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) { 01345 data_ptr = ns_dyn_mem_alloc(sckt_data->d_len); 01346 if (!data_ptr) { 01347 tr_err("Out of memory"); 01348 return; 01349 } 01350 data_len = socket_read(sckt_data->socket_id, &source_address, data_ptr, sckt_data->d_len); 01351 } 01352 if (!data_ptr || data_len < 1) { 01353 tr_err("No data received"); 01354 return; 01355 } 01356 01357 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 01358 payload_ptr = ns_dyn_mem_alloc(payload_len); 01359 01360 if (!payload_ptr) { 01361 tr_err("Out of memory"); 01362 ns_dyn_mem_free(data_ptr); 01363 return; 01364 } 01365 tr_debug("Relay TX recvfrom addr: %s, port:%d len:%d", trace_ipv6(source_address.address), source_address.identifier, data_len); 01366 thci_trace("joinerrouterJoinerDataRelayedInbound"); 01367 ptr = payload_ptr; 01368 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr); 01369 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &source_address.address[8]); 01370 ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, source_address.identifier); 01371 ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, 2, &rloc16[14]); 01372 01373 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, relay_destination_address, THREAD_MANAGEMENT_PORT, 01374 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, destination_uri_ptr, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL); 01375 ns_dyn_mem_free(payload_ptr); 01376 ns_dyn_mem_free(data_ptr); 01377 } 01378 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) 01379 { 01380 thread_management_server_t *this = thread_management_find_by_service(service_id); 01381 ns_address_t destination_address = { .address = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; 01382 uint8_t *kek_ptr; 01383 uint8_t *udp_data_ptr; 01384 uint16_t udp_data_len; 01385 uint8_t *iid_ptr; 01386 uint16_t port; 01387 (void)source_address; 01388 (void)source_port; 01389 01390 if (!this) { 01391 return -1; 01392 } 01393 01394 // unwrap message and send to joiner socket. 01395 if (8 > thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &iid_ptr) || 01396 2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &port) || 01397 0 == (udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_data_ptr)) 01398 ) { 01399 tr_err("Relay TX invalid message"); 01400 return -1; 01401 } 01402 memcpy(&destination_address.address[8], iid_ptr, 8); 01403 destination_address.identifier = port; 01404 destination_address.type = ADDRESS_IPV6; 01405 int8_t err = socket_sendto(this->listen_socket_joiner, &destination_address, udp_data_ptr, udp_data_len); 01406 if (err < 0) { 01407 tr_err("Relay TX sendto failed %d", err); 01408 } 01409 01410 //if KEK present set pairwise key to joiner and send entrust method 01411 if (0 < thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_KEK, &kek_ptr)) { 01412 // KEK present in relay set pairwise key and send entrust 01413 tr_debug("Kek received"); 01414 thread_management_server_entrust_send(this, destination_address.address, kek_ptr); 01415 } 01416 tr_debug("Relay TX sendto addr:%s port:%d, length:%d", trace_ipv6(destination_address.address), port, udp_data_len); 01417 thci_trace("joinerrouterJoinerDataRelayedOutbound"); 01418 01419 return -1; // OK no response sent 01420 } 01421 01422 int thread_management_server_joiner_router_init(int8_t interface_id) 01423 { 01424 thread_management_server_t *this = thread_management_server_find(interface_id); 01425 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 01426 int8_t securityLinkLayer = 0; 01427 bool enable = false; 01428 01429 if (!this || !cur) { 01430 return -1; 01431 } 01432 01433 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01434 // Thread 1.1 commissioner is present 01435 enable = true; 01436 } 01437 if(this->joiner_router_enabled == enable && 01438 this->relay_port_joiner == thread_joiner_port) { 01439 // Joiner router is in correct state 01440 return 0; 01441 } 01442 if(this->joiner_router_enabled) { 01443 // Need to disable Joiner router either because port changed or moving to disabled 01444 thread_management_server_joiner_router_deinit(interface_id); 01445 } 01446 if (!enable) { 01447 // Joiner router should be disabled 01448 tr_info("Joiner router Disable joining"); 01449 return 0; 01450 } 01451 01452 tr_info("Joiner router Enable joining"); 01453 01454 if (cur->thread_info->registered_commissioner.commissioner_valid && cur->thread_info->registered_commissioner.steering_data_len > 0) { 01455 // Thread 1.1 commissioner is present 01456 this->relay_port_joiner = thread_joiner_port; 01457 01458 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01459 if (this->listen_socket_joiner < 0) { 01460 // Try other ports 01461 while((this->listen_socket_joiner < 0) && (this->relay_port_joiner < thread_joiner_port + 10)) { 01462 // We try 10 ports after default port 01463 this->relay_port_joiner++; 01464 this->listen_socket_joiner = socket_open(SOCKET_UDP, this->relay_port_joiner, joiner_router_recv_commission_msg); 01465 } 01466 } 01467 if (this->listen_socket_joiner < 0) { 01468 this->joiner_router_enabled = false; 01469 this->relay_port_joiner = 0; 01470 tr_error("Joiner router init failed"); 01471 return -2; 01472 } 01473 socket_setsockopt(this->listen_socket_joiner, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t)); 01474 tr_debug("init joiner router port:%d", this->relay_port_joiner); 01475 } 01476 01477 coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_management_server_relay_tx_cb); 01478 this->joiner_router_enabled = true; 01479 return 0; 01480 } 01481 01482 void thread_management_server_joiner_router_deinit(int8_t interface_id) 01483 { 01484 thread_management_server_t *this = thread_management_server_find(interface_id); 01485 01486 if (!this) { 01487 return; 01488 } 01489 01490 tr_debug("deinit joiner router"); 01491 coap_service_unregister_uri(this->coap_service_id, THREAD_URI_RELAY_TRANSMIT); 01492 socket_close(this->listen_socket_joiner); 01493 this->listen_socket_joiner = -1; 01494 this->relay_port_joiner = 0; 01495 this->joiner_router_enabled = false; 01496 return; 01497 } 01498 01499 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 01500 { 01501 thread_management_server_t *this = thread_management_server_find(interface_id); 01502 01503 if (!this) { 01504 return -1; 01505 } 01506 01507 server_data->joiner_router_enabled = this->joiner_router_enabled; 01508 server_data->joiner_router_port = this->relay_port_joiner; 01509 server_data->commissioner_port = this->external_commissioner_port; 01510 return 0; 01511 } 01512 01513 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 01514 { 01515 link_configuration_s *linkConfiguration; 01516 linkConfiguration = thread_joiner_application_get_config(interface_id); 01517 01518 if (!linkConfiguration) { 01519 tr_error("No link configuration."); 01520 return false; 01521 } 01522 01523 if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0 && 01524 memcmp(source_address + 8, ADDR_SHORT_ADR_SUFFIC, 6) == 0 ) { 01525 // Source address is RLOC or ALOC 01526 } else if (memcmp(source_address, linkConfiguration->mesh_local_ula_prefix, 8) == 0) { 01527 // Source address is ML64 TODO this should check that destination address is ALOC or RLOC CoaP Service does not support 01528 } else if (memcmp(ADDR_LINK_LOCAL_PREFIX, source_address, 8)) { 01529 // Source address is from Link local address 01530 } else { 01531 tr_error("Message out of thread network; ML prefix: %s, src addr: %s", 01532 trace_ipv6_prefix(linkConfiguration->mesh_local_ula_prefix, 64), 01533 trace_ipv6(source_address)); 01534 return false; 01535 } 01536 // TODO: Add other (security) related checks here 01537 01538 return true; 01539 } 01540 01541 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 01542 { 01543 int ret_val = -1; 01544 01545 if (strncmp(THREAD_URI_ACTIVE_GET, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) { 01546 ret_val = thread_management_server_active_get_respond(interface_id, coap_service_id, request_ptr); 01547 } else if (strncmp(THREAD_URI_PENDING_GET,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len) == 0) { 01548 ret_val = thread_management_server_pending_get_respond(interface_id, coap_service_id, request_ptr); 01549 } else if (strncmp(THREAD_URI_MANAGEMENT_GET,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len) == 0) { 01550 ret_val = thread_management_server_management_get_respond(interface_id, coap_service_id, request_ptr); 01551 } else { 01552 // unrecognized message 01553 tr_warn("Unrecognized tmf msg"); 01554 } 01555 01556 return ret_val; 01557 } 01558 01559 #else // HAVE_THREAD_ROUTER 01560 01561 int thread_management_server_init(int8_t interface_id) 01562 { 01563 (void) interface_id; 01564 return 0; 01565 } 01566 01567 void thread_management_server_delete(int8_t interface_id) 01568 { 01569 (void) interface_id; 01570 } 01571 01572 int thread_management_server_joiner_router_init(int8_t interface_id) 01573 { 01574 (void)interface_id; 01575 return 0; 01576 } 01577 01578 void thread_management_server_joiner_router_deinit(int8_t interface_id) 01579 { 01580 (void) interface_id; 01581 } 01582 01583 int thread_management_server_commisoner_data_get(int8_t interface_id, thread_management_server_data_t *server_data) 01584 { 01585 (void) interface_id; 01586 (void) server_data; 01587 return -1; 01588 } 01589 01590 bool thread_management_server_source_address_check(int8_t interface_id, uint8_t source_address[16]) 01591 { 01592 (void)interface_id; 01593 (void)source_address; 01594 return false; 01595 } 01596 01597 int thread_management_server_tmf_get_request_handler(int8_t interface_id, int8_t coap_service_id, struct sn_coap_hdr_ *request_ptr) 01598 { 01599 (void)interface_id; 01600 (void)coap_service_id; 01601 (void)request_ptr; 01602 return -1; 01603 } 01604 #endif //HAVE_THREAD_ROUTER
Generated on Tue Jul 12 2022 13:03:20 by
