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_mdns.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 00030 #include "nsconfig.h" 00031 00032 #ifdef HAVE_THREAD_BORDER_ROUTER 00033 00034 #include <string.h> 00035 #include "ns_types.h" 00036 #include <nsdynmemLIB.h> 00037 #include "ns_trace.h" 00038 #include "common_functions.h" 00039 #include "6LoWPAN/Thread/thread_config.h" 00040 #include "6LoWPAN/Thread/thread_common.h" 00041 #include "6LoWPAN/Thread/thread_joiner_application.h" 00042 #include "ns_sha256.h" 00043 #include "ns_mdns_api.h" 00044 #include "Service_Libs/utils/ns_crc.h" 00045 00046 #define TRACE_GROUP "tmDNS" 00047 00048 /* 00049 * mDNS data structure 00050 * 00051 */ 00052 typedef struct { 00053 ns_mdns_t server_instance; 00054 ns_mdns_service_t service_instance; 00055 ns_mdns_service_param_t service_params; 00056 uint8_t *txt_record_buffer; 00057 uint16_t txt_value_crc; 00058 uint8_t txt_record_buffer_len; 00059 int8_t interface_id; 00060 int8_t interface_id_mdns; 00061 } thread_mdns_t; 00062 00063 static thread_mdns_t thread_mdns = { 00064 .server_instance = NULL, 00065 .service_instance = NULL, 00066 .txt_record_buffer = NULL, 00067 .txt_value_crc = 0, 00068 .txt_record_buffer_len = 0, 00069 .interface_id = -1, 00070 .interface_id_mdns = -1, 00071 }; 00072 00073 static thread_mdns_t *thread_mdns_ptr = &thread_mdns; 00074 00075 /* mDNS constants */ 00076 #define THREAD_MDNS_TIME_TO_LIVE 4500 /* Time to Live in seconds */ 00077 #define THREAD_MDNS_TIME_TO_LIVE_HOP_COUNT 120 /* Time to Live in hops */ 00078 00079 /* mDNS TXT record State Bitmap */ 00080 #define THREAD_MDNS_TXT_SB_CONNECTION_MODE_BM 0x07 /* Mask 0000 0111 */ 00081 #define THREAD_MDNS_TXT_SB_INTERFACE_STATUS_BM 0x18 /* Mask 0001 1000 */ 00082 #define THREAD_MDNS_TXT_SB_AVAILABILITY_HIGH 0x20 /* Value 0010 0000 */ 00083 00084 static uint8_t *thread_mdns_txt_record_sb_get(int interface_id, uint8_t *buf, uint32_t *state_bm) 00085 { 00086 uint32_t state_bitmap = 0; 00087 uint8_t *ptr = buf; 00088 00089 const uint8_t sb_string[] = {7, 's', 'b', '='}; 00090 link_configuration_s *link_configuration = thread_management_configuration_get(interface_id); 00091 00092 if (link_configuration) { 00093 if (link_configuration->securityPolicy & SECURITY_POLICY_EXTERNAL_COMMISSIONER_ALLOWED) { 00094 /* connection mode: 00095 * 1: DTLS connection to Border Agent allowed with a user chosen network Commissioner Credential and shared PSKc for the active Thread Network Partition 00096 * 2, DTLS connection to Border Agent allowed using the Border Agent Device Passphrase (PSKd) as the Commissioner Credential 00097 * */ 00098 state_bitmap = 0x01; 00099 } 00100 00101 /* Thread Interface Status 00102 * 2, Thread interface is initialized with a set of valid operational parameters and is actively part of a Thread Network Partition 00103 * */ 00104 state_bitmap |= 0x02<<3; 00105 00106 /* Availability 00107 * 1: High availability – The Border Agent device and its Thread interface are part of stable, always-on network infrastructure 00108 * */ 00109 state_bitmap |= THREAD_MDNS_TXT_SB_AVAILABILITY_HIGH; 00110 } else { 00111 /* connection mode: 00112 * -bits 0-2: 0=DTLS connection to Border Agent is not allowed 00113 * 00114 * Thread Interface Status 00115 * -bits 3-4: 0=Thread interface is not active and is not initialized with a set of valid operational network parameters 00116 * 00117 * Availability 00118 * -bits 5-6: 0= Infrequent availability - Thread interface may become inactive when the Border Agent device is not in use 00119 * */ 00120 state_bitmap = 0x00; 00121 } 00122 00123 *state_bm = state_bitmap; 00124 00125 memcpy(ptr, sb_string, sizeof(sb_string)); 00126 ptr += sizeof(sb_string); 00127 00128 ptr = common_write_32_bit(state_bitmap, ptr); 00129 00130 return ptr; 00131 } 00132 00133 static uint8_t *thread_mdns_txt_record_nn_key_fill(int8_t interface_id, uint8_t *buf, uint32_t state_bitmap) 00134 { 00135 uint8_t *ptr = buf; 00136 int i; 00137 uint8_t length; 00138 const char nn_string[4] = "nn="; 00139 00140 if (! (state_bitmap & THREAD_MDNS_TXT_SB_CONNECTION_MODE_BM)) { 00141 // if connection mode is not allowed, elide nn-key 00142 return ptr; 00143 } 00144 00145 ptr++; /* make room for length */ 00146 length = sizeof(nn_string) - 1; 00147 memcpy(ptr, nn_string, length); 00148 ptr += length; 00149 00150 if (state_bitmap & THREAD_MDNS_TXT_SB_AVAILABILITY_HIGH) { 00151 link_configuration_s *link_configuration = thread_management_configuration_get(interface_id); 00152 if (!link_configuration) { 00153 return ptr; 00154 } 00155 00156 for (i = 0; i < 16 && link_configuration->name[i] != 0; i++) { 00157 *ptr++ = link_configuration->name[i]; 00158 } 00159 00160 length += i; /* update length */ 00161 } else { 00162 // Thread interface seldomly available, use border agent product or model name 00163 memcpy(ptr, THREAD_VENDOR_MODEL, sizeof(THREAD_VENDOR_MODEL) - 1); 00164 ptr += sizeof(THREAD_VENDOR_MODEL) - 1; 00165 length += sizeof(THREAD_VENDOR_MODEL) - 1; 00166 } 00167 00168 *buf = length; // update length 00169 00170 return ptr; 00171 } 00172 00173 static uint8_t *thread_mdns_txt_record_xp_key_fill(int8_t interface_id, uint8_t *buf, uint32_t state_bitmap) 00174 { 00175 uint8_t *ptr = buf; 00176 int length; 00177 const uint8_t xp_string[4] = { 11, 'x', 'p', '=' }; 00178 00179 if (! (state_bitmap & THREAD_MDNS_TXT_SB_CONNECTION_MODE_BM)) { 00180 // if connection mode not allowed, skip xb-key 00181 return ptr; 00182 } 00183 00184 length = sizeof xp_string; 00185 memcpy(ptr, xp_string, length); 00186 ptr += length; 00187 00188 if(state_bitmap & THREAD_MDNS_TXT_SB_INTERFACE_STATUS_BM) { 00189 link_configuration_s *link_configuration = thread_management_configuration_get(interface_id); 00190 if (!link_configuration) { 00191 tr_error("Failed to read link configuration"); 00192 return ptr; 00193 } 00194 memcpy(ptr, link_configuration->extented_pan_id, 8); 00195 } else { 00196 device_configuration_s *device_configuration = thread_management_device_configuration_get(interface_id); 00197 if (!device_configuration) { 00198 tr_error("Failed to read device configuration"); 00199 return ptr; 00200 } 00201 ns_sha256_nbits(device_configuration->eui64, 8, ptr, 64); 00202 } 00203 00204 ptr += 8; 00205 00206 return ptr; 00207 } 00208 00209 static uint8_t *thread_mdns_txt_record_fill(int8_t interface_id, uint8_t *buf) 00210 { 00211 static const char mDNS_thread_version[9] = "tv=1.1.1"; 00212 uint8_t *ptr = buf; 00213 uint32_t state_bitmap; 00214 00215 /* rv */ 00216 *ptr++ = 0x04; /* rv length */ 00217 memcpy(ptr, "rv=1", 4); 00218 ptr += 4; 00219 00220 /* tv */ 00221 *ptr++ = sizeof(mDNS_thread_version) - 1; /* tv length */ 00222 memcpy(ptr, mDNS_thread_version, sizeof(mDNS_thread_version)- 1); 00223 ptr += sizeof(mDNS_thread_version) - 1; 00224 00225 /* state bitmap */ 00226 ptr = thread_mdns_txt_record_sb_get(interface_id, ptr, &state_bitmap); 00227 00228 tr_debug("state_bitmap %"PRIx32, state_bitmap); 00229 00230 /* nn-key */ 00231 ptr = thread_mdns_txt_record_nn_key_fill(interface_id, ptr, state_bitmap); 00232 00233 /* xp-key */ 00234 ptr = thread_mdns_txt_record_xp_key_fill(interface_id, ptr, state_bitmap); 00235 00236 *ptr++ = 0; 00237 00238 return ptr; 00239 } 00240 00241 /* callback from mDNS to fill TXT record */ 00242 static const uint8_t *thread_mdns_txt_record_callback(void) 00243 { 00244 uint8_t buffer[200]; /* 200 bytes enough space for TXT record */ 00245 uint8_t *ptr; 00246 size_t new_record_length; 00247 00248 ptr = thread_mdns_txt_record_fill(thread_mdns_ptr->interface_id, buffer); 00249 00250 new_record_length = ptr - buffer; 00251 00252 if (thread_mdns_ptr->txt_record_buffer_len < new_record_length) { 00253 // not enough space in current buffer 00254 ns_dyn_mem_free(thread_mdns_ptr->txt_record_buffer); 00255 thread_mdns_ptr->txt_record_buffer = NULL; 00256 } 00257 00258 if (thread_mdns_ptr->txt_record_buffer == NULL) { 00259 thread_mdns_ptr->txt_record_buffer = ns_dyn_mem_alloc(new_record_length); 00260 } 00261 00262 if (!thread_mdns_ptr->txt_record_buffer) { 00263 tr_error("mDNS record not allocated"); 00264 return (uint8_t*)'\0'; 00265 } 00266 00267 memcpy(thread_mdns_ptr->txt_record_buffer, buffer, new_record_length); 00268 thread_mdns_ptr->txt_record_buffer_len = new_record_length; 00269 00270 tr_debug("mDNS TXT record created, %d bytes", thread_mdns_ptr->txt_record_buffer_len); 00271 00272 return thread_mdns_ptr->txt_record_buffer; 00273 } 00274 00275 static uint16_t thread_mdns_txt_values_crc_get(void) 00276 { 00277 link_configuration_s *link_configuration; 00278 uint16_t txt_values_crc = 0; 00279 00280 if (!thread_mdns_ptr->server_instance) { 00281 // mdns not active 00282 return txt_values_crc; 00283 } 00284 00285 link_configuration = thread_joiner_application_get_config(thread_mdns_ptr->interface_id); 00286 if (link_configuration) { 00287 // calculate CRC for values in mDNS TXT record that may change 00288 txt_values_crc = crc16_ccitt(link_configuration->name, 16); 00289 txt_values_crc |= crc16_ccitt(link_configuration->extented_pan_id, 8); 00290 txt_values_crc |= crc16_ccitt(&link_configuration->securityPolicy, 1); 00291 } 00292 00293 return txt_values_crc; 00294 } 00295 00296 int thread_mdns_stop(void) 00297 { 00298 if (thread_mdns_ptr->server_instance == NULL) { 00299 return -1; 00300 } 00301 00302 ns_mdns_server_stop(thread_mdns_ptr->server_instance); 00303 00304 thread_mdns_ptr->server_instance = NULL; 00305 ns_dyn_mem_free(thread_mdns_ptr->txt_record_buffer); 00306 thread_mdns_ptr->txt_record_buffer = NULL; 00307 thread_mdns_ptr->txt_record_buffer_len = 0; 00308 00309 return 0; 00310 } 00311 00312 int thread_mdns_start(int8_t interface_id, int8_t interface_id_mdns, const char *service_name) 00313 { 00314 static const char *mDNS_service_type = "_meshcop._udp"; 00315 00316 if (thread_mdns_ptr->server_instance != NULL) { 00317 return -1; 00318 } 00319 00320 thread_mdns_ptr->server_instance = ns_mdns_server_start(service_name, THREAD_MDNS_TIME_TO_LIVE, THREAD_MDNS_TIME_TO_LIVE_HOP_COUNT, interface_id_mdns); 00321 if (thread_mdns_ptr->server_instance == NULL) { 00322 tr_error("mDNS server initialization failed"); 00323 return -2; 00324 } 00325 00326 thread_mdns_ptr->interface_id = interface_id; 00327 thread_mdns_ptr->interface_id_mdns = interface_id_mdns; 00328 thread_mdns_ptr->service_params.service_type = mDNS_service_type; 00329 thread_mdns_ptr->service_params.service_port = THREAD_COMMISSIONING_PORT; 00330 thread_mdns_ptr->service_params.service_get_txt = thread_mdns_txt_record_callback; 00331 thread_mdns_ptr->service_instance = ns_mdns_service_register(thread_mdns_ptr->server_instance, &thread_mdns_ptr->service_params); 00332 thread_mdns_ptr->txt_value_crc = thread_mdns_txt_values_crc_get(); 00333 00334 if (thread_mdns_ptr->service_instance == NULL) { 00335 tr_error("mDNS service init failed"); 00336 thread_mdns_stop(); 00337 return -3; 00338 } 00339 00340 return 0; 00341 } 00342 00343 #endif //HAVE_THREAD_BORDER_ROUTER 00344 00345 void thread_mdns_network_data_update_notify(void) 00346 { 00347 #ifdef HAVE_THREAD_BORDER_ROUTER 00348 uint16_t txt_value_crc; 00349 txt_value_crc = thread_mdns_txt_values_crc_get(); 00350 if (txt_value_crc != thread_mdns_ptr->txt_value_crc) { 00351 // Values for TXT-record have changed, send mDNS announcement 00352 thread_mdns_ptr->txt_value_crc = txt_value_crc; 00353 ns_mdns_announcement_send(thread_mdns_ptr->server_instance); 00354 } 00355 #endif //HAVE_THREAD_BORDER_ROUTER 00356 } 00357
Generated on Fri Jul 22 2022 04:54:03 by
