Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_management_server.c Source File

thread_management_server.c

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