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