Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
thread_border_router_api.c
00001 /* 00002 * Copyright (c) 2014-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 #include <string.h> 00032 #include "ns_types.h" 00033 #include <nsdynmemLIB.h> 00034 #include "eventOS_event.h" 00035 #include <ns_list.h> 00036 #include "ns_trace.h" 00037 #include "Core/include/ns_buffer.h" 00038 #include "common_functions.h" 00039 #include "randLIB.h" 00040 #include "thread_border_router_api.h" 00041 #include "thread_management_if.h" 00042 #include "NWK_INTERFACE/Include/protocol.h" 00043 #include "6LoWPAN/Thread/thread_config.h" 00044 #include "6LoWPAN/Thread/thread_common.h" 00045 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00046 #include "6LoWPAN/Thread/thread_network_data_storage.h" 00047 #include "6LoWPAN/Thread/thread_management_client.h" 00048 #include "6LoWPAN/Thread/thread_joiner_application.h" 00049 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00050 #include "6LoWPAN/Thread/thread_border_router_api_internal.h" 00051 #include "6LoWPAN/Thread/thread_mdns.h" 00052 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" 00053 #include "6LoWPAN/MAC/mac_helper.h" 00054 #include "MLE/mle.h" 00055 #include "thread_meshcop_lib.h" 00056 #include "thread_network_data_lib.h" 00057 #include "coap_service_api.h" 00058 00059 #define TRACE_GROUP "tBRa" 00060 00061 #ifdef HAVE_THREAD_ROUTER 00062 /* 00063 * Structure containing IPv6 Router advertisement options for DNS configuration. 00064 */ 00065 typedef struct { 00066 uint16_t option_length; 00067 uint8_t *option_data; 00068 } dns_option_t; 00069 00070 /* 00071 * Border router instance data. 00072 */ 00073 typedef struct { 00074 dns_option_t *dns_search_list_option; /* option_data encoded according to RFC6106, DNSSL */ 00075 dns_option_t *recursive_dns_server_option; /* option_data encoded according to RFC6106, RDNSS */ 00076 uint16_t nwk_data_resubmit_timer; /* network data resubmit timeout */ 00077 int8_t interface_id; 00078 int8_t coap_service_id; 00079 ns_list_link_t link; 00080 } thread_border_router_t; 00081 00082 /* Neighbor discovery options according to RFC6106 (rfc4861) */ 00083 #define RFC6106_RECURSIVE_DNS_SERVER_OPTION 25 00084 #define RFC6106_DNS_SEARCH_LIST_OPTION 31 00085 static NS_LIST_DEFINE(border_router_instance_list, thread_border_router_t, link); 00086 00087 00088 static thread_border_router_t *thread_border_router_find_by_interface(int8_t interface_id) 00089 { 00090 thread_border_router_t *this = NULL; 00091 ns_list_foreach(thread_border_router_t, cur_br, &border_router_instance_list) { 00092 if (cur_br->interface_id == interface_id) { 00093 this = cur_br; 00094 break; 00095 } 00096 } 00097 return this; 00098 } 00099 00100 static thread_border_router_t *thread_border_router_find_by_service(int8_t service_id) 00101 { 00102 thread_border_router_t *this = NULL; 00103 ns_list_foreach(thread_border_router_t, cur_br, &border_router_instance_list) { 00104 if (cur_br->coap_service_id == service_id) { 00105 this = cur_br; 00106 break; 00107 } 00108 } 00109 return this; 00110 } 00111 00112 /* 00113 * Read Border Router TLV: DNS search list option. 00114 * DNSSL option data will be fetched from: 00115 * 1. User has provided static configuration by using method thread_border_router_dns_search_list_option_set. 00116 * 2. ICMP RA messages (if service is enabled and running in background). 00117 */ 00118 static uint8_t *thread_management_server_border_router_nd_dnssl_option_read(thread_border_router_t *this, uint16_t *resp_len) 00119 { 00120 if (this->dns_search_list_option) { 00121 *resp_len = this->dns_search_list_option->option_length; 00122 return (uint8_t*)&this->dns_search_list_option->option_data; 00123 } else { 00124 // TODO: Read DNSSL from stored ICMP RA messages. 00125 *resp_len = 0; 00126 return NULL; 00127 } 00128 } 00129 00130 /* 00131 * Read Border Router TLV: Recursive DNS Server option. 00132 * RDNSS option data will be fetched from: 00133 * 1. User has provided static configuration by using method thread_border_router_recursive_dns_server_option_set. 00134 * 2. ICMP RA messages (if service is enabled and running in background). 00135 */ 00136 static uint8_t *thread_management_server_border_router_nd_rdnss_option_read(thread_border_router_t *this, uint16_t *resp_len) 00137 { 00138 if (this->recursive_dns_server_option) { 00139 *resp_len = this->recursive_dns_server_option->option_length; 00140 return (uint8_t*)&this->recursive_dns_server_option->option_data; 00141 } else { 00142 // TODO: Read RDNSS from stored ICMP RA messages. 00143 *resp_len = 0; 00144 return NULL; 00145 } 00146 } 00147 00148 /** 00149 * Thread Neighbor discovery data request handler 00150 */ 00151 static int thread_border_router_neighbor_discovery_data_req_cb(int8_t service_id, uint8_t source_address[16], uint16_t source_port, sn_coap_hdr_s *request_ptr) 00152 { 00153 thread_border_router_t *this = thread_border_router_find_by_service(service_id); 00154 uint8_t *request_tlv_ptr; 00155 uint8_t *resp_payload_ptr; 00156 uint16_t options_len, rdnss_option_len, dnssl_option_len, payload_len; 00157 uint8_t options_data[4]; 00158 uint8_t *dns_server_tlv_ptr = NULL; 00159 uint8_t *dns_search_list_tlv_ptr = NULL; 00160 uint8_t *ptr; 00161 sn_coap_msg_code_e return_code = COAP_MSG_CODE_RESPONSE_CHANGED; 00162 (void) source_port; 00163 (void) source_address; 00164 00165 tr_debug("neighbor data request"); 00166 00167 if (!this) { 00168 return -1; 00169 } 00170 00171 request_tlv_ptr = options_data; 00172 rdnss_option_len = dnssl_option_len = 0; 00173 00174 options_len = thread_tmfcop_tlv_find(request_ptr->payload_ptr, request_ptr->payload_len, TMFCOP_TLV_ND_OPTION, &request_tlv_ptr); 00175 00176 while (options_len > 0) { 00177 switch (*request_tlv_ptr) { 00178 case RFC6106_RECURSIVE_DNS_SERVER_OPTION: 00179 dns_server_tlv_ptr = thread_management_server_border_router_nd_rdnss_option_read(this, &rdnss_option_len); 00180 break; 00181 case RFC6106_DNS_SEARCH_LIST_OPTION: 00182 dns_search_list_tlv_ptr = thread_management_server_border_router_nd_dnssl_option_read(this, &dnssl_option_len); 00183 break; 00184 } 00185 request_tlv_ptr++; 00186 options_len--; 00187 } 00188 00189 payload_len = rdnss_option_len + dnssl_option_len; 00190 00191 resp_payload_ptr = ptr = ns_dyn_mem_alloc(payload_len + 4); //reserve space also for type/length 00192 if (!resp_payload_ptr) { 00193 return_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00194 goto send_response; 00195 } 00196 00197 *ptr++ = TMFCOP_TLV_ND_DATA; 00198 if (payload_len > 255) { 00199 *ptr++ = 0xff; 00200 ptr = common_write_16_bit(payload_len, ptr); 00201 } else { 00202 *ptr++ = payload_len; 00203 } 00204 00205 if (dns_server_tlv_ptr) { 00206 memcpy(ptr, dns_server_tlv_ptr, rdnss_option_len); 00207 ptr += rdnss_option_len; 00208 } 00209 00210 if (dns_search_list_tlv_ptr) { 00211 memcpy(ptr, dns_search_list_tlv_ptr, dnssl_option_len); 00212 ptr += dnssl_option_len; 00213 } 00214 00215 send_response: 00216 coap_service_response_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, request_ptr, return_code, COAP_CT_OCTET_STREAM, resp_payload_ptr, ptr-resp_payload_ptr); 00217 ns_dyn_mem_free(resp_payload_ptr); 00218 return 0; 00219 } 00220 /* 00221 * Check that local prefix is available in received network data 00222 */ 00223 static bool thread_border_router_network_data_prefix_match(thread_network_data_cache_entry_t *network_data_ptr, thread_network_local_data_entry_t *local_prefix, uint16_t router_id) 00224 { 00225 ns_list_foreach(thread_network_data_prefix_cache_entry_t, nwk_prefix, &network_data_ptr->localPrefixList ) { 00226 if (nwk_prefix->servicesPrefixLen != local_prefix->servicesPrefixLen) { 00227 continue; 00228 } 00229 00230 if (!bitsequal(nwk_prefix->servicesPrefix, local_prefix->servicesPrefix, local_prefix->servicesPrefixLen)) { 00231 continue; 00232 } 00233 00234 // check that prefix is hosted by this router 00235 if (!thread_nd_hosted_by_this_routerid(router_id, &nwk_prefix->routeList) && 00236 !thread_nd_hosted_by_this_routerid(router_id, &nwk_prefix->borderRouterList)) { 00237 return false; 00238 } 00239 00240 return true; 00241 } 00242 00243 return false; 00244 } 00245 00246 /* 00247 * Check that local service is available in network data 00248 */ 00249 static bool thread_border_router_network_data_service_match(thread_network_data_cache_entry_t *network_data_ptr, thread_network_data_service_entry_t *local_service, uint16_t router_id) 00250 { 00251 thread_network_data_service_cache_entry_t *service_cache_entry = thread_network_data_service_entry_find(&network_data_ptr->service_list, local_service); 00252 00253 if (service_cache_entry) { 00254 return thread_network_data_service_hosted_by_this_router_id(service_cache_entry, router_id); 00255 } 00256 00257 return false; 00258 } 00259 00260 static bool thread_border_router_local_network_data_prefix_match(thread_network_local_data_cache_entry_t *local_data, thread_network_data_prefix_cache_entry_t *prefix, uint16_t router_id) 00261 { 00262 bool instance_found = false; 00263 00264 if (thread_nd_hosted_by_this_routerid(router_id, &prefix->routeList)) { 00265 instance_found = true; 00266 } 00267 00268 if (thread_nd_hosted_by_this_routerid(router_id, &prefix->borderRouterList)) { 00269 instance_found = true; 00270 } 00271 00272 if (!instance_found) { 00273 /* Router ID not in propagated network data; skip */ 00274 return true; 00275 } 00276 00277 instance_found = false; 00278 00279 ns_list_foreach(thread_network_local_data_entry_t, localPrefix, &local_data->prefix_list) { 00280 if (prefix->servicesPrefixLen != localPrefix->servicesPrefixLen) { 00281 continue; 00282 } 00283 00284 if (bitsequal(prefix->servicesPrefix , localPrefix->servicesPrefix, localPrefix->servicesPrefixLen)) { 00285 /* Prefix exists in local data; return true */ 00286 instance_found = true; 00287 break; 00288 } 00289 } 00290 00291 if (!instance_found) { 00292 tr_debug("Found missing prefix: %s", trace_array(prefix->servicesPrefix , 8)); 00293 return false; 00294 } 00295 00296 return true; 00297 } 00298 00299 static bool thread_border_router_local_network_data_service_match(thread_network_local_data_cache_entry_t *local_data, thread_network_data_service_cache_entry_t *service, uint16_t router_id) 00300 { 00301 bool instance_found = false; 00302 00303 ns_list_foreach(thread_network_data_service_server_entry_t, server, &service->server_list) { 00304 if (server->router_id == router_id) { 00305 instance_found = true; 00306 break; 00307 } 00308 } 00309 00310 if (!instance_found) { 00311 /* Router ID not in propagated network data; skip */ 00312 return true; 00313 } 00314 00315 ns_list_foreach(thread_network_data_service_entry_t, local_service, &local_data->service_list) { 00316 if (local_service->S_service_data_length != service->S_service_data_length) { 00317 continue; 00318 } 00319 00320 if (memcmp(local_service->S_service_data, service->S_service_data, local_service->S_service_data_length) != 0) { 00321 continue; 00322 } 00323 00324 if (local_service->S_enterprise_number != service->S_enterprise_number) { 00325 continue; 00326 } 00327 00328 /* Service exists in local data; return true */ 00329 return true; 00330 } 00331 00332 tr_debug("Found missing service: %s", trace_array(service->S_service_data, service->S_service_data_length)); 00333 return false; 00334 } 00335 00336 /* 00337 * Check that local server data is available in network data 00338 */ 00339 static bool thread_border_router_local_srv_data_in_network_data_check(protocol_interface_info_entry_t *cur) 00340 { 00341 thread_network_data_cache_entry_t *network_data; 00342 thread_network_local_data_cache_entry_t *local_data; 00343 uint16_t router_id = cur->mac_parameters->mac_short_address; 00344 00345 network_data = &cur->thread_info->networkDataStorage; 00346 local_data = &cur->thread_info->localServerDataBase; 00347 00348 ns_list_foreach(thread_network_local_data_entry_t, localPrefix, &local_data->prefix_list) { 00349 // find matching prefix from network data 00350 if (thread_border_router_network_data_prefix_match(network_data, localPrefix, router_id) == false) { 00351 return false; 00352 } 00353 } 00354 00355 ns_list_foreach(thread_network_data_service_entry_t, localService, &local_data->service_list) { 00356 // find matching service from network data 00357 if (thread_border_router_network_data_service_match(network_data, localService, router_id) == false) { 00358 return false; 00359 } 00360 } 00361 00362 ns_list_foreach(thread_network_data_prefix_cache_entry_t, prefix, &network_data->localPrefixList ) { 00363 if (thread_border_router_local_network_data_prefix_match(local_data, prefix, router_id) == false) { 00364 return false; 00365 } 00366 } 00367 00368 ns_list_foreach(thread_network_data_service_cache_entry_t, service, &network_data->service_list) { 00369 if (thread_border_router_local_network_data_service_match(local_data, service, router_id) == false) { 00370 return false; 00371 } 00372 } 00373 00374 return true; 00375 } 00376 00377 static int thread_border_router_recursive_dns_server_option_store(int8_t interface_id, uint8_t *recursive_dns_server_option, uint16_t recursive_dns_server_option_len) 00378 { 00379 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00380 if (!this) { 00381 return -1; 00382 } 00383 00384 ns_dyn_mem_free(this->recursive_dns_server_option); 00385 00386 if (recursive_dns_server_option) { 00387 this->recursive_dns_server_option = ns_dyn_mem_alloc(sizeof(dns_option_t) + recursive_dns_server_option_len); 00388 if (!this->recursive_dns_server_option) { 00389 return -2; 00390 } 00391 memcpy(&this->recursive_dns_server_option->option_data, recursive_dns_server_option, recursive_dns_server_option_len); 00392 this->recursive_dns_server_option->option_length = recursive_dns_server_option_len; 00393 } 00394 return 0; 00395 } 00396 00397 static int thread_border_router_dns_search_list_option_store(int8_t interface_id, uint8_t *dns_search_list_option, uint16_t search_list_option_len) 00398 { 00399 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00400 if (!this) { 00401 return -1; 00402 } 00403 00404 ns_dyn_mem_free(this->dns_search_list_option); 00405 if (dns_search_list_option) { 00406 this->dns_search_list_option = ns_dyn_mem_alloc(sizeof(dns_option_t) + search_list_option_len); 00407 if (!this->dns_search_list_option) { 00408 return -2; 00409 } 00410 memcpy(&this->dns_search_list_option->option_data, dns_search_list_option, search_list_option_len); 00411 this->dns_search_list_option->option_length = search_list_option_len; 00412 } 00413 return 0; 00414 } 00415 00416 int8_t thread_border_router_init(int8_t interface_id) 00417 { 00418 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00419 if (this) { 00420 return 0; 00421 } 00422 00423 tr_debug("thread_border_router_init if=%d", interface_id); 00424 00425 this = ns_dyn_mem_alloc(sizeof(thread_border_router_t)); 00426 if (!this) { 00427 return -2; 00428 } 00429 this->dns_search_list_option = NULL; 00430 this->recursive_dns_server_option = NULL; 00431 this->interface_id = interface_id; 00432 this->nwk_data_resubmit_timer = 0; 00433 this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL); 00434 if (this->coap_service_id < 0) { 00435 tr_warn("Thread border router coap init failed"); 00436 ns_dyn_mem_free(this); 00437 return -3; 00438 } 00439 // Register to Mesh CoAP URIs 00440 coap_service_register_uri(this->coap_service_id, THREAD_URI_NEIGHBOR_DISCOVERY_DATA_REQ, COAP_SERVICE_ACCESS_GET_ALLOWED, thread_border_router_neighbor_discovery_data_req_cb); 00441 00442 ns_list_add_to_start(&border_router_instance_list, this); 00443 return 0; 00444 } 00445 00446 void thread_border_router_delete(int8_t interface_id) 00447 { 00448 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00449 if (!this) { 00450 return; 00451 } 00452 00453 coap_service_delete(this->coap_service_id); 00454 00455 ns_list_remove(&border_router_instance_list, this); 00456 ns_dyn_mem_free(this->dns_search_list_option); 00457 ns_dyn_mem_free(this->recursive_dns_server_option); 00458 ns_dyn_mem_free(this); 00459 } 00460 void thread_border_router_seconds_timer(int8_t interface_id, uint32_t seconds) 00461 { 00462 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00463 if (!this) { 00464 return; 00465 } 00466 00467 if (this->nwk_data_resubmit_timer) { 00468 if (this->nwk_data_resubmit_timer > seconds) { 00469 this->nwk_data_resubmit_timer -= seconds; 00470 } else { 00471 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00472 this->nwk_data_resubmit_timer = 0; 00473 if (cur) { 00474 if (!thread_border_router_local_srv_data_in_network_data_check(cur)) { 00475 tr_info("nwk data mismatch - resubmit"); 00476 thread_border_router_publish(cur->id); 00477 } 00478 } 00479 } 00480 } 00481 } 00482 00483 void thread_border_router_resubmit_timer_set(int8_t interface_id, int16_t seconds) 00484 { 00485 thread_border_router_t *this = thread_border_router_find_by_interface(interface_id); 00486 00487 if (!this) { 00488 return; 00489 } 00490 00491 if (seconds >= 0) { 00492 this->nwk_data_resubmit_timer = seconds; 00493 } else { 00494 // re-init network data resubmit timer to default value 00495 this->nwk_data_resubmit_timer = THREAD_DATA_RESUBMIT_DELAY + randLIB_get_random_in_range(0, THREAD_DATA_RESUBMIT_DELAY/10); 00496 } 00497 } 00498 00499 void thread_border_router_network_data_appl_callback(protocol_interface_info_entry_t *cur) 00500 { 00501 if (cur->thread_info->network_data_tlv_cb) { 00502 uint16_t payload_len = thread_network_data_tlv_size(cur, true); 00503 uint8_t *payload_ptr = ns_dyn_mem_alloc(payload_len + 3); /* 3 => room is also needed for TLV ID and length */ 00504 if (payload_ptr) { 00505 thread_network_data_tlv_write(cur, payload_ptr, true); 00506 // Send Network data TLV to application without TLV ID and length 00507 cur->thread_info->network_data_tlv_cb(cur->thread_info->interface_id, payload_ptr + 2, payload_len); 00508 ns_dyn_mem_free(payload_ptr); 00509 } 00510 } 00511 } 00512 00513 void thread_border_router_network_data_update_notify(protocol_interface_info_entry_t *cur) 00514 { 00515 thread_border_router_t *this = thread_border_router_find_by_interface(cur->thread_info->interface_id); 00516 00517 if (!this) { 00518 return; 00519 } 00520 if (!thread_border_router_local_srv_data_in_network_data_check(cur)) { 00521 if (this->nwk_data_resubmit_timer == 0) { 00522 this->nwk_data_resubmit_timer = 5; 00523 tr_debug("Resubmitted timer trig"); 00524 } 00525 00526 } else { 00527 tr_debug("All data registered"); 00528 this->nwk_data_resubmit_timer = 0; 00529 } 00530 00531 thread_border_router_network_data_appl_callback(cur); 00532 } 00533 #endif // HAVE_THREAD_ROUTER 00534 00535 /*External APIs*/ 00536 00537 int thread_border_router_prefix_add(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len, thread_border_router_info_t *prefix_info_ptr) 00538 { 00539 #ifdef HAVE_THREAD_ROUTER 00540 protocol_interface_info_entry_t *cur; 00541 thread_prefix_tlv_t prefixTlv; 00542 thread_border_router_tlv_entry_t service; 00543 cur = protocol_stack_interface_info_get_by_id(interface_id); 00544 if (!cur || !cur->thread_info || thread_attach_ready(cur) != 0) { 00545 return -1; 00546 } 00547 00548 if (!prefix_info_ptr || !prefix_ptr) { 00549 return -2; 00550 } 00551 if(prefix_info_ptr->P_dhcp == true && prefix_info_ptr->P_slaac == true) { 00552 return -3;// Can not configure both services on 00553 } 00554 00555 prefixTlv.domainId = 0; 00556 prefixTlv.Prefix = prefix_ptr; 00557 prefixTlv.PrefixLen = prefix_len; 00558 00559 service.P_configure = prefix_info_ptr->P_configure; 00560 service.P_default_route = prefix_info_ptr->P_default_route; 00561 service.P_dhcp = prefix_info_ptr->P_dhcp; 00562 service.P_preferred = prefix_info_ptr->P_preferred; 00563 service.P_slaac = prefix_info_ptr->P_slaac; 00564 service.Prf = prefix_info_ptr->Prf; 00565 service.stableData = prefix_info_ptr->stableData; 00566 service.P_on_mesh = prefix_info_ptr->P_on_mesh; 00567 service.P_nd_dns = prefix_info_ptr->P_nd_dns; 00568 00569 return thread_local_server_list_add_on_mesh_server(&cur->thread_info->localServerDataBase, &prefixTlv, &service); 00570 #else 00571 (void) interface_id; 00572 (void) prefix_ptr; 00573 (void) prefix_len; 00574 (void) prefix_info_ptr; 00575 return -1; 00576 #endif 00577 } 00578 00579 int thread_border_router_prefix_delete(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len) 00580 { 00581 #ifdef HAVE_THREAD_ROUTER 00582 protocol_interface_info_entry_t *cur; 00583 thread_prefix_tlv_t prefixTlv; 00584 cur = protocol_stack_interface_info_get_by_id(interface_id); 00585 if (!cur || !cur->thread_info || thread_attach_ready(cur) != 0) { 00586 return -1; 00587 } 00588 00589 if (!prefix_ptr) { 00590 return -2; 00591 } 00592 prefixTlv.domainId = 0; 00593 prefixTlv.Prefix = prefix_ptr; 00594 prefixTlv.PrefixLen = prefix_len; 00595 00596 return thread_local_server_list_del_on_mesh_server(&cur->thread_info->localServerDataBase, &prefixTlv); 00597 #else 00598 (void) interface_id; 00599 (void) prefix_ptr; 00600 (void) prefix_len; 00601 return -1; 00602 #endif 00603 } 00604 00605 int thread_border_router_route_add(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len, bool stable, int8_t prf) 00606 { 00607 #ifdef HAVE_THREAD_ROUTER 00608 thread_prefix_tlv_t prefixTlv; 00609 thread_border_router_tlv_entry_t route; 00610 protocol_interface_info_entry_t *cur; 00611 00612 cur = protocol_stack_interface_info_get_by_id(interface_id); 00613 if (!cur) { 00614 return -1; 00615 } 00616 00617 if (!cur->thread_info || thread_attach_ready(cur) != 0) { 00618 return -2; 00619 } 00620 prefixTlv.domainId = 0; 00621 prefixTlv.Prefix = prefix_ptr; 00622 prefixTlv.PrefixLen = prefix_len; 00623 00624 memset(&route, 0, sizeof(thread_border_router_tlv_entry_t)); 00625 route.Prf = prf; 00626 route.stableData = stable; 00627 00628 return thread_local_server_add_route(&cur->thread_info->localServerDataBase, &prefixTlv, &route); 00629 #else 00630 (void) interface_id; 00631 (void) prefix_ptr; 00632 (void) prefix_len; 00633 (void) stable; 00634 (void) prf; 00635 return -1; 00636 #endif 00637 } 00638 00639 int thread_border_router_route_delete(int8_t interface_id, uint8_t *prefix_ptr, uint8_t prefix_len) 00640 { 00641 #ifdef HAVE_THREAD_ROUTER 00642 thread_prefix_tlv_t prefixTlv; 00643 protocol_interface_info_entry_t *cur; 00644 00645 cur = protocol_stack_interface_info_get_by_id(interface_id); 00646 if (!cur) { 00647 return -1; 00648 } 00649 00650 if (!cur->thread_info || thread_attach_ready(cur) != 0) { 00651 return -1; 00652 } 00653 00654 prefixTlv.domainId = 0; 00655 prefixTlv.Prefix = prefix_ptr; 00656 prefixTlv.PrefixLen = prefix_len; 00657 00658 return thread_local_server_del_route(&cur->thread_info->localServerDataBase, &prefixTlv); 00659 #else 00660 (void) interface_id; 00661 (void) prefix_ptr; 00662 (void) prefix_len; 00663 return -1; 00664 #endif 00665 00666 } 00667 00668 int thread_border_router_service_add(int8_t interface_id, uint8_t *service_data, uint8_t service_len, uint8_t sid, uint32_t enterprise_number, uint8_t *server_data, uint8_t server_data_len, bool stable) 00669 { 00670 #ifdef HAVE_THREAD_ROUTER 00671 protocol_interface_info_entry_t *cur; 00672 cur = protocol_stack_interface_info_get_by_id(interface_id); 00673 00674 if (!cur || !cur->thread_info || thread_attach_ready(cur) != 0) { 00675 return -1; 00676 } 00677 00678 if (!service_data || !service_len) { 00679 return -2; 00680 } 00681 00682 thread_network_data_service_entry_t service = { 00683 .T = false, 00684 .S_id = sid, 00685 .S_enterprise_number = enterprise_number, 00686 .S_service_data = service_data, 00687 .S_service_data_length = service_len, 00688 .S_server_data = server_data, 00689 .S_server_data_length = server_data_len, 00690 .S_stable = stable, 00691 }; 00692 00693 if (enterprise_number == THREAD_ENTERPRISE_NUMBER) { 00694 service.T = true; 00695 } 00696 00697 return thread_local_service_list_add(&cur->thread_info->localServerDataBase, &service); 00698 #else 00699 (void)interface_id; 00700 (void)service_data; 00701 (void)service_len; 00702 (void)sid; 00703 (void)enterprise_number; 00704 (void)server_data; 00705 (void)server_data_len; 00706 (void)stable; 00707 return -1; 00708 #endif 00709 } 00710 00711 int thread_border_router_service_delete(int8_t interface_id, uint8_t *service_data, uint8_t service_len, uint32_t enterprise_number) 00712 { 00713 #ifdef HAVE_THREAD_ROUTER 00714 protocol_interface_info_entry_t *cur; 00715 cur = protocol_stack_interface_info_get_by_id(interface_id); 00716 00717 if (!cur || !cur->thread_info || thread_attach_ready(cur) != 0) { 00718 return -1; 00719 } 00720 00721 if (!service_data || !service_len) { 00722 return -2; 00723 } 00724 00725 thread_network_data_service_entry_t service = { 00726 .S_enterprise_number = enterprise_number, 00727 .S_service_data = service_data, 00728 .S_service_data_length = service_len, 00729 }; 00730 00731 return thread_local_service_list_del(&cur->thread_info->localServerDataBase, &service); 00732 #else 00733 (void) interface_id; 00734 (void) service_data; 00735 (void) service_len; 00736 (void) enterprise_number; 00737 return -1; 00738 #endif 00739 } 00740 00741 int thread_border_router_recursive_dns_server_option_set(int8_t interface_id, uint8_t *recursive_dns_server_option, uint16_t recursive_dns_server_option_len) 00742 { 00743 #ifdef HAVE_THREAD_BORDER_ROUTER 00744 return thread_border_router_recursive_dns_server_option_store(interface_id, recursive_dns_server_option, recursive_dns_server_option_len); 00745 #else 00746 (void)interface_id; 00747 (void)recursive_dns_server_option; 00748 (void)recursive_dns_server_option_len; 00749 return -1; 00750 #endif 00751 } 00752 00753 int thread_border_router_dns_search_list_option_set(int8_t interface_id, uint8_t *dns_search_list_option, uint16_t search_list_option_len) 00754 { 00755 #ifdef HAVE_THREAD_BORDER_ROUTER 00756 return thread_border_router_dns_search_list_option_store(interface_id, dns_search_list_option, search_list_option_len); 00757 #else 00758 (void)interface_id; 00759 (void)dns_search_list_option; 00760 (void)search_list_option_len; 00761 return -1; 00762 #endif 00763 } 00764 00765 /** Network data set response callback. 00766 * 00767 * callback to inform if network data was set to leader. 00768 * 00769 * /param status status of operation 0 success, -1 failure from leader received 00770 * /param data_ptr pointer to network data TLV that leader accepted. 00771 * /param data_len length of network data. 00772 * 00773 */ 00774 #ifdef HAVE_THREAD_ROUTER 00775 static void thread_tmf_client_network_data_set_cb(int8_t interface_id, int8_t status, uint8_t *data_ptr, uint16_t data_len) 00776 { 00777 protocol_interface_info_entry_t *cur; 00778 (void) status; 00779 (void) data_len; 00780 (void) data_ptr; 00781 00782 cur = protocol_stack_interface_info_get_by_id(interface_id); 00783 if (!cur) { 00784 return; 00785 } 00786 // Save the old address 00787 cur->thread_info->localServerDataBase.registered_rloc16 = mac_helper_mac16_address_get(cur); 00788 cur->thread_info->localServerDataBase.release_old_address = false; 00789 cur->thread_info->localServerDataBase.publish_active = false; 00790 00791 tr_debug("border router status %s, addr: %x",status?"Fail":"Ok", cur->thread_info->localServerDataBase.registered_rloc16); 00792 00793 if (cur->thread_info->localServerDataBase.publish_pending) { 00794 cur->thread_info->localServerDataBase.publish_pending = false; 00795 thread_border_router_publish(cur->id); 00796 } 00797 } 00798 #endif 00799 00800 int thread_border_router_publish(int8_t interface_id) 00801 { 00802 #ifdef HAVE_THREAD_ROUTER 00803 uint16_t network_data_len; 00804 uint8_t *payload_ptr; 00805 uint8_t *ptr; 00806 uint16_t rloc16; 00807 int ret_val; 00808 protocol_interface_info_entry_t *cur; 00809 00810 tr_debug("Border router Publish Local Services"); 00811 cur = protocol_stack_interface_info_get_by_id(interface_id); 00812 if (!cur) { 00813 return -1; 00814 } 00815 00816 if (!cur->thread_info || thread_attach_ready(cur) != 0) { 00817 return -2; 00818 } 00819 00820 if (cur->thread_info->localServerDataBase.publish_active) { 00821 cur->thread_info->localServerDataBase.publish_pending = true; 00822 tr_debug("Activate pending status for publish"); 00823 return 0; 00824 } 00825 00826 //Allocate Memory for Data 00827 network_data_len = thread_nd_own_service_list_data_size(&cur->thread_info->localServerDataBase); 00828 00829 // Room for RLOC16 Room for Network data TLV 00830 ptr = payload_ptr = ns_dyn_mem_temporary_alloc(network_data_len + 4 + 5); 00831 if (!ptr) { 00832 return -3; 00833 } 00834 rloc16 = mac_helper_mac16_address_get(cur); 00835 00836 ptr = thread_tmfcop_tlv_data_write_header(ptr, TMFCOP_TLV_NETWORK_DATA, network_data_len); 00837 ptr = thread_nd_own_service_list_data_write(&cur->thread_info->localServerDataBase, ptr, rloc16); 00838 00839 tr_debug("Border router old: %x, new: %x", cur->thread_info->localServerDataBase.registered_rloc16, rloc16); 00840 00841 if (cur->thread_info->localServerDataBase.registered_rloc16 != 0xffff && 00842 cur->thread_info->localServerDataBase.release_old_address && 00843 cur->thread_info->localServerDataBase.registered_rloc16 != rloc16) { 00844 // Our address has changed so we must register our network with new address and remove the old address 00845 tr_debug("Border router Address changed remove old"); 00846 ptr = thread_tmfcop_tlv_data_write_uint16(ptr,TMFCOP_TLV_RLOC16,cur->thread_info->localServerDataBase.registered_rloc16); 00847 } 00848 cur->thread_info->localServerDataBase.registered_rloc16 = rloc16; 00849 ret_val = thread_management_client_network_data_register(cur->id, payload_ptr, ptr - payload_ptr, thread_tmf_client_network_data_set_cb); 00850 if (payload_ptr) { 00851 ns_dyn_mem_free(payload_ptr); 00852 } 00853 if (ret_val == 0) { 00854 cur->thread_info->localServerDataBase.publish_active = true; 00855 } 00856 00857 thread_border_router_resubmit_timer_set(interface_id, -1); 00858 00859 return ret_val; 00860 #else 00861 (void) interface_id; 00862 return -1; 00863 #endif 00864 } 00865 00866 int thread_border_router_delete_all(int8_t interface_id) 00867 { 00868 #ifdef HAVE_THREAD_ROUTER 00869 protocol_interface_info_entry_t *cur; 00870 tr_debug("Border router Delete Local Service"); 00871 cur = protocol_stack_interface_info_get_by_id(interface_id); 00872 if (!cur) { 00873 return -1; 00874 } 00875 00876 if (!cur->thread_info || thread_attach_ready(cur) != 0) { 00877 return -2; 00878 } 00879 00880 //Delete first Local List 00881 thread_network_local_data_free_and_clean(&cur->thread_info->localServerDataBase, interface_id); 00882 00883 return 0; 00884 #else 00885 (void) interface_id; 00886 return -1; 00887 #endif 00888 } 00889 00890 int thread_border_router_network_data_callback_register(int8_t interface_id, thread_network_data_tlv_cb* nwk_data_cb) 00891 { 00892 #ifdef HAVE_THREAD 00893 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00894 if (!cur) { 00895 return -1; 00896 } 00897 00898 if (!cur->thread_info || thread_attach_ready(cur) != 0) { 00899 return -2; 00900 } 00901 00902 cur->thread_info->network_data_tlv_cb = nwk_data_cb; 00903 00904 thread_border_router_network_data_appl_callback(cur); 00905 00906 return 0; 00907 #else 00908 (void)interface_id; 00909 (void)nwk_data_cb; 00910 return -1; 00911 #endif 00912 } 00913 00914 int thread_border_router_prefix_tlv_find(uint8_t* network_data_tlv, uint16_t network_data_tlv_length, uint8_t** prefix_tlv, bool *stable) 00915 { 00916 #ifdef HAVE_THREAD 00917 uint16_t tlv_length; 00918 if (!network_data_tlv || !network_data_tlv_length || !prefix_tlv) { 00919 return -1; 00920 } 00921 //tr_debug("thread_tlv_lib_prefix_find() len=%d, tlv=%s", network_data_tlv_length, trace_array(network_data_tlv, network_data_tlv_length)); 00922 *stable = true; 00923 tlv_length = thread_meshcop_tlv_find_next(network_data_tlv, network_data_tlv_length, THREAD_NWK_DATA_TYPE_PREFIX|THREAD_NWK_STABLE_DATA, prefix_tlv); 00924 if (tlv_length == 0) { 00925 tlv_length = thread_meshcop_tlv_find_next(network_data_tlv, network_data_tlv_length, THREAD_NWK_DATA_TYPE_PREFIX, prefix_tlv); 00926 *stable = false; 00927 } 00928 return tlv_length; 00929 #else 00930 (void)network_data_tlv; 00931 (void)network_data_tlv_length; 00932 (void)prefix_tlv; 00933 (void)stable; 00934 return -1; 00935 #endif 00936 } 00937 00938 int thread_border_router_tlv_find(uint8_t* prefix_tlv, uint16_t prefix_tlv_length, uint8_t** border_router_tlv, bool *stable) 00939 { 00940 #ifdef HAVE_THREAD 00941 uint16_t tlv_length; 00942 if (!prefix_tlv || !prefix_tlv_length || !border_router_tlv) { 00943 return -1; 00944 } 00945 00946 //tr_debug("thread_tlv_lib_border_router_find() len=%d, tlv=%s", prefix_tlv_length, trace_array(prefix_tlv, prefix_tlv_length)); 00947 uint8_t prefix_length = prefix_tlv[1]; 00948 uint8_t prefix_byte_len = prefixBits_to_bytes(prefix_length); 00949 prefix_tlv = prefix_tlv + 2 + prefix_byte_len; //2 = domain ID + prefix length 00950 prefix_tlv_length = prefix_tlv_length - prefix_byte_len - 2; 00951 00952 // find stable prefix first and if not found return unstable data 00953 *stable = true; 00954 tlv_length = thread_meshcop_tlv_find_next(prefix_tlv, prefix_tlv_length, THREAD_NWK_DATA_TYPE_BORDER_ROUTER|THREAD_NWK_STABLE_DATA, border_router_tlv); 00955 if (tlv_length == 0) { 00956 tlv_length = thread_meshcop_tlv_find_next(prefix_tlv, prefix_tlv_length, THREAD_NWK_DATA_TYPE_BORDER_ROUTER, border_router_tlv); 00957 *stable = false; 00958 } 00959 return tlv_length; 00960 #else 00961 (void)prefix_tlv; 00962 (void)prefix_tlv_length; 00963 (void)border_router_tlv; 00964 (void)stable; 00965 return -1; 00966 #endif 00967 } 00968 00969 int thread_border_router_prefix_context_id(uint8_t *prefix_tlv, uint16_t prefix_tlv_length) 00970 { 00971 #ifdef HAVE_THREAD 00972 if (!prefix_tlv || !prefix_tlv_length) { 00973 return -1; 00974 } 00975 00976 uint16_t data_length = prefix_tlv_length; 00977 00978 while (data_length) { 00979 uint8_t type = *prefix_tlv++; 00980 uint16_t len = *prefix_tlv++; 00981 data_length -= 2; 00982 00983 type &= THREAD_NWK_DATA_TYPE_MASK; 00984 00985 if (type == THREAD_NWK_DATA_TYPE_6LOWPAN_ID) { 00986 return (*prefix_tlv & 0x0f); 00987 } 00988 00989 data_length -= len; 00990 prefix_tlv += len; 00991 } 00992 00993 return -2; 00994 #else 00995 (void)prefix_tlv; 00996 (void)prefix_tlv_length; 00997 return -1; 00998 #endif 00999 } 01000 01001 int thread_border_router_service_tlv_find(uint8_t* network_data_tlv, uint16_t network_data_tlv_length, uint8_t** service_tlv, bool* stable) 01002 { 01003 #ifdef HAVE_THREAD 01004 uint16_t tlv_length; 01005 if (!network_data_tlv || !network_data_tlv_length || !service_tlv) { 01006 return -1; 01007 } 01008 01009 *stable = true; 01010 tlv_length = thread_meshcop_tlv_find_next(network_data_tlv, network_data_tlv_length, THREAD_NWK_DATA_TYPE_SERVICE_DATA|THREAD_NWK_STABLE_DATA, service_tlv); 01011 if (tlv_length == 0) { 01012 tlv_length = thread_meshcop_tlv_find_next(network_data_tlv, network_data_tlv_length, THREAD_NWK_DATA_TYPE_SERVICE_DATA, service_tlv); 01013 *stable = false; 01014 } 01015 return tlv_length; 01016 #else 01017 (void)network_data_tlv; 01018 (void)network_data_tlv_length; 01019 (void)service_tlv; 01020 (void)stable; 01021 return -1; 01022 #endif 01023 } 01024 01025 int thread_border_router_server_tlv_find(uint8_t* service_tlv, uint16_t service_tlv_length, uint8_t** server_tlv, bool* stable) 01026 { 01027 #ifdef HAVE_THREAD 01028 uint16_t tlv_length; 01029 if (!service_tlv || !service_tlv_length || !server_tlv) { 01030 return -1; 01031 } 01032 01033 uint8_t t_flag = service_tlv[0] >> 7; 01034 service_tlv += 1; 01035 01036 if (!t_flag) { 01037 service_tlv_length -= 4; 01038 service_tlv += 4; 01039 } 01040 01041 uint8_t service_data_len = *service_tlv; 01042 service_tlv += 1 + service_data_len; 01043 service_tlv_length = service_tlv_length - service_data_len - 2; 01044 01045 *stable = true; 01046 tlv_length = thread_meshcop_tlv_find_next(service_tlv, service_tlv_length, THREAD_NWK_DATA_TYPE_SERVER_DATA|THREAD_NWK_STABLE_DATA, server_tlv); 01047 if (tlv_length == 0) { 01048 tlv_length = thread_meshcop_tlv_find_next(service_tlv, service_tlv_length, THREAD_NWK_DATA_TYPE_SERVER_DATA, server_tlv); 01049 *stable = false; 01050 } 01051 return tlv_length; 01052 #else 01053 (void)service_tlv; 01054 (void)service_tlv_length; 01055 (void)server_tlv; 01056 (void)stable; 01057 return -1; 01058 #endif 01059 } 01060 01061 int thread_border_router_mdns_responder_start(int8_t interface_id, int8_t interface_id_mdns, const char *service_name) 01062 { 01063 #ifdef HAVE_THREAD_BORDER_ROUTER 01064 return thread_mdns_start(interface_id, interface_id_mdns, service_name); 01065 #else 01066 (void)interface_id; 01067 (void)interface_id_mdns; 01068 (void)service_name; 01069 return -1; 01070 #endif 01071 } 01072 01073 int thread_border_router_mdns_responder_stop(void) 01074 { 01075 #ifdef HAVE_THREAD_BORDER_ROUTER 01076 return thread_mdns_stop(); 01077 #else 01078 return -1; 01079 #endif 01080 } 01081
Generated on Tue Jul 12 2022 13:03:20 by
