Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
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 }
Generated on Tue Jul 12 2022 13:03:20 by
