Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_bbr_api.c Source File

thread_bbr_api.c

00001 /*
00002  * Copyright (c) 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 #include "nsconfig.h"
00030 
00031 #ifdef HAVE_THREAD_ROUTER
00032 
00033 #include <string.h>
00034 #include "ns_types.h"
00035 #include <nsdynmemLIB.h>
00036 #include <ns_list.h>
00037 #include "ns_trace.h"
00038 #include "eventOS_event_timer.h"
00039 #include "randLIB.h"
00040 #include "common_functions.h"
00041 #include "thread_border_router_api.h"
00042 #include "thread_bbr_api.h"
00043 #include "Common_Protocols/ipv6_constants.h"
00044 #include "DHCPv6_Server/DHCPv6_server_service.h"
00045 #include "thread_management_if.h"
00046 #include "6LoWPAN/Thread/thread_config.h"
00047 #include "6LoWPAN/Thread/thread_constants.h"
00048 #include "6LoWPAN/Thread/thread_common.h"
00049 #include "6LoWPAN/Thread/thread_joiner_application.h"
00050 #include "6LoWPAN/Thread/thread_extension.h"
00051 #include "6LoWPAN/Thread/thread_extension_bbr.h"
00052 #include "6LoWPAN/Thread/thread_tmfcop_lib.h"
00053 #include "6LoWPAN/Thread/thread_management_internal.h"
00054 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00055 #include "6LoWPAN/Thread/thread_router_bootstrap.h"
00056 #include "6LoWPAN/Thread/thread_border_router_api_internal.h"
00057 #include "6LoWPAN/Thread/thread_mdns.h"
00058 #include "6LoWPAN/MAC/mac_helper.h"
00059 #include "coap_service_api.h"
00060 #include "thread_management_server.h"
00061 #include "socket_api.h"
00062 #include "coap_service_api.h"
00063 #include "Common_Protocols/icmpv6.h"
00064 
00065 #define TRACE_GROUP "tBBR"
00066 
00067 /*
00068  * Border router instance data.
00069  */
00070 typedef struct {
00071     uint8_t commissioner_address[16];
00072     uint8_t bbr_prefix[8];
00073     uint16_t commissioner_pet_request_msg_id;
00074     uint32_t br_delay_timer;
00075     uint32_t br_delete_timer;
00076     uint32_t router_upgrade_delay_timer;
00077     uint16_t commissioner_timer;/* Commissioner parameter */
00078     uint16_t commissioner_port; /* source port of commissioner border router */
00079     uint16_t joiner_router_rloc;
00080     uint8_t br_count;
00081     int8_t interface_id;
00082     int8_t coap_service_id;
00083     int8_t coap_extension_virtual_service_id;
00084     int8_t br_service_id;
00085     int8_t backbone_interface_id;
00086     int8_t udp_proxy_socket; /* socket to relay messages between BA and nodes */
00087     bool br_info_published:1;
00088     bool br_hosted:1;
00089     bool routing_enabled:1;
00090     bool commissioner_connected:1;
00091     ns_list_link_t link;
00092 } thread_bbr_t;
00093 
00094 /* Neighbor discovery options according to RFC6106 (rfc4861) */
00095 #define RFC6106_RECURSIVE_DNS_SERVER_OPTION     25
00096 #define RFC6106_DNS_SEARCH_LIST_OPTION          31
00097 static NS_LIST_DEFINE(bbr_instance_list, thread_bbr_t, link);
00098 
00099 
00100 static thread_bbr_t *thread_bbr_find_by_interface(int8_t interface_id)
00101 {
00102     thread_bbr_t *this = NULL;
00103     ns_list_foreach(thread_bbr_t, cur_br, &bbr_instance_list) {
00104         if (cur_br->interface_id == interface_id) {
00105             this = cur_br;
00106             break;
00107         }
00108     }
00109     return this;
00110 }
00111 
00112 static thread_bbr_t *thread_border_router_find_by_service(int8_t service_id)
00113 {
00114     thread_bbr_t *this = NULL;
00115     ns_list_foreach(thread_bbr_t, cur_br, &bbr_instance_list) {
00116         if (cur_br->coap_service_id == service_id || cur_br->br_service_id == service_id) {
00117             this = cur_br;
00118             break;
00119         }
00120     }
00121     return this;
00122 }
00123 
00124 static thread_bbr_t *thread_border_router_find_by_udp_proxy_recv_socket_id(int8_t socket_id)
00125 {
00126     thread_bbr_t *this = NULL;
00127     ns_list_foreach(thread_bbr_t, cur_br, &bbr_instance_list) {
00128         if (cur_br->udp_proxy_socket == socket_id) {
00129             this = cur_br;
00130             break;
00131         }
00132     }
00133     return this;
00134 }
00135 
00136 static void thread_border_router_commissioner_info_clear(thread_bbr_t *this)
00137 {
00138     this->commissioner_timer = 0;
00139     coap_service_close_secure_connection(this->br_service_id, this->commissioner_address, this->commissioner_port);
00140     coap_service_unregister_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE);
00141     this->commissioner_connected = false;
00142 }
00143 
00144 static int thread_border_agent_tmf_get_request_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00145 {
00146     (void)source_address;
00147     (void)source_port;
00148 
00149     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00150 
00151     if (!this) {
00152         return -1;
00153     }
00154 
00155     return thread_management_server_tmf_get_request_handler(this->interface_id, service_id, request_ptr);
00156 }
00157 
00158 static int thread_border_router_relay_transmit_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00159 {
00160     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00161     uint8_t destination_address[16];
00162     uint16_t shortAddress;
00163     (void)source_address;
00164     (void)source_port;
00165 
00166     tr_debug("border router relay transmit");
00167     thci_trace("brCommissionerDataRelayedInbound");
00168 
00169     if (!this) {
00170         return -1;
00171     }
00172     ;
00173     if ( thread_management_get_ml_prefix_112(this->interface_id,destination_address) != 0 ||
00174          2 > thread_meshcop_tlv_data_get_uint16(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_JOINER_ROUTER_LOCATOR,&shortAddress)) {
00175         tr_warn("No joiner router address");
00176         return -1;
00177     }
00178 
00179     common_write_16_bit(shortAddress, &destination_address[14]);
00180 
00181     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination_address, THREAD_MANAGEMENT_PORT,
00182         COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_RELAY_TRANSMIT, COAP_CT_OCTET_STREAM, request_ptr->payload_ptr, request_ptr->payload_len, NULL);
00183     return -1;
00184 }
00185 
00186 static int br_commissioner_security_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw, uint8_t *pw_len)
00187 {
00188     int ret = -1;
00189     (void)address;
00190     (void)port;
00191 
00192     tr_info("brCommissionerDtlsSessionStarted");
00193     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00194     if(this){
00195         link_configuration_s *linkConfiguration = thread_joiner_application_get_config(this->interface_id);
00196         if( linkConfiguration ){
00197             memcpy(pw, linkConfiguration->PSKc, 16 );
00198             *pw_len = 16;
00199             ret = 0;
00200         }else{
00201             *pw_len = 0;
00202         }
00203 //        ret = coap_service_security_key_set( service_id, address, port, this->PSKc_ptr, this->PSKc_len );
00204     }
00205     return ret;
00206 }
00207 
00208 static int br_commissioner_security_done_cb(int8_t service_id, uint8_t address[16], uint8_t keyblock[static 40])
00209 {
00210     (void)service_id;
00211     (void)address;
00212     (void)keyblock;
00213     thci_trace("brCommissionerAccepted");
00214     return 0;
00215 }
00216 
00217 static int thread_border_router_relay_receive_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00218 {
00219     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00220     (void) source_address;
00221     (void) source_port;
00222     tr_debug("border router relay receive");
00223     thci_trace("brCommissionerDataRelayedOutbound");
00224     if (!this)
00225         return -1;
00226 
00227     coap_service_request_send(this->br_service_id, COAP_REQUEST_OPTIONS_NONE, this->commissioner_address, this->commissioner_port,
00228                               COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_RELAY_RECEIVE, COAP_CT_OCTET_STREAM, request_ptr->payload_ptr, request_ptr->payload_len, NULL);
00229     return -1;// no response for relay
00230 }
00231 
00232 /**
00233  * Thread border router petition
00234  * uri = tn/mc/la
00235  */
00236 static int thread_border_router_leader_petition_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
00237 {
00238     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00239     uint8_t *ptr;
00240     (void)source_address;
00241     (void)source_port;
00242 
00243     if (!response_ptr) {
00244         tr_warn("invalid params");
00245         return -1;
00246     }
00247 
00248     thci_trace("BR recv petition Resp data: %s",trace_array(response_ptr->payload_ptr, response_ptr->payload_len));
00249     //tr_debug("border router leader response");
00250     if (!this) {
00251         tr_warn("commissioner service missing!");
00252         return -1;
00253     }
00254 
00255     if (1 <= thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &ptr) && *ptr == 1) {
00256         // commissioning petition successfull
00257         if(this->commissioner_connected == false) {
00258             tr_debug("enabling native commissioner");
00259             coap_service_register_uri(this->coap_service_id, THREAD_URI_RELAY_RECEIVE, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_border_router_relay_receive_cb);
00260 
00261         }
00262         this->commissioner_connected = true;
00263     } else {
00264         tr_debug("disabling native commissioner");
00265         this->commissioner_connected = false;
00266     }
00267 
00268     coap_service_response_send_by_msg_id(this->br_service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, this->commissioner_pet_request_msg_id, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, response_ptr->payload_ptr, response_ptr->payload_len);
00269     this->commissioner_pet_request_msg_id = 0;
00270     if(!this->commissioner_connected){
00271         // Commissioner rejected by leader
00272         thread_border_router_commissioner_info_clear(this);
00273     }
00274 
00275     return 0;
00276 }
00277 static int thread_border_router_leader_message_resp_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr)
00278 {
00279     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00280     (void)source_address;
00281     (void)source_port;
00282 
00283     if (!response_ptr || !this) {
00284         tr_warn("invalid params");
00285         return -1;
00286     }
00287 
00288     thci_trace("BR recv Resp data: %s",trace_array(response_ptr->payload_ptr, response_ptr->payload_len));
00289 
00290     coap_service_response_send_by_msg_id(this->br_service_id, COAP_REQUEST_OPTIONS_SECURE_BYPASS, this->commissioner_pet_request_msg_id, COAP_MSG_CODE_RESPONSE_CHANGED, COAP_CT_OCTET_STREAM, response_ptr->payload_ptr, response_ptr->payload_len);
00291     this->commissioner_pet_request_msg_id = 0;
00292 
00293     return 0;
00294 }
00295 
00296 /* UDP_TX.ntf c/tx
00297  * Handle message originating from Commissioner.
00298  * */
00299 static int thread_border_router_udp_proxy_transmit_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00300 {
00301     int ret_val = 0;
00302     uint8_t *udp_data_ptr, *ipv6_addr_ptr;
00303     uint16_t udp_data_len, ipv6_addr_len, encapsulation_payload_len;
00304     uint16_t dest_port;
00305     uint8_t *encapsulation_payload;
00306     ns_address_t ns_source_addr, ns_dest_addr;
00307     int16_t sock_status;
00308     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00309 
00310     (void) source_address;
00311     (void) source_port;
00312 
00313     tr_debug("Recv UDP_TX.ntf: %s", trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00314 
00315     if (!this) {
00316         return -1;
00317     }
00318 
00319     udp_data_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_UDP_ENCAPSULATION, &udp_data_ptr);
00320     ipv6_addr_len = thread_meshcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, MESHCOP_TLV_IPV6_ADDRESS, &ipv6_addr_ptr);
00321 
00322     if (udp_data_len == 0 || ipv6_addr_len != 16) {
00323         tr_err("UDP_TX.ntf invalid message");
00324         return -1;
00325     }
00326 
00327     // Find source and destination ports from the encapsulation message
00328     // source port is not used as we are already using ephemeral port in udp_proxy socket.
00329     dest_port = common_read_16_bit(udp_data_ptr + 2);
00330 
00331     // Get UDP payload
00332     encapsulation_payload = udp_data_ptr + 4;
00333     encapsulation_payload_len = udp_data_len - 4;
00334 
00335     // Set source parameters
00336     if (thread_management_get_commissioner_address(this->interface_id, ns_source_addr.address, 0) < 0) {
00337         tr_error("Failed to get commissioner ALOC");
00338         return -1;
00339     }
00340     // tr_debug("commissioner ALOC: %s", trace_ipv6(ns_source_addr.address));
00341     ns_source_addr.identifier = 0; // Use ephemeral port instead of src_port
00342     ns_source_addr.type = ADDRESS_IPV6;
00343 
00344     if (this->udp_proxy_socket < 0) {
00345         tr_error("UDP proxy socket not open!");
00346         return -1;
00347     }
00348 
00349     /* Bind source to Commissioner ALOC */
00350     ret_val = socket_bind(this->udp_proxy_socket, &ns_source_addr);
00351     if (ret_val < 0) {
00352         tr_error("UDP_TX socket bind2 failed %d", ret_val);
00353         ret_val = -1;
00354     }
00355 
00356     // Set destination parameters
00357     ns_dest_addr.identifier = dest_port;
00358     ns_dest_addr.type = ADDRESS_IPV6;
00359     memcpy(ns_dest_addr.address, ipv6_addr_ptr, 16);
00360 
00361     tr_debug("push TMF msg to: %s, sock=%d", trace_ipv6(ns_dest_addr.address), this->udp_proxy_socket);
00362     sock_status = socket_sendto(this->udp_proxy_socket, &ns_dest_addr, encapsulation_payload, encapsulation_payload_len);
00363     if (sock_status < 0) {
00364         tr_error("UDP Proxy socket write failed %d", sock_status);
00365         ret_val = -1;
00366     }
00367 
00368     return -1;
00369 }
00370 
00371 /*
00372  * Handle messages to commissioner.
00373  * Create UDP_RX.ntf TMF message and send it to commissioner.
00374  */
00375 static void thread_border_router_udp_proxy_tmf_message_receive(int8_t socket_id, ns_address_t *ns_address, uint8_t *tmf_data, int16_t tmf_data_len)
00376 {
00377     uint8_t *payload_ptr, *ptr;
00378     uint16_t payload_len;
00379     uint16_t dest_port = THREAD_MANAGEMENT_PORT;
00380 
00381     tr_debug("UDP_RX tmf from %s, port=%d", trace_ipv6(ns_address->address), ns_address->identifier);
00382 
00383     thread_bbr_t *this = thread_border_router_find_by_udp_proxy_recv_socket_id(socket_id);
00384     if (!this) {
00385         tr_error("BA instance not found!");
00386         return;
00387     }
00388 
00389     payload_len =  (2 + 2 + 2 + 2 + tmf_data_len) + (2 + THREAD_IPV6_ADDRESS_TLV_LENGTH);
00390 
00391     payload_ptr = ptr = ns_dyn_mem_alloc(payload_len);
00392     if (!payload_ptr) {
00393         tr_error("UDP_RX.ntf alloc failed!");
00394         return;
00395     }
00396 
00397     /* IPv6 Address TLV */
00398     ptr = thread_meshcop_tlv_data_write(ptr, MESHCOP_TLV_IPV6_ADDRESS, THREAD_IPV6_ADDRESS_TLV_LENGTH, ns_address->address);
00399 
00400     /* UDP Encapsulation TLV */
00401     *ptr++ = MESHCOP_TLV_UDP_ENCAPSULATION;
00402     *ptr++ = 0xff;
00403     ptr = common_write_16_bit(2 + 2 + tmf_data_len, ptr); // Length = source port + dest port + TMF message
00404     ptr = common_write_16_bit(ns_address->identifier, ptr);  //source port
00405     ptr = common_write_16_bit(dest_port, ptr);  // destination port
00406     memcpy(ptr, tmf_data, tmf_data_len);
00407 
00408     tr_debug("send to: %s, port=%d", trace_ipv6(this->commissioner_address), this->commissioner_port);
00409     tr_debug("UDP_RX.ntf: %s", trace_array(payload_ptr, payload_len));
00410     coap_service_request_send(this->br_service_id, COAP_REQUEST_OPTIONS_NONE, this->commissioner_address, this->commissioner_port,
00411             COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_UDP_RECVEIVE_NOTIFICATION, COAP_CT_OCTET_STREAM, payload_ptr, payload_len, NULL);
00412 
00413     ns_dyn_mem_free(payload_ptr);
00414 
00415     return;
00416 }
00417 
00418 /*
00419  * UDP_Proxy receive socket callback.
00420  * This method receives TMF messages from devices in Thread network and sends them to commissioner
00421  */
00422 static void thread_border_router_udp_proxy_socket_recv_callback(void *socket_cb)
00423 {
00424     socket_callback_t *socket_callback = (socket_callback_t *)socket_cb;
00425     ns_address_t ns_addr;
00426     int16_t length;
00427 
00428     if (socket_callback->event_type == SOCKET_DATA) {
00429         if (socket_callback->d_len > 0) {
00430             uint8_t *payload = (uint8_t *) ns_dyn_mem_alloc(socket_callback->d_len);
00431             if (!payload) {
00432                 tr_error("buffer allocation failed");
00433                 return;
00434             }
00435 
00436             length = socket_read(socket_callback->socket_id, &ns_addr, payload, socket_callback->d_len);
00437             if (length > 0) {
00438                 thread_border_router_udp_proxy_tmf_message_receive(socket_callback->socket_id, &ns_addr, payload, length);
00439             }
00440             ns_dyn_mem_free(payload);
00441         }
00442     }
00443 }
00444 
00445 static int thread_border_petition_to_leader_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00446 {
00447     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00448     uint8_t destination_address[16];
00449     char *uri_ptr;
00450 
00451     tr_debug("border router petition to leader");
00452 
00453     if (!this) {
00454         return -1;
00455     }
00456     if (0 != thread_management_get_leader_address(this->interface_id, destination_address)) {
00457         tr_debug("No leader");
00458         return -1;
00459     }
00460     if (strncmp(THREAD_URI_COMMISSIONER_PETITION, (const char *)request_ptr->uri_path_ptr, request_ptr->uri_path_len) == 0) {
00461         uri_ptr = THREAD_URI_LEADER_PETITION;
00462     } else if (strncmp(THREAD_URI_COMMISSIONER_KEEP_ALIVE,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len) == 0) {
00463         uri_ptr = THREAD_URI_LEADER_KEEP_ALIVE;
00464     } else {
00465         return -1;
00466     }
00467 
00468     // Update commissioner timeout for deleting the commissioner session if there is no messages.
00469     this->commissioner_timer = THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL/1000 + 10;
00470     //TODO simple relaying is enough
00471     memcpy(this->commissioner_address, source_address, 16);
00472     this->commissioner_port = source_port;
00473     this->commissioner_pet_request_msg_id = request_ptr->msg_id;//TODO one message at a time causes problems
00474     thci_trace("BR recv uri:%.*s data: %s",request_ptr->uri_path_len,request_ptr->uri_path_ptr,trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00475     //tr_debug("relay data %s",trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00476 
00477     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination_address, THREAD_MANAGEMENT_PORT,
00478                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, request_ptr->payload_ptr, request_ptr->payload_len, thread_border_router_leader_petition_resp_cb);
00479 
00480     return 0;
00481 }
00482 static int thread_border_relay_to_leader_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
00483 {
00484     thread_bbr_t *this = thread_border_router_find_by_service(service_id);
00485     uint8_t destination_address[16];
00486     char uri_ptr[10];
00487 
00488     tr_error("border router relay to leader using OLD specification");
00489 
00490     if (!this || request_ptr->uri_path_len > 10) {
00491         return -1;
00492     }
00493     if (0 != thread_management_get_leader_address(this->interface_id, destination_address)) {
00494         tr_debug("No leader");
00495         return -1;
00496     }
00497     //buffer length is limited to 10 characters
00498     memset(uri_ptr,0,10);
00499     memcpy(uri_ptr,(const char *)request_ptr->uri_path_ptr,request_ptr->uri_path_len);
00500 
00501     // Update commissioner timeout for deleting the commissioner session if there is no messages.
00502     this->commissioner_timer = THREAD_COMMISSIONER_KEEP_ALIVE_INTERVAL/1000 + 10;
00503     //TODO simple relaying is enough
00504     memcpy(this->commissioner_address, source_address, 16);
00505     this->commissioner_port = source_port;
00506     this->commissioner_pet_request_msg_id = request_ptr->msg_id;//TODO one message at a time causes problems
00507     thci_trace("BR recv uri:%.*s data: %s",request_ptr->uri_path_len,request_ptr->uri_path_ptr,trace_array(request_ptr->payload_ptr, request_ptr->payload_len));
00508 
00509     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination_address, THREAD_MANAGEMENT_PORT,
00510                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, uri_ptr, COAP_CT_OCTET_STREAM, request_ptr->payload_ptr, request_ptr->payload_len, thread_border_router_leader_message_resp_cb);
00511 
00512     return -1;
00513 }
00514 
00515 #ifdef HAVE_THREAD_BORDER_ROUTER
00516 static bool thread_bbr_i_host_prefix(struct protocol_interface_info_entry *cur, uint8_t prefix_ptr[8], uint8_t *br_count, bool *i_am_lowest)
00517 {
00518     bool i_host_this_prefix = false;
00519     uint16_t rloc16 = mac_helper_mac16_address_get(cur);
00520     uint16_t lowest_rloc16 = 0xfffe;
00521 
00522     if (br_count) {
00523         *br_count = 0;
00524     }
00525     if (i_am_lowest) {
00526         *i_am_lowest = false;
00527     }
00528     if (!prefix_ptr) {
00529         return false;
00530     }
00531 
00532     ns_list_foreach(thread_network_data_prefix_cache_entry_t, prefix, &cur->thread_info->networkDataStorage.localPrefixList) {
00533 
00534         if (prefix->servicesPrefixLen != 64 ||
00535             memcmp(prefix_ptr, prefix->servicesPrefix, 8) != 0) {
00536             continue;
00537         }
00538 
00539         ns_list_foreach(thread_network_server_data_entry_t, br, &prefix->borderRouterList) {
00540             if (br->routerID == 0xfffe) {
00541                 continue;
00542             }
00543             if (!br->P_default_route) {
00544                 continue;
00545             }
00546             if (lowest_rloc16 > br->routerID) {
00547                 lowest_rloc16 = br->routerID;
00548             }
00549             if (br_count) {
00550                 (*br_count)++;
00551             }
00552             if (rloc16 == br->routerID) {
00553                 i_host_this_prefix = true;
00554             }
00555         }
00556     }
00557     //tr_info("br: prefix %s, brs:%d %s",trace_array(prefix_ptr,8), *br_count, i_host_this_prefix?"I host":"");
00558     if (i_am_lowest) {
00559         *i_am_lowest = (lowest_rloc16 == rloc16);
00560     }
00561     return i_host_this_prefix;
00562 }
00563 
00564 static void thread_bbr_network_data_remove(thread_bbr_t *this)
00565 {
00566     tr_info("br: remove default route from network");
00567     thread_border_router_prefix_delete(this->interface_id, this->bbr_prefix, 64);
00568     DHCPv6_server_service_delete(this->interface_id,this->bbr_prefix,true);
00569     memset(this->bbr_prefix,0,8);
00570     this->br_info_published = false;
00571 }
00572 
00573 static void thread_bbr_network_data_send(thread_bbr_t *this, uint8_t prefix[8], uint8_t eui64[8])
00574 {
00575     thread_border_router_info_t br_info = { 0 };
00576 
00577     tr_info("br: publish default route to network");
00578 
00579     // delete old prefix
00580     memset(this->bbr_prefix,0,8);
00581     // create new prefix
00582     if (DHCPv6_server_service_init(this->interface_id, prefix, eui64, DHCPV6_DUID_HARDWARE_EUI64_TYPE) != 0) {
00583         tr_warn("DHCP server alloc fail");
00584         // set 20 seconds delay before next process
00585         this->br_delay_timer = 20;
00586         return;
00587     }
00588     memcpy(this->bbr_prefix,prefix,8);
00589 
00590     DHCPv6_server_service_set_address_validlifetime(this->interface_id, this->bbr_prefix, THREAD_MIN_PREFIX_LIFETIME);
00591 
00592     br_info.P_default_route = true;
00593     br_info.P_dhcp = true;
00594     br_info.P_on_mesh = true;
00595     br_info.stableData = true;
00596     thread_border_router_prefix_add(this->interface_id, this->bbr_prefix, 64, &br_info);
00597     thread_border_router_publish(this->interface_id);
00598     this->br_info_published = true;
00599 }
00600 
00601 static void thread_bbr_routing_enable(thread_bbr_t *this)
00602 {
00603     if (this->routing_enabled) {
00604         return;
00605     }
00606     tr_info("br: enable routing");
00607     // Start multicast proxying
00608     multicast_fwd_set_forwarding(this->interface_id, true);
00609     this->routing_enabled = true;
00610 }
00611 
00612 static void thread_bbr_routing_disable(thread_bbr_t *this)
00613 {
00614     if (!this->routing_enabled) {
00615         return;
00616     }
00617     tr_info("br: disable routing");
00618     // Stop multicast proxying
00619     //multicast_fwd_set_proxy_upstream(-1);
00620     // By default allow sitelocal multicast to enter mesh
00621     multicast_fwd_set_forwarding(this->interface_id, false);
00622     this->routing_enabled = false;
00623 }
00624 
00625 static void thread_bbr_status_check(thread_bbr_t *this, uint32_t seconds)
00626 {
00627     uint8_t global_address[16];
00628     uint8_t *bbr_prefix_ptr = NULL;
00629     bool br_lowest_host;
00630 
00631     if (this->br_delay_timer) {
00632         if (this->br_delay_timer > seconds) {
00633             this->br_delay_timer -= seconds;
00634             return;
00635         }
00636         this->br_delay_timer = 0;
00637     }
00638 
00639     if (arm_net_address_get(this->backbone_interface_id, ADDR_IPV6_GP, global_address) == 0) {
00640         bbr_prefix_ptr = global_address;
00641     }
00642 
00643     if ( this->br_info_published &&
00644          (!bbr_prefix_ptr || memcmp(this->bbr_prefix,bbr_prefix_ptr,8) != 0)) {
00645         // Address is changed or address removed
00646         // remove the old prefix and read the status of the new prefix
00647         tr_info("br: Address changed or not valid stop routing");
00648         thread_bbr_network_data_remove(this);
00649         thread_bbr_routing_disable(this);
00650         thread_border_router_publish(this->interface_id);
00651     }
00652     // Check if network data as border router is possible or modified
00653     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id);
00654     this->br_hosted = thread_bbr_i_host_prefix(cur, bbr_prefix_ptr,&this->br_count, &br_lowest_host);
00655 
00656     if (!this->br_info_published && bbr_prefix_ptr && this->br_count == 0) {
00657         // publish global route either no border routers or our info has changed
00658         tr_info("br: start and publish br info");
00659         thread_bbr_network_data_send(this, bbr_prefix_ptr, &global_address[8]);
00660     }
00661 
00662     // Check from network data are we currently BR or not and change routing state
00663     if (this->br_hosted) {
00664         thread_bbr_routing_enable(this);
00665     } else {
00666         thread_bbr_routing_disable(this);
00667     }
00668 
00669     // Check if we can abort the deletion
00670     if (this->br_count == 1) {
00671         if (bbr_prefix_ptr) {
00672             // Everything is ok cancel clearing if it was running as other BR is removed
00673             this->br_delete_timer = 0;
00674         }
00675     }
00676 
00677     if (this->br_delete_timer) {
00678         if (this->br_delete_timer > seconds) {
00679             this->br_delete_timer -= seconds;
00680         } else {
00681             // Delete timer was set and we need to remove our subscription.
00682             thread_bbr_network_data_remove(this);
00683             thread_border_router_publish(this->interface_id);
00684             this->br_delete_timer = 0;
00685         }
00686     } else {
00687         // Check states when we need to remove our BR from network
00688         if (this->br_hosted && this->br_count > 1) {
00689             // Race condition More border routers than there should trigger random delay to remove BR
00690             // our implementation prefers lowest RLOC to to stay to reduce problem time
00691             if (br_lowest_host) {
00692                 this->br_delete_timer = randLIB_get_random_in_range(20,60);
00693             } else {
00694                 this->br_delete_timer = randLIB_get_random_in_range(5,10);
00695             }
00696             tr_info("br: too many BRs start remove jitter:%"PRIu32, this->br_delete_timer);
00697             return;
00698         }
00699         if (this->br_info_published && !bbr_prefix_ptr ) {
00700             // Need to disable ND proxy will give a 20 second delay for it We could also disable routing immediately
00701             this->br_delete_timer = 20;
00702             tr_info("br: can not be border router need to remove after: %"PRIu32, this->br_delete_timer);
00703             return;
00704         }
00705     }
00706 }
00707 
00708 static bool thread_bbr_activated(thread_bbr_t *this, uint32_t seconds)
00709 {
00710     protocol_interface_info_entry_t *cur;
00711 
00712     if (this->backbone_interface_id < 0) {
00713         return false;
00714     }
00715 
00716     cur = protocol_stack_interface_info_get_by_id(this->interface_id);
00717 
00718     if (!cur || !cur->thread_info) {
00719         return false;
00720     }
00721     // Check if we are router If we are not router upgrade to router.
00722     // If upgrade fails then start as child router because network is full
00723     if (thread_am_router(cur)) {
00724         return true;
00725     }
00726 
00727     if (cur->thread_info->routerIdReqCoapID) {
00728         // Router id reguest pending we need to wait for response
00729         return false;
00730     }
00731     if(this->router_upgrade_delay_timer) {
00732         if (this->router_upgrade_delay_timer > seconds) {
00733             this->router_upgrade_delay_timer -= seconds;
00734         } else {
00735             this->router_upgrade_delay_timer = 0;
00736         }
00737         // Delay timer running no actions can be made, so we will become router as child
00738         return true;
00739     }
00740     // We will try to become router. This is done only in 120 seconds intervals if failed
00741     thread_router_bootstrap_router_id_request(cur, 0);
00742     this->router_upgrade_delay_timer = 120;
00743     return false;
00744 }
00745 
00746 bool thread_bbr_routing_enabled(protocol_interface_info_entry_t *cur)
00747 {
00748     thread_bbr_t *this = thread_bbr_find_by_interface(cur->thread_info->interface_id);
00749 
00750     if (!this) {
00751         return false;
00752     }
00753     return this->routing_enabled;
00754 }
00755 
00756 void thread_bbr_network_data_update_notify(protocol_interface_info_entry_t *cur)
00757 {
00758     (void) cur;
00759     thread_mdns_network_data_update_notify();
00760 }
00761 #endif /* HAVE_THREAD_BORDER_ROUTER*/
00762 
00763 static void thread_bbr_udp_proxy_service_stop(int8_t interface_id)
00764 {
00765     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00766 
00767     if (!this) {
00768         tr_error("Failed to find BA instance");
00769         return;
00770     }
00771 
00772     socket_close(this->udp_proxy_socket);
00773     this->udp_proxy_socket = -1;
00774 }
00775 
00776 int thread_bbr_commissioner_proxy_service_update(int8_t interface_id)
00777 {
00778     protocol_interface_info_entry_t *cur;
00779     ns_address_t ns_source_addr;
00780     int ret_val;
00781 
00782     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00783     cur = protocol_stack_interface_info_get_by_id(interface_id);
00784 
00785     if (!this || !cur) {
00786         tr_error("Failed to find BBR instance");
00787         ret_val = -1;
00788         goto return_fail;
00789     }
00790 
00791     if (!cur->thread_info->registered_commissioner.commissioner_valid) {
00792         // commissioner not enabled
00793         if (this->udp_proxy_socket != -1) {
00794             thread_bbr_udp_proxy_service_stop(interface_id);
00795         }
00796         return 0;
00797     }
00798 
00799     if (this->udp_proxy_socket != -1) {
00800         // commissioner is valid and UDP service is already running
00801         return 0;
00802     }
00803 
00804     // Set source parameters, if commissioner is available
00805     ret_val = thread_management_get_commissioner_address(this->interface_id, &ns_source_addr.address[0], 0);
00806     if ( ret_val < 0) {
00807         tr_error("Failed to get commissioner ALOC %d", ret_val);
00808         ret_val = -1;
00809         goto return_fail;
00810     }
00811 
00812     this->udp_proxy_socket = socket_open(SOCKET_UDP, 0, thread_border_router_udp_proxy_socket_recv_callback);
00813     if (this->udp_proxy_socket < 0) {
00814         tr_error("socket allocation failed!");
00815         ret_val = -2;
00816         goto return_fail;
00817     }
00818 
00819     /* register to handle UDP_TX.nft */
00820     coap_service_register_uri(this->br_service_id, THREAD_URI_UDP_TRANSMIT_NOTIFICATION, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_router_udp_proxy_transmit_cb);
00821 
00822     return 0;
00823 
00824     return_fail:
00825         thread_bbr_udp_proxy_service_stop(interface_id);
00826         return ret_val;
00827 }
00828 int8_t thread_bbr_init(int8_t interface_id, uint16_t external_commisssioner_port)
00829 {
00830     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00831     if (this) {
00832         return 0;
00833     }
00834 
00835     tr_debug("thread_border_router_init if=%d", interface_id);
00836 
00837     this = ns_dyn_mem_alloc(sizeof(thread_bbr_t));
00838     if (!this) {
00839         return -2;
00840     }
00841     this->commissioner_pet_request_msg_id = 0;
00842     this->commissioner_connected = false;
00843     this->commissioner_port = 0;
00844     this->interface_id = interface_id;
00845     this->udp_proxy_socket = -1;
00846     this->commissioner_timer = 0;
00847     this->backbone_interface_id = -1;
00848     this->br_delay_timer = 0;
00849     this->router_upgrade_delay_timer = 0;
00850     this->br_delete_timer = 0;
00851     this->br_info_published = false;
00852     this->routing_enabled = false;
00853 
00854     memset(this->bbr_prefix,0,8);
00855     this->joiner_router_rloc = 0xffff;
00856     this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
00857     if (this->coap_service_id < 0) {
00858         tr_warn("Thread border router coap init failed");
00859         ns_dyn_mem_free(this);
00860         return -3;
00861     }
00862 
00863     this->br_service_id = coap_service_initialize(this->interface_id, external_commisssioner_port, COAP_SERVICE_OPTIONS_SECURE | COAP_SERVICE_OPTIONS_SECURE_BYPASS, br_commissioner_security_start_cb, br_commissioner_security_done_cb);
00864     //TODO this needs secure bypass option HACK made
00865     if (this->br_service_id < 0) {
00866         tr_warn("Thread border router br-service init failed");
00867         coap_service_delete(this->coap_service_id);
00868         ns_dyn_mem_free(this);
00869         return -4;
00870     }
00871 
00872     // Border Agent handles MGMT_GET, MGMT_ACTIVE_GET, and MGMT_PENDING_GET directly
00873     coap_service_register_uri(this->br_service_id, THREAD_URI_MANAGEMENT_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_agent_tmf_get_request_cb);
00874     coap_service_register_uri(this->br_service_id, THREAD_URI_ACTIVE_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_agent_tmf_get_request_cb);
00875     coap_service_register_uri(this->br_service_id, THREAD_URI_PENDING_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_agent_tmf_get_request_cb);
00876 
00877     // TODO, these URI's should be available in BA, if they are asked from BA by Native/External commissioner */
00878     /*
00879     coap_service_register_uri(this->br_service_id, THREAD_URI_ACTIVE_SET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_relay_to_leader_cb);
00880     coap_service_register_uri(this->br_service_id, THREAD_URI_PENDING_SET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_relay_to_leader_cb);
00881     */
00882 
00883     // Border router URIs for native and external commissioner
00884     coap_service_register_uri(this->br_service_id, THREAD_URI_RELAY_TRANSMIT, COAP_SERVICE_ACCESS_POST_ALLOWED, thread_border_router_relay_transmit_cb);
00885     coap_service_register_uri(this->br_service_id, THREAD_URI_COMMISSIONER_PETITION, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_petition_to_leader_cb);
00886     coap_service_register_uri(this->br_service_id, THREAD_URI_COMMISSIONER_KEEP_ALIVE, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_petition_to_leader_cb);
00887 
00888     // These messages should not be forwarded according to new specification
00889     coap_service_register_uri(this->br_service_id, THREAD_URI_COMMISSIONER_SET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_relay_to_leader_cb);
00890     coap_service_register_uri(this->br_service_id, THREAD_URI_COMMISSIONER_GET, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_relay_to_leader_cb);
00891 
00892     ns_list_add_to_start(&bbr_instance_list, this);
00893     return 0;
00894 }
00895 
00896 void thread_bbr_delete(int8_t interface_id)
00897 {
00898     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00899     if (!this) {
00900         return;
00901     }
00902 
00903     thread_bbr_stop(interface_id);
00904     coap_service_delete(this->coap_service_id);
00905     coap_service_delete(this->br_service_id);
00906 
00907     ns_list_remove(&bbr_instance_list, this);
00908     ns_dyn_mem_free(this);
00909 }
00910 
00911 void thread_bbr_seconds_timer(int8_t interface_id, uint32_t seconds)
00912 {
00913     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00914     if (!this) {
00915         return;
00916     }
00917 
00918     if (this->commissioner_timer) {
00919         if (this->commissioner_timer > seconds) {
00920             this->commissioner_timer -= seconds;
00921         } else {
00922             //Clear commissioner session from the border router
00923             tr_info("Timing out the commissioner");
00924             thread_border_router_commissioner_info_clear(this);
00925         }
00926     }
00927 
00928 #ifdef HAVE_THREAD_BORDER_ROUTER
00929 
00930     // check if Border router can be active
00931     if (thread_bbr_activated(this,seconds)) {
00932         // Run the BBR SM
00933         thread_bbr_status_check(this,seconds);
00934     }
00935 
00936     if (!thread_extension_version_check(thread_version)) {
00937         return;
00938     }
00939     thread_extension_bbr_seconds_timer(interface_id, seconds);
00940 
00941 #endif
00942 }
00943 #endif // HAVE_THREAD_ROUTER
00944 
00945 #ifdef HAVE_THREAD_BORDER_ROUTER
00946 static int thread_bbr_na_send(int8_t interface_id, const uint8_t target[static 16])
00947 {
00948     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00949     if (!cur) {
00950         return -1;
00951     }
00952 
00953     buffer_t *buffer = icmpv6_build_na(cur, false, true, true, target, NULL, ADDR_UNSPECIFIED);
00954     protocol_push(buffer);
00955     return 0;
00956 
00957 }
00958 int thread_bbr_nd_entry_add (int8_t interface_id, const uint8_t *addr_data_ptr,  uint32_t lifetime, void *info, const uint8_t *mleid_ptr) {
00959     (void) mleid_ptr;
00960     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
00961     if (!this || this->backbone_interface_id < 0) {
00962         tr_err("bbr not ready");
00963         return -1;
00964     }
00965     ipv6_route_t *route = ipv6_route_add_with_info(addr_data_ptr, 128, interface_id, NULL, ROUTE_THREAD_PROXIED_HOST, info, 0, lifetime, 0);
00966     // We are using route info field to store sequence number
00967     if (!route) {
00968         // Direct route to host allows ND proxying to work
00969         tr_err("out of resources");
00970         return -2;
00971     }
00972     // send NA
00973     thread_bbr_na_send(this->backbone_interface_id, addr_data_ptr);
00974 
00975     return 0;
00976 }
00977 
00978 int thread_bbr_nd_entry_find(int8_t interface_id, const uint8_t *addr_data_ptr) {
00979     ipv6_route_t *route = ipv6_route_choose_next_hop(addr_data_ptr, interface_id, NULL);
00980     if (!route || route->prefix_len < 128 || !route->on_link || route->info.source != ROUTE_THREAD_PROXIED_HOST ) {
00981         //Not found
00982         return -1;
00983     }
00984     //TODO get information to route to parameters eq mleid, timeout
00985     return 0;
00986 }
00987 
00988 int thread_bbr_proxy_state_update(int8_t caller_interface_id , int8_t handler_interface_id, bool status)
00989 {
00990     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(handler_interface_id);
00991     (void) caller_interface_id;
00992     if (!cur) {
00993         tr_error("No Interface");
00994         return -1;
00995     }
00996     // Route prefix is variable-length, so need to zero pad for ip6tos
00997     bool weHostServiceAlso = false;
00998     bool validToLearOnMeshRoute;
00999     uint16_t routerId;
01000     routerId = cur->mac_parameters->mac_short_address;
01001     thread_network_data_cache_entry_t *networkData;
01002     networkData = &cur->thread_info->networkDataStorage;
01003     validToLearOnMeshRoute = thread_on_mesh_route_possible_add(cur->thread_info->thread_device_mode);
01004 
01005     tr_debug("Proxy update");
01006 
01007     ns_list_foreach(thread_network_data_prefix_cache_entry_t, curPrefix, &networkData->localPrefixList ) {
01008 
01009         weHostServiceAlso = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->routeList);
01010 
01011         if (weHostServiceAlso) {
01012             ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD, 0xffffffff, 0);
01013         }
01014 
01015         weHostServiceAlso = thread_nd_hosted_by_this_routerid(routerId, &curPrefix->borderRouterList);
01016 
01017         ns_list_foreach(thread_network_server_data_entry_t, curRoute, &curPrefix->borderRouterList) {
01018             if (thread_nd_on_mesh_address_valid(curRoute)) {
01019                 if (validToLearOnMeshRoute) {
01020                     if (curRoute->P_dhcp && weHostServiceAlso) {
01021                         if (status) {
01022                             ipv6_route_delete(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD);
01023                         } else {
01024                             ipv6_route_add(curPrefix->servicesPrefix, curPrefix->servicesPrefixLen, cur->id, NULL, ROUTE_THREAD, 0xffffffff, 0);
01025                         }
01026 
01027                     }
01028                 }
01029             }
01030         }
01031     }
01032     return 0;
01033 }
01034 #endif
01035 
01036 /*Public API control*/
01037 int thread_bbr_start(int8_t interface_id, int8_t backbone_interface_id)
01038 {
01039     (void) interface_id;
01040     (void) backbone_interface_id;
01041 #ifdef HAVE_THREAD_BORDER_ROUTER
01042     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
01043     link_configuration_s *link_configuration_ptr = thread_joiner_application_get_config(interface_id);
01044     uint8_t *extended_random_mac = thread_joiner_application_random_mac_get(interface_id);
01045     char service_name[30] = {0};
01046     char *ptr;
01047 
01048     if(!this || !link_configuration_ptr || backbone_interface_id < 0) {
01049         return -1;
01050     }
01051 
01052     tr_info("Thread BBR start if:%d, bb_if:%d",interface_id, backbone_interface_id);
01053 
01054     this->backbone_interface_id = backbone_interface_id;
01055     ptr = service_name;
01056     *ptr++ = 'a' + extended_random_mac[0] % 26;
01057     *ptr++ = 'a' + extended_random_mac[1] % 26;
01058     *ptr++ = 'a' + extended_random_mac[2] % 26;
01059     *ptr++ = 'a' + extended_random_mac[3] % 26;
01060     memcpy(ptr,"-ARM-",5);
01061     ptr += 5;
01062     memcpy(ptr,link_configuration_ptr->name,16);
01063 
01064     // Start mdns service
01065     thread_mdns_start(this->interface_id, this->backbone_interface_id, service_name);
01066     multicast_fwd_set_proxy_upstream(this->backbone_interface_id);
01067     multicast_fwd_full_for_scope(this->interface_id, 0);
01068     multicast_fwd_full_for_scope(this->backbone_interface_id, 0);
01069     // By default multicast forwarding is not enabled as it causes multicast loops
01070     multicast_fwd_set_forwarding(this->interface_id, false);
01071 
01072     thread_extension_bbr_init(interface_id,backbone_interface_id);
01073     return 0;
01074 #else
01075     return -1;
01076 #endif // HAVE_THREAD_BORDER_ROUTER
01077 }
01078 
01079 int thread_bbr_timeout_set(int8_t interface_id, uint32_t timeout_a, uint32_t timeout_b, uint32_t delay)
01080 {
01081     (void) interface_id;
01082     (void) timeout_a;
01083     (void) timeout_b;
01084     (void) delay;
01085 #ifdef HAVE_THREAD_BORDER_ROUTER
01086     thread_extension_bbr_timeout_set(interface_id, timeout_a, timeout_b, delay);
01087 return 0;
01088 #else
01089     return -1;
01090 #endif // HAVE_THREAD_BORDER_ROUTER
01091 }
01092 
01093 int thread_bbr_validation_interface_address_set(int8_t interface_id, const uint8_t *addr_ptr, uint16_t port)
01094 {
01095     (void) interface_id;
01096     (void) addr_ptr;
01097     (void) port;
01098 #ifdef HAVE_THREAD_BORDER_ROUTER
01099     return thread_extension_bbr_address_set(interface_id, addr_ptr, port);
01100 #else
01101     return -1;
01102 #endif // HAVE_THREAD_BORDER_ROUTER
01103 }
01104 
01105 
01106 
01107 void thread_bbr_stop(int8_t interface_id)
01108 {
01109     (void) interface_id;
01110 #ifdef HAVE_THREAD_BORDER_ROUTER
01111 
01112     thread_bbr_t *this = thread_bbr_find_by_interface(interface_id);
01113 
01114     if(!this) {
01115         return;
01116     }
01117     thread_extension_bbr_delete(interface_id);
01118     thread_bbr_network_data_remove(this);
01119     thread_bbr_routing_disable(this);
01120     thread_border_router_publish(interface_id);
01121     thread_mdns_stop();
01122     this->backbone_interface_id = -1;
01123 
01124 #else
01125     return;
01126 #endif // HAVE_THREAD_BORDER_ROUTER
01127 
01128 }