Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_bbr_api.c Source File

thread_bbr_api.c

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