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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 }
Generated on Tue Jul 12 2022 13:54:57 by
