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