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.
Fork of OmniWheels by
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 Fri Jul 22 2022 04:54:02 by
1.7.2
