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_commissioning_api.c Source File

thread_commissioning_api.c

00001 /*
00002  * Copyright (c) 2015-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 /*Nanostack includes*/
00031 #include "nsconfig.h"
00032 
00033 #include <string.h>
00034 #include "ns_types.h"
00035 #include "ns_list.h"
00036 #include "ns_trace.h"
00037 #include "nsdynmemLIB.h"
00038 #include "randLIB.h"
00039 #include "common_functions.h"
00040 #include "ns_sha256.h"
00041 
00042 /*thread includes*/
00043 #include "thread_config.h"
00044 #include "thread_management_if.h"
00045 #include "thread_meshcop_lib.h"
00046 #include "thread_management_api.h"
00047 #include "thread_commissioning_api.h"
00048 #include "thread_beacon.h"
00049 /*Private includes*/
00050 #include "6LoWPAN/Thread/thread_common.h"
00051 #include "6LoWPAN/Thread/thread_management_internal.h"
00052 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"// Get coordinator address
00053 
00054 #define TRACE_GROUP TRACE_GROUP_THREAD_COMMISSIONING_API
00055 #ifdef HAVE_THREAD
00056 
00057 #include "coap_service_api.h"
00058 
00059 typedef struct device {
00060     uint8_t PSKd[32];
00061     uint8_t kek[32];// shal libs needs 32 bytes kek is first 16
00062     uint8_t EUI64[8];
00063     uint8_t IID[8];
00064     thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr;
00065     uint16_t joiner_router_rloc;
00066     uint8_t PSKd_len;
00067     bool send_kek: 1;
00068     bool short_eui64: 1;/*< Use short format for bloom filter creation*/
00069 
00070     ns_list_link_t link;
00071 } device_t;
00072 
00073 typedef NS_LIST_HEAD (device_t, link) device_list_t;
00074 
00075 typedef struct commissioner_entry {
00076     device_list_t device_list;
00077     uint8_t destination_address[16];
00078     uint8_t final_dest_address[16]; // Relay message final destination
00079     uint8_t leader_address[16]; // leader ALOC for contacting the leader
00080     uint8_t PSKc_ptr[16];
00081     thread_commissioning_status_cb *status_cb_ptr;
00082     uint16_t destination_port;
00083     uint16_t session_id;
00084     int8_t management_instance;
00085     int8_t interface_id;
00086     int8_t coap_service_id;
00087     int8_t coap_secure_service_id;
00088     int8_t coap_secure_virtual_service_id;
00089     int8_t coap_udp_proxy_service_id;
00090     bool registered: 1;
00091     bool native_commissioner: 1;
00092 
00093     ns_list_link_t link;
00094 } commissioner_t;
00095 
00096 static NS_LIST_DEFINE(instance_list, commissioner_t, link);
00097 
00098 const uint8_t any_device[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
00099 
00100 /*
00101  * Commissioned device handlers;
00102  */
00103 static device_t *device_create(commissioner_t *commissioner_ptr)
00104 {
00105     device_t *device_ptr = ns_dyn_mem_alloc(sizeof(device_t));
00106     if (device_ptr) {
00107         memset(device_ptr, 0, sizeof(device_t));
00108         device_ptr->send_kek = false;
00109         device_ptr->joining_device_cb_ptr = NULL;
00110         ns_list_add_to_start(&commissioner_ptr->device_list, device_ptr);
00111     }
00112     return device_ptr;
00113 }
00114 
00115 static void device_delete(commissioner_t *commissioner_ptr, device_t *device_ptr)
00116 {
00117     if (device_ptr) {
00118         ns_list_remove(&commissioner_ptr->device_list, device_ptr);
00119         ns_dyn_mem_free(device_ptr);
00120     }
00121     return;
00122 }
00123 
00124 static device_t *device_find(commissioner_t *commissioner_ptr, uint8_t EUI64[8])
00125 {
00126     device_t *this = NULL;
00127     if (!commissioner_ptr || !EUI64) {
00128         return NULL;
00129     }
00130 
00131     ns_list_foreach(device_t, cur_ptr, &commissioner_ptr->device_list) {
00132         if (memcmp(cur_ptr->EUI64, EUI64, 8) == 0) {
00133             this = cur_ptr;
00134             break;
00135         }
00136     }
00137     return this;
00138 }
00139 
00140 static device_t *device_find_by_iid(commissioner_t *commissioner_ptr, uint8_t IID[8])
00141 {
00142     device_t *this = NULL;
00143     if (!IID) {
00144         return NULL;
00145     }
00146     ns_list_foreach(device_t, cur_ptr, &commissioner_ptr->device_list) {
00147         tr_debug("device iid %s and commissioner iid %s", trace_array(cur_ptr->IID, 8), trace_array(IID, 8));
00148         if (memcmp(cur_ptr->IID, IID, 8) == 0) {
00149             this = cur_ptr;
00150             break;
00151         }
00152     }
00153     return this;
00154 }
00155 #define device_get_first(commissioner) ns_list_get_first(&commissioner->device_list)
00156 
00157 
00158 /* Commissioner class handlers*/
00159 static commissioner_t *commissioner_find(int8_t interface_id)
00160 {
00161     commissioner_t *this = NULL;
00162     ns_list_foreach(commissioner_t, cur_ptr, &instance_list) {
00163         if (cur_ptr->interface_id == interface_id) {
00164             this = cur_ptr;
00165             break;
00166         }
00167     }
00168     return this;
00169 }
00170 static commissioner_t *commissioner_find_by_service(int8_t service_id)
00171 {
00172     commissioner_t *this = NULL;
00173     ns_list_foreach(commissioner_t, cur_ptr, &instance_list) {
00174         if (cur_ptr->coap_service_id == service_id || cur_ptr->coap_secure_virtual_service_id == service_id || cur_ptr->coap_secure_service_id == service_id || cur_ptr->coap_udp_proxy_service_id == service_id) {
00175             this = cur_ptr;
00176             break;
00177         }
00178     }
00179     return this;
00180 }
00181 static commissioner_t *commissioner_create(int8_t interface_id)
00182 {
00183     commissioner_t *this = ns_dyn_mem_alloc(sizeof(commissioner_t));
00184     if (this) {
00185         memset(this, 0, sizeof(commissioner_t));
00186         this->interface_id = interface_id;
00187         this->registered = false;
00188         ns_list_init(&this->device_list);
00189         ns_list_add_to_start(&instance_list, this);
00190     }
00191     return this;
00192 }
00193 
00194 static void commissioner_delete(commissioner_t *this)
00195 {
00196     if (this) {
00197         device_t *device_ptr = device_get_first(this);
00198         while (device_ptr != NULL) {
00199             device_delete(this, device_ptr);
00200             device_ptr = device_get_first(this);
00201         }
00202         ns_list_remove(&instance_list, this);
00203         ns_dyn_mem_free(this);
00204     }
00205     return;
00206 }
00207 
00208 /*Internal helper functions*/
00209 static int commissioning_meshcop_map_state(commissioning_state_e state)
00210 {
00211     if (state == COMMISSIONING_STATE_ACCEPT) {
00212         return 1;
00213     } else if (state == COMMISSIONING_STATE_PENDING) {
00214         return 0;
00215     }
00216 
00217     return -1;
00218 }
00219 
00220 
00221 static int commission_finalisation_resp_send(int8_t coap_service_id, device_t *device_ptr, sn_coap_hdr_s *request_ptr, commissioning_state_e state)
00222 {
00223     commissioner_t *this = commissioner_find_by_service(coap_service_id);
00224     uint8_t payload[11];// 4 + 1 + 4 + 2
00225     uint8_t *ptr;
00226 
00227     if (!this || !request_ptr || !device_ptr) {
00228         return -1;
00229     }
00230 
00231     ptr = payload;
00232     ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, (uint8_t)commissioning_meshcop_map_state(state));
00233 
00234     thci_trace("Device - Comm|Direction - sent|EUI - %s|Type - JOIN_FIN.resp|Length - %d|Payload - %s", trace_array(device_ptr->EUI64, 8), (int)(ptr - payload), trace_array(payload, ptr - payload));
00235     tr_debug("finalisation response send state:%d value:%d ", state, (uint8_t)commissioning_meshcop_map_state(state));
00236     coap_service_response_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload);
00237     return 0;
00238 }
00239 
00240 /*
00241  * Callback functions
00242 */
00243 
00244 static int thread_commissioning_active_get_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
00245 {
00246     commissioner_t *this = commissioner_find_by_service(service_id);
00247     commissioning_state_e state = COMMISSIONING_STATE_REJECT;// Default is accept if we get error it is rejected
00248     uint8_t *ptr;
00249     uint16_t len;
00250     (void) source_address;
00251     (void) source_port;
00252 
00253     /* Transaction failed */
00254     if (!response_ptr) {
00255         return -1;
00256     }
00257 
00258     tr_debug("management get response from comm module");
00259     if (!this) {
00260         return -2;
00261     }
00262 
00263     if ((len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_NETWORK_MESH_LOCAL_ULA, &ptr)) > 0) {
00264         state = COMMISSIONING_STATE_ACCEPT;
00265         tr_debug(" TLV ml prefix=%s\r\n", trace_array(ptr, len));
00266         memcpy(this->leader_address, ptr, 8);
00267         memcpy(this->leader_address + 8, ADDR_SHORT_ADR_SUFFIC, 6);
00268         common_write_16_bit(0xfc00, this->leader_address + 14);
00269     }
00270 
00271     if (this->status_cb_ptr) {
00272         this->status_cb_ptr(this->interface_id, this->session_id, state);
00273     }
00274     return 0;
00275 }
00276 
00277 static int commissioning_leader_petition_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
00278 {
00279     commissioner_t *this = commissioner_find_by_service(service_id);
00280     commissioning_state_e state = COMMISSIONING_STATE_REJECT;
00281     uint16_t session_id = 0;
00282     uint8_t *ptr = NULL;
00283     char *uri_ptr = THREAD_URI_ACTIVE_GET;
00284     (void) source_address;
00285     (void) source_port;
00286 
00287     tr_debug("Thread Petition response received service %d", service_id);
00288     if (!this) {
00289         return -1;
00290     }
00291 
00292     if (!response_ptr || !response_ptr->payload_ptr || response_ptr->payload_len < 1) {
00293         tr_debug("invalid response");
00294         thci_trace("commissionerPetitionError");
00295         goto user_response;
00296     }
00297 
00298     if ((2 <= thread_meshcop_tlv_data_get_uint16(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_COMMISSIONER_SESSION_ID, &session_id)) &&
00299             (1 <= thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &ptr) && *ptr == 1)) {
00300         state = COMMISSIONING_STATE_ACCEPT;
00301         thci_trace("commissionerPetitionAccepted");
00302         this->session_id = session_id;
00303         this->registered = true;
00304         //@TODO order keep alive timer for the message and start sending it periodically
00305     }
00306     tr_debug("petition response session_id: %d state:%d", session_id, state);
00307 
00308     // if registered and native commissioner send ACTIVE_GET to BBR to get mesh parameters
00309     // if not native set leader ALOC from stack
00310     if (this->native_commissioner) {
00311         coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00312                                   COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb);
00313         return 0;
00314     } else {
00315         thread_management_get_leader_aloc(this->interface_id, this->leader_address);
00316     }
00317 
00318 user_response:
00319     if (state == COMMISSIONING_STATE_REJECT) {
00320         thci_trace("commissionerPetitionRejected");
00321     }
00322     if (this->status_cb_ptr) {
00323         this->status_cb_ptr(this->interface_id, this->session_id, state);
00324     }
00325     return 0;
00326 }
00327 
00328 static int commissioning_keep_alive_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
00329 {
00330     commissioner_t *this = commissioner_find_by_service(service_id);
00331     uint8_t *ptr;
00332     (void) source_address;
00333     (void) source_port;
00334 
00335     tr_debug("Thread keep alive response received");
00336     if (!this) {
00337         tr_warn("commissioner service missing!");
00338         thci_trace("commissionerError");
00339         return -1;
00340     }
00341     if (!response_ptr) {
00342         tr_warn("commission ka response without ptr!");
00343         thci_trace("commissionerError");
00344         return -1;
00345     }
00346 
00347     if (1 <= thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &ptr) && *ptr == 1) {
00348         // only handle success
00349         return 0;
00350     }
00351 
00352     this->session_id = 0;
00353     this->registered = false;
00354     if (this->status_cb_ptr) {
00355         this->status_cb_ptr(this->interface_id, this->session_id, COMMISSIONING_STATE_REJECT);
00356     }
00357 
00358     return -2;
00359 }
00360 
00361 static int commission_finalisation_req_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00362 {
00363     commissioner_t *this = commissioner_find_by_service(service_id);
00364     uint8_t address[16];
00365     device_t *device_ptr;
00366     int ret = -1;// always reject
00367     (void) source_port;
00368 
00369     tr_debug("joiner finalisation recv addr %s", trace_ipv6(source_address));
00370     if (!this || !source_address || !request_ptr) {
00371         return -1;
00372     }
00373 
00374     device_ptr = device_find_by_iid(this, &source_address[8]);
00375     if (device_ptr) {
00376         ret = 0;    // accept even without application confirmation
00377     }
00378     thci_trace("Device - Comm|Direction - recv|EUI - %s|Type - JOIN_FIN.req|Length - %d|Payload - %s", trace_array(device_ptr->EUI64, 8), request_ptr->payload_len, trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00379     memcpy(address, source_address, 16);
00380 
00381     if (device_ptr) {
00382         if (device_ptr->joining_device_cb_ptr) {
00383             ret = device_ptr->joining_device_cb_ptr(this->interface_id, &source_address[8], request_ptr->payload_ptr, request_ptr->payload_len);
00384         }
00385 
00386         device_ptr->send_kek = true;
00387     }
00388 
00389     if (ret == 0) {
00390         thci_trace("commissionerJoinerAccepted");
00391     }
00392 
00393     commission_finalisation_resp_send(service_id, device_ptr, request_ptr, ret == 0 ? COMMISSIONING_STATE_ACCEPT : COMMISSIONING_STATE_REJECT);
00394     coap_service_close_secure_connection(service_id, address, source_port);
00395 
00396     return 0;
00397 }
00398 static int commission_application_provision_req_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00399 {
00400     commissioner_t *this = commissioner_find_by_service(service_id);
00401     uint8_t payload[11];// 4 + 1 + 4 + 2
00402     uint8_t *ptr;
00403 
00404     (void) source_port;
00405 
00406     tr_debug("joiner application provisioning recv addr %s", trace_ipv6(source_address));
00407     if (!this || !source_address || !request_ptr) {
00408         return -1;
00409     }
00410 
00411     thci_trace("Device - Comm|Direction - recv|EUI - %s|Type - JOIN_APP.req|Length - %d|Payload - %s", trace_array(&source_address[8], 8), request_ptr->payload_len, trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00412 
00413     ptr = payload;
00414     ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 1);
00415 
00416     thci_trace("Device - Comm|Direction - sent|EUI - %s|Type - JOIN_APP.resp|Length - %d|Payload - %s", trace_array(&source_address[8], 8), (int)(ptr - payload), trace_array(payload, ptr - payload));
00417     coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, payload, ptr - payload);
00418     return 0;
00419 }
00420 
00421 static int commission_dataset_changed_notify_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00422 {
00423     (void)source_address;
00424     (void)source_port;
00425 
00426     tr_debug("Dataset changed - notification received from: %s", trace_ipv6(source_address));
00427     commissioner_t *this = commissioner_find_by_service(service_id);
00428 
00429     if (!this) {
00430         return -1;
00431     }
00432 
00433     coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00434                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ACTIVE_GET, COAP_CT_OCTET_STREAM, NULL, 0, thread_commissioning_active_get_cb);
00435 
00436     coap_service_response_send(service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_NONE, NULL, 0);
00437 
00438     return 0;
00439 }
00440 static int thread_commission_udp_proxy_receive_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00441 {
00442     tr_debug("Recv UDP_RX.ntf");
00443 
00444     commissioner_t *this = commissioner_find_by_service(service_id);
00445     uint8_t *udp_encapsulation_ptr, *udp_tmf_ptr;
00446     uint16_t udp_encapsulation_len, udp_tmf_len;
00447     uint8_t *ipv6_addr_ptr;
00448     uint16_t ipv6_addr_len;
00449     uint16_t dest_port;
00450 
00451     (void) source_port;
00452 
00453     if (!this || !source_address || !request_ptr) {
00454         return -1;    // goto error response
00455     }
00456 
00457     udp_encapsulation_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_UDP_ENCAPSULATION, &udp_encapsulation_ptr);
00458     ipv6_addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_IPV6_ADDRESS, &ipv6_addr_ptr);
00459 
00460     if (udp_encapsulation_len == 0 || ipv6_addr_len < 16) {
00461         tr_warn("Corrupted UDP_RX.ntf received (%d, %d)", udp_encapsulation_len, ipv6_addr_len);
00462         return -1;
00463     }
00464 
00465     dest_port = common_read_16_bit(udp_encapsulation_ptr + 2);
00466     udp_tmf_len = udp_encapsulation_len - 4;
00467     udp_tmf_ptr = udp_encapsulation_ptr + 4;
00468 
00469     tr_debug("UDP_RX tmf: %s", trace_array(udp_tmf_ptr, udp_tmf_len));
00470 
00471     coap_service_virtual_socket_recv(this->coap_udp_proxy_service_id, ipv6_addr_ptr, dest_port, udp_tmf_ptr, udp_tmf_len);
00472 
00473     return -1; // no response sent
00474 }
00475 
00476 static uint8_t *bloom_filter_calculate(uint8_t *bloom_filter_ptr, device_list_t device_list, int *steering_tlv_max_length)
00477 {
00478     memset(bloom_filter_ptr, 0, *steering_tlv_max_length);
00479     ns_list_foreach(device_t, cur_ptr, &device_list) {
00480         if (memcmp(cur_ptr->EUI64, any_device, 8) != 0) {
00481             tr_debug("eui64 used on commissioning side = %s", trace_array(cur_ptr->EUI64, 8));
00482             cur_ptr->IID[0] |= 2; //Changed IID to MAC extended address for bloom filter calculation
00483             thread_beacon_calculate_bloom_filter(bloom_filter_ptr, *steering_tlv_max_length, cur_ptr->IID, 8);
00484             cur_ptr->IID[0] &= ~2;//Restore IID
00485         } else {
00486             bloom_filter_ptr[0] = 0xff;
00487             *steering_tlv_max_length = 1;
00488             break;
00489         }
00490     }
00491 
00492     return bloom_filter_ptr;
00493 }
00494 static int thread_commissioner_set_steering_data(commissioner_t *this, uint16_t session_id, uint8_t *steering_data_ptr, uint8_t steering_data_len)
00495 {
00496     uint8_t payload[24];/* 4 + 16 + 4*/
00497     uint8_t *ptr;
00498     int8_t coap_service_id;
00499     if (!this || steering_data_len > 16) {
00500         return -1;
00501     }
00502 
00503     ptr = payload;
00504     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_STEERING_DATA, steering_data_len, steering_data_ptr);
00505     ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, session_id);
00506 
00507     tr_debug("thread commissioner set steering data %s", trace_array(steering_data_ptr, steering_data_len));
00508     memcpy(this->final_dest_address, this->leader_address, 16);
00509     //default uri for thread version 1.1
00510     char *uri = THREAD_URI_COMMISSIONER_SET;
00511 
00512     if (this->native_commissioner) {
00513         coap_service_id = this->coap_udp_proxy_service_id;
00514     } else {
00515         coap_service_id = this->coap_service_id;
00516     }
00517 
00518     coap_service_request_send(coap_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00519                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri, COAP_CT_OCTET_STREAM, payload, ptr - payload, NULL);
00520 
00521     return 0;
00522 }
00523 
00524 static int commission_steering_data_update(commissioner_t *this)
00525 {
00526     //variable for steering tlv length - maximum possible length is 16 bytes - section 8.10.1.9 Max length
00527     int steering_tlv_length = 16;
00528     uint8_t bloom_filter_ptr[16];
00529     int ret;
00530 
00531     //bloom filter calculation function call
00532     bloom_filter_calculate(bloom_filter_ptr, this->device_list, &steering_tlv_length);
00533     tr_debug("Steering bloom set :%s", trace_array(bloom_filter_ptr, 16));
00534     ret = thread_commissioner_set_steering_data(this, this->session_id, bloom_filter_ptr, steering_tlv_length);
00535     if (ret) {
00536         tr_warn("Steering data set failed %d", ret);
00537         return -1;
00538     }
00539 
00540     return 0;
00541 }
00542 
00543 /*
00544  * These functions are the relay endpoint for commissioner device.
00545  * this can be either:
00546  * secure native commissioner
00547  * or unsecure native commissioner
00548  * */
00549 static int commission_relay_rx_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00550 {
00551     commissioner_t *this = commissioner_find_by_service(service_id);
00552     uint8_t joiner_address[16] = { 0xfe, 0x80 };
00553     uint8_t *joiner_iid_ptr;
00554     uint8_t *udp_ptr;
00555     uint16_t udp_len;
00556     uint16_t joiner_port;
00557     uint16_t joiner_router_rloc;
00558     device_t *device_ptr;
00559     (void) source_port;
00560 
00561     if (!this || !source_address || !request_ptr) {
00562         return -1;    // goto error response
00563     }
00564 
00565     if ((0 == (udp_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ENCAPSULATION, &udp_ptr))) ||
00566             (8 > thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_IID, &joiner_iid_ptr))  ||
00567             (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_UDP_PORT, &joiner_port)) ||
00568             (2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, &joiner_router_rloc))) {
00569         tr_warn("Corrupted relay packet received");
00570         return -1;
00571     }
00572 
00573     memcpy(&joiner_address[8], joiner_iid_ptr, 8);
00574     tr_debug("Relay RX from (%x) addr %s, port %d, len:%d", joiner_router_rloc, trace_ipv6(joiner_address), joiner_port, udp_len);
00575 
00576     device_ptr = device_find_by_iid(this, joiner_iid_ptr);
00577     if (!device_ptr) {
00578         tr_warn("unknown device connected");
00579         //Interop HACK
00580         device_ptr = device_find(this, (uint8_t *)any_device);
00581         if (!device_ptr) {
00582             tr_warn("No catch all device added");
00583             return -1;
00584         }
00585 
00586         memcpy(device_ptr->IID, &joiner_address[8], 8);
00587         memcpy(device_ptr->EUI64, &joiner_address[8], 8); // This is wrong as we cannot reverse the SHA1 But ok For Any device
00588         device_ptr->EUI64[0] ^= 2;// We are searching for list of eui64 so need to flip
00589         if (commission_steering_data_update(this) != 0) {
00590             return -1;
00591         }
00592         tr_warn("catching device for iid:%s", trace_array(&joiner_address[8], 8));
00593     }
00594     device_ptr->joiner_router_rloc = joiner_router_rloc;
00595     coap_service_virtual_socket_recv(this->coap_secure_virtual_service_id, joiner_address, joiner_port, udp_ptr, udp_len);
00596     return -1; // no response sent
00597 }
00598 
00599 static int commission_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len)
00600 {
00601     commissioner_t *this = commissioner_find_by_service(service_id);
00602     uint8_t destination_address[16];
00603     uint16_t destination_port;
00604     device_t *device_ptr;
00605     uint8_t *payload_ptr;
00606     uint8_t *ptr;
00607     uint16_t payload_len;
00608     uint8_t destination_service_id;
00609 
00610     tr_debug("Relay RX send addr %s, port %d, len:%d", trace_ipv6(destination_addr_ptr), port, data_len);
00611     if (!this || !destination_addr_ptr || !data_ptr) {
00612         return -1;
00613     }
00614 
00615     device_ptr = device_find_by_iid(this, &destination_addr_ptr[8]);
00616     if (!device_ptr) {
00617         return -2;
00618     }
00619     payload_len =  4 + data_len + 4 + 8 + 4 + 2;
00620 
00621     if (device_ptr->send_kek) {
00622         payload_len += 4 + 16;
00623     }
00624 
00625     payload_ptr = ns_dyn_mem_alloc(payload_len);
00626     if (!payload_ptr) {
00627         return -3;
00628     }
00629     if (this->native_commissioner) {
00630         destination_service_id = this->coap_secure_service_id;
00631         memcpy(destination_address, this->destination_address, 16);
00632         destination_port = this->destination_port;
00633     } else {
00634         memset(destination_address, 0, 16);
00635         destination_service_id = this->coap_service_id;
00636         thread_management_get_ml_prefix(this->interface_id, destination_address);
00637         common_write_16_bit(0xfffe, &destination_address[11]);
00638         common_write_16_bit(device_ptr->joiner_router_rloc, &destination_address[14]);
00639         destination_port = THREAD_MANAGEMENT_PORT;
00640     }
00641 
00642     tr_debug("Relay destination %s:%d", trace_ipv6(destination_address), destination_port);
00643 
00644     ptr = payload_ptr;
00645     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ENCAPSULATION, data_len, data_ptr);
00646     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_IID, 8, &destination_addr_ptr[8]);
00647     ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_UDP_PORT, port);
00648     ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_JOINER_ROUTER_LOCATOR, device_ptr->joiner_router_rloc);
00649 
00650     if (device_ptr->send_kek) {
00651         tr_debug("Relay RX Send KEK");
00652         ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_JOINER_ROUTER_KEK, 16, device_ptr->kek);
00653         device_ptr->send_kek = false;
00654     }
00655 
00656     coap_service_request_send(destination_service_id, COAP_REQUEST_OPTIONS_NONE, destination_address, destination_port,
00657                               COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_RELAY_TRANSMIT, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL);
00658 
00659     ns_dyn_mem_free(payload_ptr);
00660 
00661     return 0;
00662 }
00663 
00664 static int commissioning_security_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40])
00665 {
00666     commissioner_t *this = commissioner_find_by_service(service_id);
00667     device_t *device_ptr;
00668 
00669     if (!this) {
00670         return -1;
00671     }
00672 
00673     tr_debug("Commissioner security done addr %s keyblock %s", trace_ipv6(address), trace_array(keyblock, 40));
00674     device_ptr = device_find_by_iid(this, &address[8]);
00675     if (!device_ptr) {
00676         tr_debug("Commissioner device not found");
00677         thci_trace("commissionerBrError");
00678         return -1;
00679     }
00680     ns_sha256(keyblock, 40, device_ptr->kek);
00681 
00682     return 0;
00683 }
00684 
00685 static int joiner_commissioner_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len)
00686 {
00687     int ret = -1;
00688     (void)port;
00689     tr_info("commissionerJoinerDtlsSessionStarted");
00690 
00691     commissioner_t *this = commissioner_find_by_service(service_id);
00692 
00693     if (!this) {
00694         return ret;
00695     }
00696 
00697     device_t *device_ptr = device_find_by_iid(this, &address[8]);
00698 
00699     if (device_ptr) {
00700         memcpy(pw, device_ptr->PSKd, device_ptr->PSKd_len);
00701         *pw_len = device_ptr->PSKd_len;
00702         ret = 0;
00703 //        ret = coap_service_security_key_set( service_id, address, port, device_ptr->PSKd, device_ptr->PSKd_len );
00704     }
00705 
00706     return ret;
00707 }
00708 
00709 static int commissioner_br_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len)
00710 {
00711     int ret = -1;
00712     (void)address;
00713     (void)port;
00714     tr_info("commissionerBrDtlsSessionStarted");
00715     commissioner_t *this = commissioner_find_by_service(service_id);
00716     if (this) {
00717         memcpy(pw, this->PSKc_ptr, 16);
00718         *pw_len = 16;
00719         ret = 0;
00720 //        ret = coap_service_security_key_set( service_id, address, port, this->PSKc_ptr, this->PSKc_len );
00721     }
00722 
00723     return ret;
00724 }
00725 
00726 static int commissioner_br_security_done_cb(int8_t service_id, uint8_t address[16], uint8_t keyblock[static 40])
00727 {
00728     (void)service_id;
00729     (void)address;
00730     (void)keyblock;
00731     thci_trace("commissionerBrAccepted");
00732     thci_trace("commissionerPetitionStarted");
00733     return 0;
00734 }
00735 
00736 static int thread_commission_udp_proxy_virtual_socket_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port, const uint8_t *data_ptr, uint16_t data_len)
00737 {
00738     (void) port;
00739     uint8_t *payload_ptr;
00740     uint8_t *ptr;
00741     uint16_t payload_len;
00742     uint16_t source_port;
00743 
00744     commissioner_t *this = commissioner_find_by_service(service_id);
00745     if (!this) {
00746         return -1;
00747     }
00748 
00749     tr_debug("UDP_TX.ntf tmf: %s", trace_array(data_ptr, data_len));
00750     if (!this || !destination_addr_ptr || !data_ptr) {
00751         return -1;
00752     }
00753 
00754     payload_len =  2 + THREAD_IPV6_ADDRESS_TLV_LENGTH + 4 + 4 + data_len; // MESHCOP_TLV_IPV6_ADDRESS + MESHCOP_TLV_UDP_ENCAPSULATION
00755 
00756     payload_ptr = ns_dyn_mem_alloc(payload_len);
00757     if (!payload_ptr) {
00758         return -3;
00759     }
00760 
00761     ptr = payload_ptr;
00762 
00763     tr_debug("br_address %s final dest_address %s and port %d", trace_ipv6(this->destination_address),
00764              trace_ipv6(this->final_dest_address), this->destination_port);
00765 
00766     /* MESHCOP_TLV_IPV6_ADDRESS */
00767     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_IPV6_ADDRESS, THREAD_IPV6_ADDRESS_TLV_LENGTH, this->final_dest_address);
00768 
00769     /* MESHCOP_TLV_UDP_ENCAPSULATION */
00770     *ptr++ = MESHCOP_TLV_UDP_ENCAPSULATION;
00771     *ptr++ = 0xff;
00772     ptr = common_write_16_bit(2 + 2 + data_len, ptr); // length (Port x 2 + TMF message)
00773     source_port = randLIB_get_16bit(); // ephemeral port, 16-bit number
00774     ptr = common_write_16_bit(source_port, ptr); // source port,
00775     ptr = common_write_16_bit(THREAD_MANAGEMENT_PORT, ptr); // destination port
00776     memcpy(ptr, data_ptr, data_len);
00777     ptr += data_len;
00778 
00779     /* Send UDP_TX.ntf */
00780     coap_service_request_send(this->coap_secure_service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00781                               COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_UDP_TRANSMIT_NOTIFICATION, COAP_CT_OCTET_STREAM, payload_ptr, ptr - payload_ptr, NULL);
00782 
00783     ns_dyn_mem_free(payload_ptr);
00784 
00785     return 0;
00786 }
00787 
00788 /*
00789 Public api functions
00790 */
00791 int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16])
00792 {
00793     commissioner_t *this = commissioner_find(interface_id);
00794     if (!this) {
00795         this = commissioner_create(interface_id);
00796     }
00797     if (!this) {
00798         return -2;
00799     }
00800     memcpy(this->PSKc_ptr, PSKc, 16);
00801     if (this->registered) {
00802         return 0;
00803     }
00804     this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
00805     coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb);
00806     coap_service_register_uri(this->coap_service_id, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_application_provision_req_recv_cb);
00807     coap_service_register_uri(this->coap_service_id, THREAD_URI_DATASET_CHANGED, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_dataset_changed_notify_recv_cb);
00808 
00809     this->coap_secure_service_id = coap_service_initialize(this->interface_id, THREAD_COMMISSIONING_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, commissioner_br_security_start_cb, commissioner_br_security_done_cb);
00810     coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_relay_rx_recv_cb);
00811     coap_service_register_uri(this->coap_secure_service_id, THREAD_URI_UDP_RECVEIVE_NOTIFICATION, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_commission_udp_proxy_receive_cb);
00812 
00813     this->coap_secure_virtual_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, joiner_commissioner_security_start_cb, commissioning_security_done_cb);
00814     coap_service_register_uri(this->coap_secure_virtual_service_id, THREAD_URI_JOINER_FINALIZATION, COAP_SERVICE_ACCESS_POST_ALLOWED, commission_finalisation_req_recv_cb);
00815     coap_service_virtual_socket_set_cb(this->coap_secure_virtual_service_id, commission_virtual_socket_send_cb);
00816 
00817     this->coap_udp_proxy_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET, NULL, NULL);
00818     coap_service_virtual_socket_set_cb(this->coap_udp_proxy_service_id, thread_commission_udp_proxy_virtual_socket_send_cb);
00819 
00820     return 0;
00821 }
00822 
00823 int thread_commissioning_unregister(int8_t interface_id)
00824 {
00825     commissioner_t *this = commissioner_find(interface_id);
00826     if (!this) {
00827         return -1;
00828     }
00829     if (this->registered) {
00830         // Unregister the commissioner
00831         thread_commissioning_petition_keep_alive(this->interface_id, COMMISSIONING_STATE_REJECT);
00832     }
00833 
00834     coap_service_delete(this->coap_service_id);
00835     coap_service_delete(this->coap_secure_service_id);
00836     coap_service_delete(this->coap_secure_virtual_service_id);
00837     coap_service_delete(this->coap_udp_proxy_service_id);
00838 
00839     commissioner_delete(this);
00840     return 0;
00841 }
00842 
00843 int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_id_ptr, thread_commissioning_status_cb *status_cb_ptr)
00844 {
00845     commissioner_t *this;
00846     uint8_t payload[68];// max length for commissioner id is 64 + 4 byte header
00847     uint8_t commissioner_id_length;
00848     uint8_t service_id;
00849     uint8_t *ptr;
00850     char *uri_ptr;
00851     this = commissioner_find(interface_id);
00852 
00853     if (!this) {
00854         return -1;
00855     }
00856     if (!commissioner_id_ptr) {
00857         return -2;
00858     }
00859     commissioner_id_length = strlen(commissioner_id_ptr);
00860 
00861     if (commissioner_id_length > 64) {
00862         return -3;
00863     }
00864 
00865     if (this->native_commissioner) {
00866         uri_ptr = THREAD_URI_COMMISSIONER_PETITION;
00867         service_id = this->coap_secure_service_id;
00868     } else {
00869         uri_ptr = THREAD_URI_LEADER_PETITION;
00870         service_id = this->coap_service_id;
00871         thread_management_get_leader_aloc(this->interface_id, this->destination_address);
00872         this->destination_port = THREAD_MANAGEMENT_PORT;
00873     }
00874 
00875     this->status_cb_ptr = status_cb_ptr;
00876     ptr = payload;
00877     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_COMMISSIONER_ID, commissioner_id_length, (uint8_t *) commissioner_id_ptr);
00878 
00879     tr_debug("Thread Petition send to %s:%d id %s ", trace_ipv6(this->destination_address), this->destination_port, commissioner_id_ptr);
00880 
00881     //TODO there must be way to set PSKc for request
00882     //TODO there must be way to make client transactions with security and no security
00883     coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00884                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, payload, ptr - payload, commissioning_leader_petition_recv_cb);
00885     return 0;
00886 }
00887 
00888 int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_state_e state)
00889 {
00890     commissioner_t *this;
00891     uint8_t payload[7];
00892     uint8_t *ptr;
00893     uint8_t service_id;
00894     char *uri_ptr;
00895     /* length is
00896        state tlv 3
00897        session id tlv 4
00898     */
00899     this = commissioner_find(interface_id);
00900 
00901     if (!this) {
00902         return -1;
00903     }
00904 
00905     if (this->native_commissioner) {
00906         uri_ptr = THREAD_URI_COMMISSIONER_KEEP_ALIVE;
00907         service_id = this->coap_secure_service_id;
00908     } else {
00909         uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE;
00910         service_id = this->coap_service_id;
00911         thread_management_get_leader_aloc(this->interface_id, this->destination_address);
00912     }
00913 
00914     ptr = payload;
00915     ptr = thread_meshcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, (uint8_t)commissioning_meshcop_map_state(state));
00916     ptr = thread_meshcop_tlv_data_write_uint16(ptr, MESHCOP_TLV_COMMISSIONER_SESSION_ID, this->session_id);
00917 
00918     tr_debug("Commissioner keep alive send to %s:%d, session_id=%d, state=%d",
00919              trace_ipv6(this->destination_address), this->destination_port,
00920              this->session_id, state);
00921     thci_trace("commissionerKeepAliveSent");
00922     if (state != COMMISSIONING_STATE_ACCEPT) {
00923         this->session_id = 0;
00924     }
00925     coap_service_request_send(service_id, COAP_REQUEST_OPTIONS_NONE, this->destination_address, this->destination_port,
00926                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, payload, ptr - payload, commissioning_keep_alive_recv_cb);
00927     return 0;
00928 }
00929 
00930 /*
00931  * PSKD (Pre-Shared Key -Device). A PSKD can be a minimum of six (6) uppercase alphanumeric characters long
00932  *
00933  * */
00934 int thread_commissioning_device_add(int8_t interface_id, bool short_eui64, uint8_t EUI64[static 8], uint8_t *PSKd_ptr, uint8_t PSKd_len, thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr)
00935 {
00936     commissioner_t *this;
00937     device_t *device_ptr = NULL;
00938 
00939     this = commissioner_find(interface_id);
00940     if (!this || PSKd_len < 1 || PSKd_len > 32 || !PSKd_ptr) {
00941         return -1;
00942     }
00943 
00944     if (memcmp(EUI64, any_device, 8) == 0) {
00945         // always add 'any' device to allow multiple 'any' devices
00946         device_ptr = device_create(this);
00947     }
00948 
00949     if (!device_ptr) {
00950         // try to find an existing device
00951         device_ptr = device_find(this, EUI64);
00952     }
00953 
00954     if (!device_ptr) {
00955         // create device
00956         device_ptr = device_create(this);
00957     }
00958 
00959     if (!device_ptr) {
00960         return -2;
00961     }
00962 
00963     memcpy(device_ptr->EUI64, EUI64, 8);
00964     if (memcmp(EUI64, any_device, 8) != 0) {
00965         ns_sha256_nbits(EUI64, 8, device_ptr->IID, 64);
00966         device_ptr->IID[0] &= ~2; //local administered bit is set in MAC and flipped in IID
00967     } else {
00968         memcpy(device_ptr->IID, any_device, 8);
00969     }
00970 
00971     memcpy(device_ptr->PSKd, PSKd_ptr, PSKd_len);
00972     device_ptr->PSKd_len = PSKd_len;
00973     device_ptr->short_eui64 = short_eui64;
00974     device_ptr->joining_device_cb_ptr = joining_device_cb_ptr;
00975 
00976     if (commission_steering_data_update(this) != 0) {
00977         return -2;
00978     }
00979     thci_trace("commissionerNwkDataSynced");
00980     return 0;
00981 }
00982 
00983 int thread_commissioning_device_delete(int8_t interface_id, uint8_t EUI64[static 8])
00984 {
00985     commissioner_t *this = commissioner_find(interface_id);
00986 
00987     if (!this) {
00988         return -1;
00989     }
00990 
00991     tr_debug("delete commissioned device EUI64:%s", trace_array(EUI64, 8));
00992     device_delete(this, device_find(this, EUI64));
00993 
00994     if (commission_steering_data_update(this) != 0) {
00995         return -2;
00996     }
00997     return 0;
00998 }
00999 
01000 
01001 void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *short_eui64, uint8_t EUI64[8], uint8_t PSKd[32], uint8_t *PSKd_len)
01002 {
01003     commissioner_t *this = commissioner_find(interface_id);
01004     if (!this) {
01005         return NULL;
01006     }
01007     device_t *cur_ptr = (device_t *)ptr;
01008     if (cur_ptr == NULL) {
01009         cur_ptr = (device_t *)ns_list_get_first(&this->device_list);
01010     } else {
01011         cur_ptr = (device_t *)ns_list_get_next(&this->device_list, cur_ptr);
01012     }
01013     if (!cur_ptr) {
01014         return NULL;
01015     }
01016     if (short_eui64) {
01017         *short_eui64 = cur_ptr->short_eui64;
01018     }
01019     if (EUI64) {
01020         memcpy(EUI64, cur_ptr->EUI64, 8);
01021     }
01022     if (PSKd) {
01023         memcpy(PSKd, cur_ptr->PSKd, 32);
01024     }
01025     if (PSKd_len) {
01026         *PSKd_len = cur_ptr->PSKd_len;
01027     }
01028 
01029     return cur_ptr;
01030 }
01031 
01032 int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port)
01033 {
01034     tr_debug("start ethernet commissioner attach");
01035     commissioner_t *this = commissioner_find(interface_id);
01036     if (!this) {
01037         return -1;
01038     }
01039     memcpy(this->destination_address, destination_address, 16);
01040     this->destination_port = destination_port;
01041     this->native_commissioner = true;
01042     return 0;
01043 
01044 }
01045 
01046 int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr)
01047 {
01048     protocol_interface_info_entry_t *cur;
01049     cur = protocol_stack_interface_info_get_by_id(interface_id);
01050     tr_debug("start native commissioner scanning");
01051     if (!cur || !cur->thread_info) {
01052         return -1;
01053     }
01054     cur->thread_info->native_commissioner_link = NULL;
01055     cur->thread_info->native_commissioner_cb = cb_ptr;
01056     //TODO check if bootstrap is connected then we have to drop from old network and trigger scanning
01057     return 0;
01058 
01059 }
01060 
01061 int thread_commissioning_native_commissioner_stop(int8_t interface_id)
01062 {
01063     protocol_interface_info_entry_t *cur;
01064     cur = protocol_stack_interface_info_get_by_id(interface_id);
01065     tr_debug("stop native commissioner scanning");
01066     if (!cur || !cur->thread_info) {
01067         return -1;
01068     }
01069     ns_dyn_mem_free(cur->thread_info->native_commissioner_link);
01070     cur->thread_info->native_commissioner_link = NULL;
01071     cur->thread_info->native_commissioner_cb = NULL;
01072     return 0;
01073 }
01074 
01075 int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread_commissioning_link_configuration_s *link_ptr)
01076 {
01077     protocol_interface_info_entry_t *cur;
01078     cur = protocol_stack_interface_info_get_by_id(interface_id);
01079     tr_debug("connect native commissioner");
01080     if (!cur || !cur->thread_info) {
01081         return -1;
01082     }
01083     cur->thread_info->native_commissioner_link = ns_dyn_mem_alloc(sizeof(thread_commissioning_link_configuration_s));
01084     if (!cur->thread_info->native_commissioner_link) {
01085         return -2;
01086     }
01087     *cur->thread_info->native_commissioner_link = *link_ptr;
01088 
01089     commissioner_t *this = commissioner_find(interface_id);
01090     if (!this) {
01091         this = commissioner_create(interface_id);
01092     }
01093     if (!this) {
01094         return -3;
01095     }
01096 
01097     this->native_commissioner = true;
01098     memcpy(this->destination_address, link_ptr->destination_address, 16);
01099     this->destination_port = link_ptr->destination_port;
01100     //TODO check that we are scanning for networks and reset backup timers
01101 
01102     return 0;
01103 }
01104 
01105 int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port)
01106 {
01107     commissioner_t *this = commissioner_find(interface_id);
01108     tr_debug("get native connection info");
01109     if (!this) {
01110         return -1;
01111     }
01112 
01113     memcpy(address_ptr, this->destination_address, 16);
01114 
01115     *port = this->destination_port;
01116     return 0;
01117 }
01118 
01119 int8_t thread_commissioning_get_management_id(int8_t interface_id)
01120 {
01121     commissioner_t *this = commissioner_find(interface_id);
01122     if (!this) {
01123         return -1;
01124     }
01125 
01126     return this->management_instance;
01127 }
01128 
01129 
01130 #else
01131 int thread_commissioning_register(int8_t interface_id, uint8_t PSKc[static 16])
01132 {
01133     (void)interface_id;
01134     (void)PSKc;
01135     return -1;
01136 }
01137 
01138 int thread_commissioning_unregister(int8_t interface_id)
01139 {
01140     (void)interface_id;
01141     return -1;
01142 }
01143 
01144 int thread_commissioning_device_add(int8_t interface_id, bool short_eui64, uint8_t EUI64[static 8], uint8_t *PSKd_ptr, uint8_t PSKd_len, thread_commissioning_joiner_finalisation_cb *joining_device_cb_ptr)
01145 {
01146     (void)interface_id;
01147     (void)short_eui64;
01148     (void)EUI64;
01149     (void)PSKd_ptr;
01150     (void)PSKd_len;
01151     (void)joining_device_cb_ptr;
01152     return -1;
01153 }
01154 
01155 int thread_commissioning_device_delete(int8_t interface_id, uint8_t EUI64[8])
01156 {
01157     (void)interface_id;
01158     (void)EUI64;
01159     return -1;
01160 }
01161 void *thread_commission_device_get_next(void *ptr, int8_t interface_id, bool *short_eui64, uint8_t EUI64[8], uint8_t PSKd[32], uint8_t *PSKd_len)
01162 {
01163     (void)ptr;
01164     (void)interface_id;
01165     (void)short_eui64;
01166     (void)EUI64;
01167     (void)PSKd;
01168     (void)PSKd_len;
01169     return NULL;
01170 }
01171 
01172 int thread_commissioning_petition_keep_alive(int8_t interface_id, commissioning_state_e state)
01173 {
01174     (void)interface_id;
01175     (void)state;
01176     return -1;
01177 }
01178 
01179 int thread_commissioning_petition_start(int8_t interface_id, char *commissioner_id_ptr, thread_commissioning_status_cb *status_cb_ptr)
01180 {
01181     (void)interface_id;
01182     (void)commissioner_id_ptr;
01183     (void)status_cb_ptr;
01184     return -1;
01185 }
01186 
01187 int thread_commissioning_native_commissioner_get_connection_info(int8_t interface_id, uint8_t *address_ptr, uint16_t *port)
01188 {
01189     (void)interface_id;
01190     (void)address_ptr;
01191     (void)port;
01192     return -1;
01193 }
01194 
01195 int8_t thread_commissioning_get_management_id(int8_t interface_id)
01196 {
01197     (void)interface_id;
01198     return -1;
01199 }
01200 
01201 int thread_commissioning_native_commissioner_start(int8_t interface_id, thread_commissioning_native_select_cb *cb_ptr)
01202 {
01203     (void)interface_id;
01204     (void)cb_ptr;
01205     return -1;
01206 }
01207 
01208 int thread_commissioning_native_commissioner_stop(int8_t interface_id)
01209 {
01210     (void)interface_id;
01211     return -1;
01212 }
01213 
01214 int thread_commissioning_native_commissioner_connect(int8_t interface_id, thread_commissioning_link_configuration_s *link_ptr)
01215 {
01216     (void)interface_id;
01217     (void)link_ptr;
01218     return -1;
01219 }
01220 
01221 int thread_commissioning_attach(int8_t interface_id, uint8_t *destination_address, uint16_t destination_port)
01222 {
01223     (void)interface_id;
01224     (void)destination_address;
01225     (void)destination_port;
01226     return -1;
01227 }
01228 
01229 #endif