EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

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