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