1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Multicast Domain Name System (mDNS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 #define NX_MDNS_SOURCE_CODE
24
25
26 /* Force error checking to be disabled in this module */
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif /* NX_DISABLE_ERROR_CHECKING */
30
31
32 /* Include necessary system files. */
33 #include "nxd_mdns.h"
34 #include "tx_thread.h"
35
36 /* Define the application protocol. */
37 static CHAR *nx_mdns_app_protocol[]= {"_tcp", "_udp", NX_NULL};
38
39 /* Define the service type. */
40 #ifndef NX_MDNS_DISABLE_CLIENT
41 static CHAR *nx_mdns_service_types[] =
42 {
43 "_device-info",
44 "_http",
45 "_https",
46 "_guid",
47 "_h323",
48 "_ntp",
49 "_objective",
50 "_rdp",
51 "_remote",
52 "_rtsp",
53 "_sip",
54 "_smb",
55 "_soap",
56 "_ssh",
57 "_telnet",
58 "_tftp",
59 "_xmpp-client",
60 NX_NULL
61 };
62 #endif /* NX_MDNS_DISABLE_CLIENT */
63
64
65 /* Define the mDNS internal Function. */
66 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
67 static VOID _nx_mdns_timer_entry(ULONG mdns_value);
68 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr, ULONG timer_count);
69 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr);
70 static VOID _nx_mdns_thread_entry(ULONG mdns_value);
71 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
72 static UINT _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR type);
73 static VOID _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
74 static UINT _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type);
75 static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index);
76 static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op);
77 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
78 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr);
79 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
80 static UINT _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index);
81 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain);
82 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
83 static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr);
84 static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length);
85 static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr);
86 static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name);
87 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size);
88 static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name);
89 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size);
90 static VOID _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value);
91 static VOID _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value);
92
93 #ifndef NX_MDNS_DISABLE_SERVER
94 static VOID _nx_mdns_address_change_process(NX_MDNS *mdns_ptr);
95 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index);
96 static UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index);
97 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
98 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index);
99 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
100 static UINT _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority, USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index);
101 static UINT _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index);
102 static UINT _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index);
103
104 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
105 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index);
106 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
107
108 static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length, UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index);
109 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
110 static UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
111 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index);
112 static VOID _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index);
113 static VOID _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index);
114 static VOID _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index);
115 #ifndef NX_DISABLE_IPV4
116 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info);
117 #endif /* NX_DISABLE_IPV4 */
118 #ifdef NX_MDNS_ENABLE_IPV6
119 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address);
120 #endif /* NX_MDNS_ENABLE_IPV6 */
121 #endif /* NX_MDNS_DISABLE_SERVER */
122
123 #ifndef NX_MDNS_DISABLE_CLIENT
124 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present);
125 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index);
126 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask);
127 static UINT _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index);
128 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index);
129 static VOID _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index);
130 static UINT _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index);
131 static VOID _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER);
132 static VOID _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
133 NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option);
134 static VOID _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr);
135 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
136 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index);
137 #endif /* NX_MDNS_DISABLE_CLIENT */
138
139 UINT _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size, VOID *peer_cache_ptr, UINT peer_cache_size);
140 UINT _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present);
141 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr);
142 UINT _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_result);
143 UINT _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len, VOID **insert_ptr, UCHAR find_string, UCHAR add_name);
144 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len);
145 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr);
146
147
148 /* Define the mDNS STRUCT. */
149 static struct NX_MDNS_STRUCT *_nx_mdns_created_ptr;
150 static CHAR _nx_mdns_dns_sd[NX_MDNS_DNS_SD_MAX + 1] = "_services._dns-sd._udp.local";
151 static UCHAR temp_string_buffer[NX_MDNS_NAME_MAX + 1];
152 static UCHAR target_string_buffer[NX_MDNS_NAME_MAX + 1];
153
154 #ifdef NX_MDNS_ENABLE_IPV6
155 static NXD_ADDRESS NX_MDNS_IPV6_MULTICAST_ADDRESS;
156 #endif /* NX_MDNS_ENABLE_IPV6 */
157
158 /**************************************************************************/
159 /* */
160 /* FUNCTION RELEASE */
161 /* */
162 /* _nxe_mdns_create PORTABLE C */
163 /* 6.1 */
164 /* AUTHOR */
165 /* */
166 /* Yuxin Zhou, Microsoft Corporation */
167 /* */
168 /* DESCRIPTION */
169 /* */
170 /* This function checks for errors in the mDNS create function call */
171 /* */
172 /* Note: the name string is generated by internal logic and it is */
173 /* always NULL-terminated. */
174 /* */
175 /* INPUT */
176 /* */
177 /* mdns_ptr Pointer to mDNS instance */
178 /* ip_ptr Pointer to IP instance */
179 /* priority The priority of mDNS Thread */
180 /* stack_ptr Stack pointer for mDNS Thread */
181 /* stack_size Stack size for mDNS Thread */
182 /* host_name Pointer to host name */
183 /* local_cache_ptr Pointer to local cache */
184 /* local_cache_size The size of local cache */
185 /* peer_cache_ptr Pointer to peer cache */
186 /* peer_cache_size The size of peer cache */
187 /* probing_notify mDNS probing notify */
188 /* */
189 /* OUTPUT */
190 /* */
191 /* status Completion status */
192 /* */
193 /* CALLS */
194 /* */
195 /* _nx_mdns_create Actual mDNS create function */
196 /* */
197 /* CALLED BY */
198 /* */
199 /* Application Code */
200 /* */
201 /* RELEASE HISTORY */
202 /* */
203 /* DATE NAME DESCRIPTION */
204 /* */
205 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
206 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
207 /* resulting in version 6.1 */
208 /* */
209 /**************************************************************************/
_nxe_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))210 UINT _nxe_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
211 UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
212 VOID *local_cache_ptr, UINT local_cache_size,
213 VOID *peer_cache_ptr, UINT peer_cache_size,
214 VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
215 {
216
217 UINT status;
218 UCHAR *ptr;
219
220
221 /* Check for invalid input pointers. */
222 if ((!ip_ptr) || (!mdns_ptr) || (!stack_ptr) || (!packet_pool) || (!host_name))
223 {
224 return(NX_PTR_ERROR);
225 }
226
227 /* Check for invalid non pointer input. */
228 if ((ip_ptr -> nx_ip_id != NX_IP_ID) ||
229 (stack_size < TX_MINIMUM_STACK) ||
230 (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
231 {
232 return(NX_MDNS_PARAM_ERROR);
233 }
234
235 /* Check the host name format, RFC 1033,1034,1035 recomend that host names contain only letters, digits, and hyphens RFC6763, Appendix E, Page44. */
236 ptr = host_name;
237 while (*ptr != '\0')
238 {
239 if (((*ptr >= 'a') && (*ptr <= 'z')) ||
240 ((*ptr >= 'A') && (*ptr <= 'Z')) ||
241 ((*ptr >= '0') && (*ptr <= '9')) ||
242 ((*ptr == '-')))
243 ptr++;
244 else
245 return(NX_MDNS_HOST_NAME_ERROR);
246 }
247
248 /* Check the default domain name size. */
249 if ((sizeof("local") - 1) > NX_MDNS_DOMAIN_NAME_MAX)
250 {
251 return(NX_MDNS_DATA_SIZE_ERROR);
252 }
253
254 #ifndef NX_MDNS_DISABLE_SERVER
255
256 /* Check for invalid input pointers, cache header and tail (8 bytes). */
257 if ((!local_cache_ptr) || (local_cache_size < 8))
258 {
259 return(NX_PTR_ERROR);
260 }
261
262 /* Make sure record_buffer is 4-byte aligned. */
263 if ((((UINT)local_cache_ptr & 0x3) != 0) ||
264 ((local_cache_size & 0x3) != 0))
265 {
266 return(NX_MDNS_CACHE_ERROR);
267 }
268 #endif /* NX_MDNS_DISABLE_SERVER */
269
270 #ifndef NX_MDNS_DISABLE_CLIENT
271
272 /* Check for invalid input pointers, cache header and tail (8 bytes). */
273 if ((!peer_cache_ptr) || (peer_cache_size < 8))
274 {
275 return(NX_PTR_ERROR);
276 }
277
278 /* Make sure peer cache is 4-byte aligned. */
279 if ((((UINT)peer_cache_ptr & 0x3) != 0) ||
280 ((peer_cache_size & 0x3) != 0))
281 {
282 return(NX_MDNS_CACHE_ERROR);
283 }
284 #endif /* NX_MDNS_DISABLE_CLIENT */
285
286 /* Call actual mDNS create service. */
287 status = _nx_mdns_create(mdns_ptr, ip_ptr, packet_pool, priority,
288 stack_ptr, stack_size, host_name,
289 local_cache_ptr, local_cache_size,
290 peer_cache_ptr, peer_cache_size,
291 probing_notify);
292
293 /* Return status. */
294 return(status);
295 }
296
297
298 /**************************************************************************/
299 /* */
300 /* FUNCTION RELEASE */
301 /* */
302 /* _nx_mdns_create PORTABLE C */
303 /* 6.1.11 */
304 /* AUTHOR */
305 /* */
306 /* Yuxin Zhou, Microsoft Corporation */
307 /* */
308 /* DESCRIPTION */
309 /* */
310 /* This function initializes the mDNS structure and associated IP */
311 /* instance for mDNS operation. In doing so, it creates a UDP socket */
312 /* for communication with the server and a mDNS processing thread */
313 /* */
314 /* Note: the name string is generated by internal logic and it is */
315 /* always NULL-terminated. */
316 /* */
317 /* INPUT */
318 /* */
319 /* mdns_ptr Pointer to mDNS instance */
320 /* ip_ptr Pointer to IP instance */
321 /* priority The priority of mDNS Thread */
322 /* stack_ptr Stack pointer for mDNS Thread */
323 /* stack_size Stack size for mDNS Thread */
324 /* host_name Pointer to host name */
325 /* local_cache_ptr Pointer to local cache */
326 /* local_cache_size The size of local cache */
327 /* peer_cache_ptr Pointer to peer cache */
328 /* peer_cache_size The size of peer cache */
329 /* probing_notify mDNS probing notify */
330 /* */
331 /* OUTPUT */
332 /* */
333 /* status Completion status */
334 /* */
335 /* CALLS */
336 /* */
337 /* nx_udp_socket_create Create the mDNS UDP socket */
338 /* nx_udp_socket_delete Delete the mDNS UDP socket */
339 /* nx_udp_socket_bind Bind the mDNS UDP socket */
340 /* nx_udp_socket_unbind Unbind the mDNS UDP socket */
341 /* nx_udp_socket_receive_notify Register the mDNS function */
342 /* nx_ip_address_change_notify Register IPv4 address function*/
343 /* nxd_ipv6_address_change_notify Register IPv6 address function*/
344 /* tx_mutex_create Create the mDNS mutex */
345 /* tx_mutex_delete Delete the mDNS mutex */
346 /* tx_thread_create Create the mDNS thread */
347 /* tx_thread_delete Delete the mDNS thread */
348 /* tx_event_flags_create Create the ThreadX flag event */
349 /* _nx_mdns_cache_initialize Initialize the mDNS cache */
350 /* */
351 /* CALLED BY */
352 /* */
353 /* Application Code */
354 /* */
355 /* RELEASE HISTORY */
356 /* */
357 /* DATE NAME DESCRIPTION */
358 /* */
359 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
360 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
361 /* verified memcpy use cases, */
362 /* resulting in version 6.1 */
363 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
364 /* corrected the random value, */
365 /* used internal ip address */
366 /* change notification, */
367 /* resulting in version 6.1.11 */
368 /* */
369 /**************************************************************************/
_nx_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))370 UINT _nx_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
371 UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
372 VOID *local_cache_ptr, UINT local_cache_size,
373 VOID *peer_cache_ptr, UINT peer_cache_size,
374 VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
375 {
376
377 UINT status;
378 UINT host_name_size;
379
380
381 /* Check the size of the host name string. The last four characters in the
382 host_name are reserved so DNS-SD is able to append " (2)" during the conflict
383 resolution process. */
384 #if (NX_MDNS_HOST_NAME_MAX >= NX_MDNS_LABEL_MAX)
385 if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_LABEL_MAX - 4)))
386 #else
387 if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_HOST_NAME_MAX - 4)))
388 #endif
389 {
390 return(NX_MDNS_DATA_SIZE_ERROR);
391 }
392
393 /* Initialize the mDNS control block to zero. */
394 memset((void *) mdns_ptr, 0, sizeof(NX_MDNS));
395
396 #ifdef NX_MDNS_ENABLE_IPV6
397
398 /* Initialize the IPv6 Multicast address. */
399 memset(&NX_MDNS_IPV6_MULTICAST_ADDRESS, 0, sizeof(NXD_ADDRESS));
400 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_version = NX_IP_VERSION_V6;
401 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0] = 0xFF020000;
402 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1] = 0x00000000;
403 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2] = 0x00000000;
404 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3] = 0x000000FB;
405 #endif /* NX_MDNS_ENABLE_IPV6 */
406
407 /* Save the IP pointer. */
408 mdns_ptr -> nx_mdns_ip_ptr = ip_ptr;
409
410 /* Save the Packet pool. */
411 mdns_ptr -> nx_mdns_packet_pool_ptr = packet_pool;
412
413 /* Save the host name. */
414 memcpy((char*)mdns_ptr -> nx_mdns_host_name, (const char*)host_name, (host_name_size + 1)); /* Use case of memcpy is verified. */
415
416 /* Set the domain name as "local" by default. */
417 memcpy((char*)mdns_ptr -> nx_mdns_domain_name, "local", sizeof("local")); /* Use case of memcpy is verified. */
418
419 /* Assign the resource record change notify. */
420 mdns_ptr -> nx_mdns_probing_notify = probing_notify;
421
422 /* Set the mDNS announcing period. */
423 mdns_ptr -> nx_mdns_announcing_period = (USHORT)NX_MDNS_ANNOUNCING_PERIOD;
424
425 /* Set the mDNS announcing retransmission interval. */
426 mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)NX_MDNS_ANNOUNCING_RETRANS_INTERVAL;
427
428 /* Set the mDNS announcing period interval. */
429 mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)NX_MDNS_ANNOUNCING_PERIOD_INTERVAL;
430
431 /* Set the mDNS announcing count between one announcing period. */
432 mdns_ptr -> nx_mdns_announcing_count = (UCHAR)NX_MDNS_ANNOUNCING_COUNT;
433
434 /* Set the mDNS announcing factor. */
435 mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)NX_MDNS_ANNOUNCING_FACTOR;
436
437 /* Set the mDNS announcing max time. */
438 mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)NX_MDNS_ANNOUNCING_MAX_TIME;
439
440 /* Set the pointer of global variable mDNS. */
441 _nx_mdns_created_ptr = mdns_ptr;
442
443 #ifndef NX_MDNS_DISABLE_SERVER
444
445 #ifndef NX_DISABLE_IPV4
446 /* Setup the IP address change callback function. */
447 ip_ptr -> nx_ip_address_change_notify_internal = _nx_mdns_ip_address_change_notify;
448 #endif /* NX_DISABLE_IPV4 */
449
450 #ifdef NX_MDNS_ENABLE_IPV6
451
452 /* Setup the IPv6 address change callback function. */
453 ip_ptr -> nx_ipv6_address_change_notify_internal = _nx_mdns_ipv6_address_change_notify;
454 #endif /* NX_MDNS_ENABLE_IPV6 */
455 #endif /* NX_MDNS_DISABLE_SERVER */
456
457 /* Create the Socket and check the status */
458 status = nx_udp_socket_create(mdns_ptr -> nx_mdns_ip_ptr, &(mdns_ptr -> nx_mdns_socket), "Multicast DNS",
459 NX_MDNS_UDP_TYPE_OF_SERVICE, NX_MDNS_UDP_FRAGMENT_OPTION,
460 NX_MDNS_UDP_TIME_TO_LIVE, NX_MDNS_UDP_QUEUE_DEPTH);
461
462 /* Determine if it was successful. */
463 if (status != NX_SUCCESS)
464 {
465 return(status);
466 }
467
468 /* Bind the UDP socket to the mDNS port. */
469 status = nx_udp_socket_bind(&(mdns_ptr -> nx_mdns_socket), NX_MDNS_UDP_PORT, TX_NO_WAIT);
470
471 /* Check for error */
472 if (status)
473 {
474
475 /* Delete the UDP socket. */
476 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
477 return(status);
478 }
479
480 /* Register UDP receive callback. */
481 status = nx_udp_socket_receive_notify(&(mdns_ptr -> nx_mdns_socket), _nx_mdns_udp_receive_notify);
482
483 /* Check for error */
484 if (status)
485 {
486
487 /* Delete the UDP socket. */
488 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
489 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
490 return(status);
491 }
492
493 /* Create the mDNS mutex. */
494 status = tx_mutex_create(&(mdns_ptr -> nx_mdns_mutex),
495 "mDNS Mutex", TX_NO_INHERIT);
496
497 /* Determine if the semaphore creation was successful. */
498 if (status != NX_SUCCESS)
499 {
500
501 /* Delete the UDP socket. */
502 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
503 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
504
505 /* No, return error status. */
506 return(status);
507 }
508
509 /* Create the internal mDNS event flag object. */
510 status = tx_event_flags_create(&mdns_ptr -> nx_mdns_events, "mDNS Thread Events");
511
512 /* Determine if the event flags creation was successful. */
513 if (status)
514 {
515
516 /* Delete the UDP socket. */
517 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
518 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
519
520 /* Delete the mDNS mutex. */
521 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
522
523 /* No, return error status. */
524 return(status);
525 }
526
527 /* Create the mDNS processing thread. */
528 status = tx_thread_create(&(mdns_ptr -> nx_mdns_thread), "mDNS Thread",
529 _nx_mdns_thread_entry, (ULONG) mdns_ptr,
530 stack_ptr, stack_size, priority, priority,
531 1, TX_AUTO_START);
532
533 /* Determine if the thread creation was successful. */
534 if (status != NX_SUCCESS)
535 {
536
537 /* Delete the UDP socket. */
538 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
539 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
540
541 /* Delete the mDNS mutex. */
542 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
543
544 /* Delete the mDNS events. */
545 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
546
547 /* No, return error status. */
548 return(status);
549 }
550
551 /* Create the timer of Resource record lifetime. */
552 status = tx_timer_create(&(mdns_ptr -> nx_mdns_timer), "mDNS Timer",
553 _nx_mdns_timer_entry, (ULONG) mdns_ptr,
554 0xFFFFFFFF, 0, TX_NO_ACTIVATE);
555
556 /* Determine if the thread creation was successful. */
557 if (status != NX_SUCCESS)
558 {
559
560 /* Delete the UDP socket. */
561 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
562 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
563
564 /* Delete the mDNS mutex. */
565 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
566
567 /* Delete the mDNS events. */
568 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
569
570 /* Delete the mDNS thread. */
571 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
572
573 /* No, return error status. */
574 return(status);
575 }
576
577 /* Initialize the buffer. */
578 status = _nx_mdns_cache_initialize(mdns_ptr, local_cache_ptr, local_cache_size,
579 peer_cache_ptr, peer_cache_size);
580
581 /* Determine if the buffer initialize was successful. */
582 if (status != NX_SUCCESS)
583 {
584
585 /* Delete the UDP socket. */
586 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
587 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
588
589 /* Delete the mDNS timer. */
590 tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
591
592 /* Delete the mDNS mutex. */
593 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
594
595 /* Delete the mDNS events. */
596 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
597
598 /* Delete the mDNS thread. */
599 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
600
601 /* No, return error status. */
602 return(status);
603 }
604
605 /* Update the mDNS structure ID. */
606 mdns_ptr -> nx_mdns_id = NX_MDNS_ID;
607
608 /* The random delay of first probing for RR. */
609 mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (((ULONG)NX_RAND()) % NX_MDNS_PROBING_TIMER_COUNT));
610
611 /* Return a successful status. */
612 return(NX_SUCCESS);
613 }
614
615
616 /**************************************************************************/
617 /* */
618 /* FUNCTION RELEASE */
619 /* */
620 /* _nxe_mdns_delete PORTABLE C */
621 /* 6.1 */
622 /* AUTHOR */
623 /* */
624 /* Yuxin Zhou, Microsoft Corporation */
625 /* */
626 /* DESCRIPTION */
627 /* */
628 /* This function checks for errors in the mDNS delete function call. */
629 /* */
630 /* INPUT */
631 /* */
632 /* mdns_ptr Pointer to mDNS instance */
633 /* */
634 /* OUTPUT */
635 /* */
636 /* status Completion status */
637 /* */
638 /* CALLS */
639 /* */
640 /* _nx_mdns_delete Actual mDNS delete function */
641 /* */
642 /* CALLED BY */
643 /* */
644 /* Application Code */
645 /* */
646 /* RELEASE HISTORY */
647 /* */
648 /* DATE NAME DESCRIPTION */
649 /* */
650 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
651 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
652 /* resulting in version 6.1 */
653 /* */
654 /**************************************************************************/
_nxe_mdns_delete(NX_MDNS * mdns_ptr)655 UINT _nxe_mdns_delete(NX_MDNS *mdns_ptr)
656 {
657
658 UINT status;
659
660
661 /* Check for invalid input pointers. */
662 if (!mdns_ptr)
663 {
664 return(NX_PTR_ERROR);
665 }
666
667 /* Check for invalid server attributes. */
668 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
669 {
670 return(NX_MDNS_PARAM_ERROR);
671 }
672
673 /* Call actual mDNS delete service. */
674 status = _nx_mdns_delete(mdns_ptr);
675
676 /* Return status. */
677 return(status);
678 }
679
680
681 /**************************************************************************/
682 /* */
683 /* FUNCTION RELEASE */
684 /* */
685 /* _nx_mdns_delete PORTABLE C */
686 /* 6.1 */
687 /* AUTHOR */
688 /* */
689 /* Yuxin Zhou, Microsoft Corporation */
690 /* */
691 /* DESCRIPTION */
692 /* */
693 /* This function deletes the mDNS instance. */
694 /* */
695 /* INPUT */
696 /* */
697 /* mdns_ptr Pointer to mDNS instance */
698 /* */
699 /* OUTPUT */
700 /* */
701 /* status Completion status */
702 /* */
703 /* CALLS */
704 /* */
705 /* nx_udp_socket_unbind Unbind the mDNS UDP socket */
706 /* nx_udp_socket_delete Delete the mDNS UDP socket */
707 /* tx_mutex_get Get the mDNS mutex */
708 /* tx_mutex_put Put the mDNS mutex */
709 /* tx_mutex_delete Delete the mDNS mutex */
710 /* tx_thread_terminate Terminate the mDNS thread */
711 /* tx_thread_delete Delete the mDNS thread */
712 /* tx_event_flags_delete Delete the mDNS events flag */
713 /* */
714 /* CALLED BY */
715 /* */
716 /* Application Code */
717 /* */
718 /* RELEASE HISTORY */
719 /* */
720 /* DATE NAME DESCRIPTION */
721 /* */
722 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
723 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
724 /* resulting in version 6.1 */
725 /* */
726 /**************************************************************************/
_nx_mdns_delete(NX_MDNS * mdns_ptr)727 UINT _nx_mdns_delete(NX_MDNS *mdns_ptr)
728 {
729
730
731 /* Get the mDNS mutex. */
732 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
733
734 /* Clear the mDNS structure ID. */
735 mdns_ptr -> nx_mdns_id = 0;
736
737 /* Set the pointer of global variable mDNS. */
738 _nx_mdns_created_ptr = NX_NULL;
739
740 /* Unbind the port. */
741 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
742
743 /* Delete the UDP socket. */
744 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
745
746 /* Terminate the mDNS processing thread. */
747 tx_thread_terminate(&(mdns_ptr -> nx_mdns_thread));
748
749 /* Delete the mDNS processing thread. */
750 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
751
752 /* Delete the event flags. */
753 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
754
755 /* Delete the timer. */
756 tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
757
758 /* Release the mDNS mutex. */
759 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
760
761 /* Delete the mDNS mutex. */
762 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
763
764 /* Return a successful status. */
765 return(NX_SUCCESS);
766 }
767
768
769 /**************************************************************************/
770 /* */
771 /* FUNCTION RELEASE */
772 /* */
773 /* _nxe_mdns_cache_notify_set PORTABLE C */
774 /* 6.1 */
775 /* AUTHOR */
776 /* */
777 /* Yuxin Zhou, Microsoft Corporation */
778 /* */
779 /* DESCRIPTION */
780 /* */
781 /* This function checks for errors in the mDNS cache full notify */
782 /* function call. */
783 /* */
784 /* INPUT */
785 /* */
786 /* mdns_ptr Pointer to mDNS instance */
787 /* cache_full_notify Cache full notify function */
788 /* */
789 /* OUTPUT */
790 /* */
791 /* status Completion status */
792 /* */
793 /* CALLS */
794 /* */
795 /* _nx_mdns_cache_notify_set Actual cache notify */
796 /* set function */
797 /* */
798 /* CALLED BY */
799 /* */
800 /* Application Code */
801 /* */
802 /* RELEASE HISTORY */
803 /* */
804 /* DATE NAME DESCRIPTION */
805 /* */
806 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
807 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
808 /* resulting in version 6.1 */
809 /* */
810 /**************************************************************************/
_nxe_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))811 UINT _nxe_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
812 {
813
814 UINT status;
815
816
817 /* Check for invalid input pointers. */
818 if (!mdns_ptr)
819 {
820 return(NX_PTR_ERROR);
821 }
822
823 /* Check for invalid non pointer input. */
824 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
825 {
826 return(NX_MDNS_PARAM_ERROR);
827 }
828
829 /* Call actual mDNS cache notify set function. */
830 status = _nx_mdns_cache_notify_set(mdns_ptr, cache_full_notify_cb);
831
832 /* Return status. */
833 return(status);
834 }
835
836
837 /**************************************************************************/
838 /* */
839 /* FUNCTION RELEASE */
840 /* */
841 /* _nx_mdns_cache_notify_set PORTABLE C */
842 /* 6.1 */
843 /* AUTHOR */
844 /* */
845 /* Yuxin Zhou, Microsoft Corporation */
846 /* */
847 /* DESCRIPTION */
848 /* */
849 /* This function set the cache full notify function. */
850 /* */
851 /* INPUT */
852 /* */
853 /* mdns_ptr Pointer to mDNS instance */
854 /* */
855 /* OUTPUT */
856 /* */
857 /* status Completion status */
858 /* */
859 /* CALLS */
860 /* */
861 /* tx_mutex_get Get the mDNS mutex */
862 /* tx_mutex_put Put the mDNS mutex */
863 /* */
864 /* CALLED BY */
865 /* */
866 /* Application Code */
867 /* */
868 /* RELEASE HISTORY */
869 /* */
870 /* DATE NAME DESCRIPTION */
871 /* */
872 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
873 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
874 /* resulting in version 6.1 */
875 /* */
876 /**************************************************************************/
_nx_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))877 UINT _nx_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
878 {
879
880
881 /* Get the mDNS mutex. */
882 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
883
884 /* Set the cache notify. */
885 mdns_ptr -> nx_mdns_cache_full_notify = cache_full_notify_cb;
886
887 /* Release the mDNS mutex. */
888 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
889
890 return(NX_MDNS_SUCCESS);
891 }
892
893
894 /**************************************************************************/
895 /* */
896 /* FUNCTION RELEASE */
897 /* */
898 /* _nxe_mdns_cache_notify_clear PORTABLE C */
899 /* 6.1 */
900 /* AUTHOR */
901 /* */
902 /* Yuxin Zhou, Microsoft Corporation */
903 /* */
904 /* DESCRIPTION */
905 /* */
906 /* This function checks for errors in the mDNS cache full notify */
907 /* function call. */
908 /* */
909 /* INPUT */
910 /* */
911 /* mdns_ptr Pointer to mDNS instance */
912 /* cache_full_notify Cache full notify function */
913 /* */
914 /* OUTPUT */
915 /* */
916 /* status Completion status */
917 /* */
918 /* CALLS */
919 /* */
920 /* _nx_mdns_cache_notify_clear Actual cache notify */
921 /* clear function */
922 /* */
923 /* CALLED BY */
924 /* */
925 /* Application Code */
926 /* */
927 /* RELEASE HISTORY */
928 /* */
929 /* DATE NAME DESCRIPTION */
930 /* */
931 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
932 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
933 /* resulting in version 6.1 */
934 /* */
935 /**************************************************************************/
_nxe_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)936 UINT _nxe_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
937 {
938
939 UINT status;
940
941
942 /* Check for invalid input pointers. */
943 if (!mdns_ptr)
944 {
945 return(NX_PTR_ERROR);
946 }
947
948 /* Check for invalid non pointer input. */
949 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
950 {
951 return(NX_MDNS_PARAM_ERROR);
952 }
953
954 /* Call actual mDNS cache notify clear function. */
955 status = _nx_mdns_cache_notify_clear(mdns_ptr);
956
957 /* Return status. */
958 return(status);
959 }
960
961
962 /**************************************************************************/
963 /* */
964 /* FUNCTION RELEASE */
965 /* */
966 /* _nx_mdns_cache_notify_clear PORTABLE C */
967 /* 6.1 */
968 /* AUTHOR */
969 /* */
970 /* Yuxin Zhou, Microsoft Corporation */
971 /* */
972 /* DESCRIPTION */
973 /* */
974 /* This function set the cache full notify function. */
975 /* */
976 /* INPUT */
977 /* */
978 /* mdns_ptr Pointer to mDNS instance */
979 /* */
980 /* OUTPUT */
981 /* */
982 /* status Completion status */
983 /* */
984 /* CALLS */
985 /* */
986 /* tx_mutex_get Get the mDNS mutex */
987 /* tx_mutex_put Put the mDNS mutex */
988 /* */
989 /* CALLED BY */
990 /* */
991 /* Application Code */
992 /* */
993 /* RELEASE HISTORY */
994 /* */
995 /* DATE NAME DESCRIPTION */
996 /* */
997 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
998 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
999 /* resulting in version 6.1 */
1000 /* */
1001 /**************************************************************************/
_nx_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)1002 UINT _nx_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
1003 {
1004
1005
1006 /* Get the mDNS mutex. */
1007 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1008
1009 /* Clear the cache notify. */
1010 mdns_ptr -> nx_mdns_cache_full_notify = NX_NULL;
1011
1012 /* Release the mDNS mutex. */
1013 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1014
1015 return(NX_MDNS_SUCCESS);
1016 }
1017
1018
1019 #ifndef NX_MDNS_DISABLE_CLIENT
1020 /**************************************************************************/
1021 /* */
1022 /* FUNCTION RELEASE */
1023 /* */
1024 /* _nxe_mdns_service_ignore_set PORTABLE C */
1025 /* 6.1 */
1026 /* AUTHOR */
1027 /* */
1028 /* Yuxin Zhou, Microsoft Corporation */
1029 /* */
1030 /* DESCRIPTION */
1031 /* */
1032 /* This function checks for errors in the mDNS service ignore mask */
1033 /* set function call. */
1034 /* */
1035 /* INPUT */
1036 /* */
1037 /* mdns_ptr Pointer to mDNS instance */
1038 /* service_mask The service mask */
1039 /* */
1040 /* OUTPUT */
1041 /* */
1042 /* status Completion status */
1043 /* */
1044 /* CALLS */
1045 /* */
1046 /* _nx_mdns_service_ignore_set Actual ignore set function */
1047 /* */
1048 /* CALLED BY */
1049 /* */
1050 /* Application Code */
1051 /* */
1052 /* RELEASE HISTORY */
1053 /* */
1054 /* DATE NAME DESCRIPTION */
1055 /* */
1056 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1057 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1058 /* resulting in version 6.1 */
1059 /* */
1060 /**************************************************************************/
_nxe_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1061 UINT _nxe_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1062 {
1063
1064 UINT status;
1065
1066
1067 /* Check for invalid input pointers. */
1068 if (!mdns_ptr)
1069 {
1070 return(NX_PTR_ERROR);
1071 }
1072
1073 /* Check for invalid non pointer input. */
1074 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1075 {
1076 return(NX_MDNS_PARAM_ERROR);
1077 }
1078
1079 /* Call actual mDNS service ignore mask set function. */
1080 status = _nx_mdns_service_ignore_set(mdns_ptr, service_mask);
1081
1082 /* Return status. */
1083 return(status);
1084 }
1085
1086
1087 /**************************************************************************/
1088 /* */
1089 /* FUNCTION RELEASE */
1090 /* */
1091 /* _nx_mdns_service_ignore_set PORTABLE C */
1092 /* 6.1 */
1093 /* AUTHOR */
1094 /* */
1095 /* Yuxin Zhou, Microsoft Corporation */
1096 /* */
1097 /* DESCRIPTION */
1098 /* */
1099 /* This function sets the service mask to ignore the service. */
1100 /* */
1101 /* INPUT */
1102 /* */
1103 /* mdns_ptr Pointer to mDNS instance */
1104 /* service_mask The service mask */
1105 /* */
1106 /* OUTPUT */
1107 /* */
1108 /* status Completion status */
1109 /* */
1110 /* CALLS */
1111 /* */
1112 /* tx_mutex_get Get the MDNS mutex */
1113 /* tx_mutex_put Put the MDNS mutex */
1114 /* */
1115 /* CALLED BY */
1116 /* */
1117 /* Application Code */
1118 /* */
1119 /* RELEASE HISTORY */
1120 /* */
1121 /* DATE NAME DESCRIPTION */
1122 /* */
1123 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1124 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1125 /* resulting in version 6.1 */
1126 /* */
1127 /**************************************************************************/
_nx_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1128 UINT _nx_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1129 {
1130
1131
1132 /* Get the mDNS mutex. */
1133 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1134
1135 /* Set the service ignore mask. */
1136 mdns_ptr -> nx_mdns_service_ignore_mask = service_mask;
1137
1138 /* Release the mDNS mutex. */
1139 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1140
1141 return(NX_MDNS_SUCCESS);
1142 }
1143
1144
1145 /**************************************************************************/
1146 /* */
1147 /* FUNCTION RELEASE */
1148 /* */
1149 /* _nxe_mdns_service_notify_set PORTABLE C */
1150 /* 6.1 */
1151 /* AUTHOR */
1152 /* */
1153 /* Yuxin Zhou, Microsoft Corporation */
1154 /* */
1155 /* DESCRIPTION */
1156 /* */
1157 /* This function checks for errors in the mDNS service notify function */
1158 /* call. */
1159 /* */
1160 /* INPUT */
1161 /* */
1162 /* mdns_ptr Pointer to mDNS instance */
1163 /* service_mask The service mask */
1164 /* service_change_notify Service change notify function*/
1165 /* */
1166 /* OUTPUT */
1167 /* */
1168 /* status Completion status */
1169 /* */
1170 /* CALLS */
1171 /* */
1172 /* _nx_mdns_service_notify_set Actual mDNS service notify */
1173 /* set function */
1174 /* */
1175 /* CALLED BY */
1176 /* */
1177 /* Application Code */
1178 /* */
1179 /* RELEASE HISTORY */
1180 /* */
1181 /* DATE NAME DESCRIPTION */
1182 /* */
1183 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1184 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1185 /* resulting in version 6.1 */
1186 /* */
1187 /**************************************************************************/
_nxe_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1188 UINT _nxe_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1189 VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1190 {
1191
1192 UINT status;
1193
1194
1195 /* Check for invalid input pointers. */
1196 if (!mdns_ptr)
1197 {
1198 return(NX_PTR_ERROR);
1199 }
1200
1201 /* Check for invalid non pointer input. */
1202 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1203 {
1204 return(NX_MDNS_PARAM_ERROR);
1205 }
1206
1207 /* Call actual mDNS service notify set function. */
1208 status = _nx_mdns_service_notify_set(mdns_ptr, service_mask, service_change_notify);
1209
1210 /* Return status. */
1211 return(status);
1212 }
1213
1214
1215 /**************************************************************************/
1216 /* */
1217 /* FUNCTION RELEASE */
1218 /* */
1219 /* _nx_mdns_service_notify_set PORTABLE C */
1220 /* 6.1 */
1221 /* AUTHOR */
1222 /* */
1223 /* Yuxin Zhou, Microsoft Corporation */
1224 /* */
1225 /* DESCRIPTION */
1226 /* */
1227 /* This function set the service mask and notify callback function. */
1228 /* */
1229 /* INPUT */
1230 /* */
1231 /* mdns_ptr Pointer to mDNS instance */
1232 /* service_mask The service mask */
1233 /* service_change_notify Service change notify function*/
1234 /* */
1235 /* OUTPUT */
1236 /* */
1237 /* status Completion status */
1238 /* */
1239 /* CALLS */
1240 /* */
1241 /* tx_mutex_get Get the mDNS mutex */
1242 /* tx_mutex_put Put the mDNS mutex */
1243 /* */
1244 /* CALLED BY */
1245 /* */
1246 /* Application Code */
1247 /* */
1248 /* RELEASE HISTORY */
1249 /* */
1250 /* DATE NAME DESCRIPTION */
1251 /* */
1252 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1253 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1254 /* resulting in version 6.1 */
1255 /* */
1256 /**************************************************************************/
_nx_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1257 UINT _nx_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1258 VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1259 {
1260
1261
1262 /* Get the mDNS mutex. */
1263 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1264
1265 /* Set the service mask. */
1266 mdns_ptr -> nx_mdns_service_notify_mask = service_mask;
1267
1268 /* Assign the service change notify. */
1269 mdns_ptr -> nx_mdns_service_change_notify = service_change_notify;
1270
1271 /* Release the mDNS mutex. */
1272 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1273
1274 return(NX_MDNS_SUCCESS);
1275 }
1276
1277
1278 /**************************************************************************/
1279 /* */
1280 /* FUNCTION RELEASE */
1281 /* */
1282 /* _nxe_mdns_service_notify_clear PORTABLE C */
1283 /* 6.1 */
1284 /* AUTHOR */
1285 /* */
1286 /* Yuxin Zhou, Microsoft Corporation */
1287 /* */
1288 /* DESCRIPTION */
1289 /* */
1290 /* This function checks for errors in the mDNS service notify function */
1291 /* call. */
1292 /* */
1293 /* INPUT */
1294 /* */
1295 /* mdns_ptr Pointer to mDNS instance */
1296 /* */
1297 /* OUTPUT */
1298 /* */
1299 /* status Completion status */
1300 /* */
1301 /* CALLS */
1302 /* */
1303 /* _nx_mdns_service_notify_clear Actual service notify */
1304 /* clear function */
1305 /* */
1306 /* CALLED BY */
1307 /* */
1308 /* Application Code */
1309 /* */
1310 /* RELEASE HISTORY */
1311 /* */
1312 /* DATE NAME DESCRIPTION */
1313 /* */
1314 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1315 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1316 /* resulting in version 6.1 */
1317 /* */
1318 /**************************************************************************/
_nxe_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1319 UINT _nxe_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1320 {
1321
1322 UINT status;
1323
1324
1325 /* Check for invalid input pointers. */
1326 if (!mdns_ptr)
1327 {
1328
1329 return(NX_PTR_ERROR);
1330 }
1331
1332 /* Check for invalid non pointer input. */
1333 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1334 {
1335
1336 return(NX_MDNS_PARAM_ERROR);
1337 }
1338
1339 /* Call actual mDNS service notify clear function. */
1340 status = _nx_mdns_service_notify_clear(mdns_ptr);
1341
1342 /* Return status. */
1343 return(status);
1344 }
1345
1346
1347 /**************************************************************************/
1348 /* */
1349 /* FUNCTION RELEASE */
1350 /* */
1351 /* _nx_mdns_service_notify_clear PORTABLE C */
1352 /* 6.1 */
1353 /* AUTHOR */
1354 /* */
1355 /* Yuxin Zhou, Microsoft Corporation */
1356 /* */
1357 /* DESCRIPTION */
1358 /* */
1359 /* This function clears the service mask and notify callback function. */
1360 /* */
1361 /* INPUT */
1362 /* */
1363 /* mdns_ptr Pointer to mDNS instance */
1364 /* */
1365 /* OUTPUT */
1366 /* */
1367 /* status Completion status */
1368 /* */
1369 /* CALLS */
1370 /* */
1371 /* tx_mutex_get Get the mDNS mutex */
1372 /* tx_mutex_put Put the mDNS mutex */
1373 /* */
1374 /* CALLED BY */
1375 /* */
1376 /* Application Code */
1377 /* */
1378 /* RELEASE HISTORY */
1379 /* */
1380 /* DATE NAME DESCRIPTION */
1381 /* */
1382 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1383 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1384 /* resulting in version 6.1 */
1385 /* */
1386 /**************************************************************************/
_nx_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1387 UINT _nx_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1388 {
1389
1390
1391 /* Get the mDNS mutex. */
1392 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1393
1394 /* Clear the service mask. */
1395 mdns_ptr -> nx_mdns_service_notify_mask = 0;
1396
1397 /* Clear the service change notify. */
1398 mdns_ptr -> nx_mdns_service_change_notify = NX_NULL;
1399
1400 /* Release the mDNS mutex. */
1401 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1402
1403 return(NX_MDNS_SUCCESS);
1404 }
1405 #endif /* NX_MDNS_DISABLE_CLIENT */
1406
1407
1408 #ifndef NX_MDNS_DISABLE_SERVER
1409 /**************************************************************************/
1410 /* */
1411 /* FUNCTION RELEASE */
1412 /* */
1413 /* _nxe_mdns_service_announcement_timing_set PORTABLE C */
1414 /* 6.1 */
1415 /* AUTHOR */
1416 /* */
1417 /* Yuxin Zhou, Microsoft Corporation */
1418 /* */
1419 /* DESCRIPTION */
1420 /* */
1421 /* This function checks for errors in the mDNS announcement timing */
1422 /* set function call. */
1423 /* */
1424 /* INPUT */
1425 /* */
1426 /* mdns_ptr Pointer to mDNS instance */
1427 /* t Announcing period */
1428 /* p Announcing count */
1429 /* k Announcing factor */
1430 /* retrans_interval Announcing retransmission */
1431 /* interval */
1432 /* interval Announcing period interval */
1433 /* max_time Announcing max time */
1434 /* */
1435 /* OUTPUT */
1436 /* */
1437 /* status Completion status */
1438 /* */
1439 /* CALLS */
1440 /* */
1441 /* _nx_mdns_service_announcement_timing_set */
1442 /* Actual mDNS announcement */
1443 /* timing set function */
1444 /* */
1445 /* CALLED BY */
1446 /* */
1447 /* Application Code */
1448 /* */
1449 /* RELEASE HISTORY */
1450 /* */
1451 /* DATE NAME DESCRIPTION */
1452 /* */
1453 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1454 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1455 /* resulting in version 6.1 */
1456 /* */
1457 /**************************************************************************/
_nxe_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1458 UINT _nxe_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1459 {
1460
1461 UINT status;
1462
1463
1464 /* Check for invalid input pointers. */
1465 if ((!mdns_ptr) || (!t) || (!p) || (!k) || (!period_interval) || (!max_time))
1466 {
1467 return(NX_PTR_ERROR);
1468 }
1469
1470 /* Check for invalid non pointer input. */
1471 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1472 {
1473 return(NX_MDNS_PARAM_ERROR);
1474 }
1475
1476 /* Call actual mDNS delete service. */
1477 status = _nx_mdns_service_announcement_timing_set(mdns_ptr, t, p, k, retrans_interval, period_interval, max_time);
1478
1479 /* Return status. */
1480 return(status);
1481 }
1482
1483
1484 /**************************************************************************/
1485 /* */
1486 /* FUNCTION RELEASE */
1487 /* */
1488 /* _nx_mdns_service_announcement_timing_set PORTABLE C */
1489 /* 6.1 */
1490 /* AUTHOR */
1491 /* */
1492 /* Yuxin Zhou, Microsoft Corporation */
1493 /* */
1494 /* DESCRIPTION */
1495 /* */
1496 /* This function set the service mask and notify callback function. */
1497 /* */
1498 /* INPUT */
1499 /* */
1500 /* mdns_ptr Pointer to mDNS instance */
1501 /* t Announcing period */
1502 /* p Announcing count */
1503 /* k Announcing factor */
1504 /* retrans_interval Announcing retransmission */
1505 /* interval */
1506 /* interval Announcing period interval */
1507 /* max_time Announcing max time */
1508 /* */
1509 /* OUTPUT */
1510 /* */
1511 /* status Completion status */
1512 /* */
1513 /* CALLS */
1514 /* */
1515 /* tx_mutex_get Get the mDNS mutex */
1516 /* tx_mutex_put Put the mDNS mutex */
1517 /* */
1518 /* CALLED BY */
1519 /* */
1520 /* Application Code */
1521 /* */
1522 /* RELEASE HISTORY */
1523 /* */
1524 /* DATE NAME DESCRIPTION */
1525 /* */
1526 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1527 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1528 /* resulting in version 6.1 */
1529 /* */
1530 /**************************************************************************/
_nx_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1531 UINT _nx_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1532 {
1533
1534
1535 /* Get the mDNS mutex. */
1536 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1537
1538 /* Set the mDNS announcing period. */
1539 mdns_ptr -> nx_mdns_announcing_period = (USHORT)t;
1540
1541 /* Set the mDNS announcing count between one announcing period. */
1542 mdns_ptr -> nx_mdns_announcing_count = (UCHAR)p;
1543
1544 /* Set the mDNS announcing factor. */
1545 mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)k;
1546
1547 /* Set the mDNS announcing retransmission interval. */
1548 mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)retrans_interval;
1549
1550 /* Set the mDNS announcing period interval. */
1551 mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)period_interval;
1552
1553 /* Set the mDNS announcing max time. */
1554 mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)max_time;
1555
1556 /* Release the mDNS mutex. */
1557 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1558
1559 return(NX_MDNS_SUCCESS);
1560 }
1561 #endif /* NX_MDNS_DISABLE_SERVER */
1562
1563
1564 /**************************************************************************/
1565 /* */
1566 /* FUNCTION RELEASE */
1567 /* */
1568 /* _nxe_mdns_enable PORTABLE C */
1569 /* 6.1 */
1570 /* AUTHOR */
1571 /* */
1572 /* Yuxin Zhou, Microsoft Corporation */
1573 /* */
1574 /* DESCRIPTION */
1575 /* */
1576 /* This function checks for errors in the mDNS enable function call. */
1577 /* */
1578 /* INPUT */
1579 /* */
1580 /* mdns_ptr Pointer to mDNS instance */
1581 /* interface_index The interface index */
1582 /* */
1583 /* OUTPUT */
1584 /* */
1585 /* status Completion status */
1586 /* */
1587 /* CALLS */
1588 /* */
1589 /* _nx_mdns_enable Actual mDNS enable function */
1590 /* */
1591 /* CALLED BY */
1592 /* */
1593 /* Application Code */
1594 /* */
1595 /* RELEASE HISTORY */
1596 /* */
1597 /* DATE NAME DESCRIPTION */
1598 /* */
1599 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1600 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1601 /* resulting in version 6.1 */
1602 /* */
1603 /**************************************************************************/
_nxe_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1604 UINT _nxe_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1605 {
1606
1607 UINT status;
1608
1609
1610 /* Check for invalid input pointers. */
1611 if (!mdns_ptr)
1612 {
1613 return(NX_PTR_ERROR);
1614 }
1615
1616 /* Check for invalid non pointer input or invalid server attributes. */
1617 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1618 {
1619 return(NX_MDNS_PARAM_ERROR);
1620 }
1621
1622 /* Call actual mDNS delete service. */
1623 status = _nx_mdns_enable(mdns_ptr, interface_index);
1624
1625 /* Return status. */
1626 return(status);
1627 }
1628
1629
1630 /**************************************************************************/
1631 /* */
1632 /* FUNCTION RELEASE */
1633 /* */
1634 /* _nx_mdns_enable PORTABLE C */
1635 /* 6.1 */
1636 /* AUTHOR */
1637 /* */
1638 /* Yuxin Zhou, Microsoft Corporation */
1639 /* */
1640 /* DESCRIPTION */
1641 /* */
1642 /* This function enables the mDNS of the physical host interface by */
1643 /* interface index. */
1644 /* */
1645 /* INPUT */
1646 /* */
1647 /* mdns_ptr Pointer to mDNS instance */
1648 /* interface_index The interface index */
1649 /* */
1650 /* OUTPUT */
1651 /* */
1652 /* status Completion status */
1653 /* */
1654 /* CALLS */
1655 /* */
1656 /* tx_mutex_get Get the mDNS mutex */
1657 /* tx_mutex_put Put the mDNS mutex */
1658 /* nx_ipv4_multicast_interface_join Join the IPv4 Multicast group */
1659 /* nxd_ipv6_multicast_interface_join Join the IPv6 Multicast group */
1660 /* _nx_mdns_host_name_register Register the host name */
1661 /* _nx_mdns_timer_set Set the mDNS timer */
1662 /* */
1663 /* CALLED BY */
1664 /* */
1665 /* Application Code */
1666 /* */
1667 /* RELEASE HISTORY */
1668 /* */
1669 /* DATE NAME DESCRIPTION */
1670 /* */
1671 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1672 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1673 /* resulting in version 6.1 */
1674 /* */
1675 /**************************************************************************/
_nx_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1676 UINT _nx_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1677 {
1678
1679 UINT status;
1680
1681 #ifndef NX_MDNS_DISABLE_SERVER
1682 ULONG *head;
1683 NX_MDNS_RR *p;
1684 #endif /* NX_MDNS_DISABLE_SERVER */
1685
1686 #ifdef NX_MDNS_ENABLE_IPV6
1687 NX_INTERFACE *interface_ptr;
1688 NXD_IPV6_ADDRESS *ipv6_address;
1689 #endif /* NX_MDNS_ENABLE_IPV6 */
1690
1691 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1692 {
1693 return(NX_MDNS_PARAM_ERROR);
1694 }
1695
1696 /* Check to see if mDNS is already enabled on this interface. */
1697 if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_TRUE)
1698 {
1699 return(NX_MDNS_ALREADY_ENABLED);
1700 }
1701
1702 /* Get the mDNS mutex. */
1703 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1704
1705 /* Enable the mdns function. */
1706 mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_TRUE;
1707
1708 #ifdef NX_MDNS_ENABLE_IPV6
1709 /* Set the interface pointer. */
1710 interface_ptr = &(mdns_ptr -> nx_mdns_ip_ptr -> nx_ip_interface[interface_index]);
1711
1712 /* Find the link-local address as source adress. Get first address from interface. */
1713 ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
1714
1715 /* Loop to check the address. */
1716 while (ipv6_address)
1717 {
1718
1719 /* Check for link-local address. */
1720 if (IPv6_Address_Type(ipv6_address -> nxd_ipv6_address) & IPV6_ADDRESS_LINKLOCAL)
1721 {
1722 break;
1723 }
1724 ipv6_address = ipv6_address -> nxd_ipv6_address_next;
1725 }
1726
1727 /* Check if found the link-local address. */
1728 if(ipv6_address)
1729 {
1730
1731 /* Set the IPv6 link-local address index. */
1732 mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = ipv6_address -> nxd_ipv6_address_index;
1733 }
1734 else
1735 {
1736
1737 /* No available address, set the address index as 0xFFFFFFFF. */
1738 mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = 0xFFFFFFFF;
1739 }
1740 #endif /* NX_MDNS_ENABLE_IPV6 */
1741
1742 /* Join the group. */
1743 status = nx_ipv4_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
1744
1745 /* Check status. */
1746 if (status)
1747 {
1748
1749 /* Release the mDNS mutex. */
1750 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1751 return(status);
1752 }
1753
1754 #ifdef NX_MDNS_ENABLE_IPV6
1755 status = nxd_ipv6_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
1756
1757 /* Check status. */
1758 if (status)
1759 {
1760
1761 /* Release the mDNS mutex. */
1762 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1763 return(status);
1764 }
1765 #endif /* NX_MDNS_ENABLE_IPV6 */
1766
1767 #ifndef NX_MDNS_DISABLE_SERVER
1768
1769 /* Register the host name. */
1770 status = _nx_mdns_host_name_register(mdns_ptr, NX_TRUE, interface_index);
1771
1772 /* Check status. */
1773 if (status)
1774 {
1775
1776 /* Release the mDNS mutex. */
1777 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1778 return(status);
1779 }
1780
1781 /* Probing the all resource record wheneven a Multicast DNS responder starts up, waks up from sleep, receives an indication of a network interface "Link CHange" event.RFC6762, Section8, Page25. */
1782
1783 /* Get the header to the local buffer. */
1784 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
1785
1786 /* Set the pointer. */
1787 head = (ULONG*)(*head);
1788
1789 /* Check the resource record. */
1790 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
1791 {
1792
1793 /* Check the interface index. */
1794 if (p -> nx_mdns_rr_interface_index != interface_index)
1795 continue;
1796
1797 /* Check whether the resource record is valid. */
1798 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
1799 continue;
1800
1801 /* Check the state and delete flag, GOODBYE state and DELETE FLAG means this resource record should be deleted. */
1802 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) &&
1803 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE))
1804 {
1805
1806 /* Delete the resource records. */
1807 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
1808 continue;
1809 }
1810
1811 /* Check the resource reocrd type. */
1812 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) ||
1813 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))
1814 {
1815 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
1816 continue;
1817 }
1818
1819 /* Check the unique flag. */
1820 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
1821 {
1822 /* For a unique type, we need to probe it on the network
1823 to guarantee its uniqueness. */
1824 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
1825 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
1826 p -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
1827 }
1828 else
1829 {
1830 /* If the record is not marked as unique, start the announcement process. */
1831 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
1832 p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
1833 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
1834
1835 /* Check the announcing max time. */
1836 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
1837 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
1838 else
1839 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
1840
1841 /* Set the retransmit count. */
1842 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
1843 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
1844 else
1845 p -> nx_mdns_rr_retransmit_count = 1;
1846 }
1847
1848 /* Set the mDNS timer. */
1849 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
1850 }
1851 #endif /* NX_MDNS_DISABLE_SERVER */
1852
1853 /* Set the mdns started flag. */
1854 mdns_ptr -> nx_mdns_started = NX_TRUE;
1855
1856 /* Release the mDNS mutex. */
1857 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1858
1859 /* Return. */
1860 return(NX_MDNS_SUCCESS);
1861 }
1862
1863
1864 /**************************************************************************/
1865 /* */
1866 /* FUNCTION RELEASE */
1867 /* */
1868 /* _nxe_mdns_disable PORTABLE C */
1869 /* 6.1 */
1870 /* AUTHOR */
1871 /* */
1872 /* Yuxin Zhou, Microsoft Corporation */
1873 /* */
1874 /* DESCRIPTION */
1875 /* */
1876 /* This function checks for errors in the mDNS disable function call. */
1877 /* */
1878 /* INPUT */
1879 /* */
1880 /* mdns_ptr Pointer to mDNS instance */
1881 /* interface_index The interface index */
1882 /* */
1883 /* OUTPUT */
1884 /* */
1885 /* status Completion status */
1886 /* */
1887 /* CALLS */
1888 /* */
1889 /* _nx_mdns_disable Actual mDNS disable function */
1890 /* */
1891 /* CALLED BY */
1892 /* */
1893 /* Application Code */
1894 /* */
1895 /* RELEASE HISTORY */
1896 /* */
1897 /* DATE NAME DESCRIPTION */
1898 /* */
1899 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1900 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1901 /* resulting in version 6.1 */
1902 /* */
1903 /**************************************************************************/
_nxe_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1904 UINT _nxe_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1905 {
1906
1907 UINT status;
1908
1909
1910 /* Check for invalid input pointers. */
1911 if (!mdns_ptr)
1912 {
1913 return(NX_PTR_ERROR);
1914 }
1915
1916 /* Check for invalid non pointer input or invalid server attributes. */
1917 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1918 {
1919 return(NX_MDNS_PARAM_ERROR);
1920 }
1921
1922 /* Call actual mDNS delete service. */
1923 status = _nx_mdns_disable(mdns_ptr, interface_index);
1924
1925 /* Return status. */
1926 return(status);
1927 }
1928
1929
1930 /**************************************************************************/
1931 /* */
1932 /* FUNCTION RELEASE */
1933 /* */
1934 /* _nx_mdns_disable PORTABLE C */
1935 /* 6.1 */
1936 /* AUTHOR */
1937 /* */
1938 /* Yuxin Zhou, Microsoft Corporation */
1939 /* */
1940 /* DESCRIPTION */
1941 /* */
1942 /* This function disables the mDNS of the physical host interface by */
1943 /* interface index. */
1944 /* */
1945 /* INPUT */
1946 /* */
1947 /* mdns_ptr Pointer to mDNS instance */
1948 /* interface_index The interface index */
1949 /* */
1950 /* OUTPUT */
1951 /* */
1952 /* status Completion status */
1953 /* */
1954 /* CALLS */
1955 /* */
1956 /* tx_mutex_get Get the mDNS mutex */
1957 /* tx_mutex_put Put the mDNS mutex */
1958 /* nx_ipv4_multicast_leave Leave the IPv4 Multicast group*/
1959 /* nxd_ipv6_multicast_interface_leave Leave the IPv6 Multicast group*/
1960 /* _nx_mdns_cache_initialize Initialize the mDNS peer cache*/
1961 /* _nx_mdns_timer_set Set the mDNS timer */
1962 /* */
1963 /* CALLED BY */
1964 /* */
1965 /* Application Code */
1966 /* */
1967 /* RELEASE HISTORY */
1968 /* */
1969 /* DATE NAME DESCRIPTION */
1970 /* */
1971 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1972 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1973 /* resulting in version 6.1 */
1974 /* */
1975 /**************************************************************************/
_nx_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1976 UINT _nx_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1977 {
1978
1979 UINT dns_sd_size;
1980 UINT i;
1981 ULONG *head;
1982 NX_MDNS_RR *p;
1983
1984
1985 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1986 {
1987 return(NX_MDNS_PARAM_ERROR);
1988 }
1989
1990 /* Check to see if mDNS is not enabled on this interface.
1991 Note: Only support one interface yet. */
1992 if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_FALSE)
1993 {
1994 return(NX_MDNS_NOT_ENABLED);
1995 }
1996
1997 /* Check the DNS-SD string. */
1998 if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_size, NX_MDNS_DNS_SD_MAX))
1999 {
2000 return(NX_MDNS_DATA_SIZE_ERROR);
2001 }
2002
2003 /* Get the mDNS mutex. */
2004 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2005
2006 /* Disable the mdns function. */
2007 mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_FALSE;
2008
2009 /* Leave the group. */
2010 nx_ipv4_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
2011
2012 #ifdef NX_MDNS_ENABLE_IPV6
2013 nxd_ipv6_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
2014 #endif /* NX_MDNS_ENABLE_IPV6 */
2015
2016 #ifndef NX_MDNS_DISABLE_CLIENT
2017
2018 /* Get the local buffer head. */
2019 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
2020
2021 /* Set the pointer. */
2022 head = (ULONG*)(*head);
2023
2024 /* Delete all services on this interface. */
2025 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2026 {
2027
2028 /* Check whether the resource record is valid. */
2029 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2030 continue;
2031
2032 /* Check the interface index. */
2033 if (p -> nx_mdns_rr_interface_index != interface_index)
2034 continue;
2035
2036 /* Delete the resource record. */
2037 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
2038 }
2039 #endif /* NX_MDNS_DISABLE_CLIENT */
2040
2041 #ifndef NX_MDNS_DISABLE_SERVER
2042
2043 /* Get the local buffer head. */
2044 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2045
2046 /* Set the pointer. */
2047 head = (ULONG*)(*head);
2048
2049 /* Send the Goodbye message, RFC6762, Section10.1, Page33. */
2050 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2051 {
2052
2053 /* Check whether the resource record is valid. */
2054 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2055 continue;
2056
2057 /* Check the interface index. */
2058 if (p -> nx_mdns_rr_interface_index != interface_index)
2059 continue;
2060
2061 /* Skip the NSEC and DNS-SD PTR resource record. */
2062 if ((p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) ||
2063 ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
2064 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_size))))
2065 {
2066
2067 /* Suspend the resource record. */
2068 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
2069 }
2070 else
2071 {
2072
2073 /* Set the state to send Goodbye packet. */
2074 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
2075
2076 /* Clear the retransmit count. */
2077 p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
2078
2079 /* Set the timer count. 250ms. */
2080 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
2081
2082 /* Set the mDNS timer. */
2083 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
2084 }
2085 }
2086 #endif /* NX_MDNS_DISABLE_SERVER */
2087
2088 /* Check if all interfaces are disabled. */
2089 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
2090 {
2091 if (mdns_ptr -> nx_mdns_interface_enabled[i])
2092 break;
2093 }
2094
2095 /* Set the mdns started flag. */
2096 if (i == NX_MAX_PHYSICAL_INTERFACES)
2097 mdns_ptr -> nx_mdns_started = NX_FALSE;
2098
2099 /* Release the mDNS mutex. */
2100 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2101
2102 return(NX_MDNS_SUCCESS);
2103 }
2104
2105
2106 /**************************************************************************/
2107 /* */
2108 /* FUNCTION RELEASE */
2109 /* */
2110 /* _nxe_mdns_local_domain_set PORTABLE C */
2111 /* 6.1 */
2112 /* AUTHOR */
2113 /* */
2114 /* Yuxin Zhou, Microsoft Corporation */
2115 /* */
2116 /* DESCRIPTION */
2117 /* */
2118 /* This function checks for errors in the mDNS domain sets */
2119 /* function call. */
2120 /* */
2121 /* INPUT */
2122 /* */
2123 /* mdns_ptr Pointer to mDNS instance */
2124 /* domain_name Domain name */
2125 /* */
2126 /* OUTPUT */
2127 /* */
2128 /* status Completion status */
2129 /* */
2130 /* CALLS */
2131 /* */
2132 /* _nx_mdns_domain_name_set Actual domain set function */
2133 /* */
2134 /* CALLED BY */
2135 /* */
2136 /* Application Code */
2137 /* */
2138 /* RELEASE HISTORY */
2139 /* */
2140 /* DATE NAME DESCRIPTION */
2141 /* */
2142 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2143 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2144 /* resulting in version 6.1 */
2145 /* */
2146 /**************************************************************************/
_nxe_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2147 UINT _nxe_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2148 {
2149
2150 UINT status;
2151
2152
2153 /* Check for invalid input pointers. */
2154 if ((!mdns_ptr) || (!domain_name))
2155 {
2156 return(NX_PTR_ERROR);
2157 }
2158
2159 /* Check for invalid non pointer input or invalid server attributes. */
2160 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2161 {
2162 return(NX_MDNS_PARAM_ERROR);
2163 }
2164
2165 /* Call actual mDNS domain name set service. */
2166 status = _nx_mdns_domain_name_set(mdns_ptr, domain_name);
2167
2168 /* Return status. */
2169 return(status);
2170 }
2171
2172
2173 /**************************************************************************/
2174 /* */
2175 /* FUNCTION RELEASE */
2176 /* */
2177 /* _nx_mdns_domain_name_set PORTABLE C */
2178 /* 6.1 */
2179 /* AUTHOR */
2180 /* */
2181 /* Yuxin Zhou, Microsoft Corporation */
2182 /* */
2183 /* DESCRIPTION */
2184 /* */
2185 /* This function sets the mDNS domain name. By default is "local". */
2186 /* */
2187 /* INPUT */
2188 /* */
2189 /* mdns_ptr Pointer to mDNS instance */
2190 /* domain_name Domain name */
2191 /* */
2192 /* OUTPUT */
2193 /* */
2194 /* status Completion status */
2195 /* */
2196 /* CALLS */
2197 /* */
2198 /* tx_mutex_get Get the mDNS mutex */
2199 /* tx_mutex_put Put the mDNS mutex */
2200 /* */
2201 /* CALLED BY */
2202 /* */
2203 /* Application Code */
2204 /* */
2205 /* RELEASE HISTORY */
2206 /* */
2207 /* DATE NAME DESCRIPTION */
2208 /* */
2209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2210 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2211 /* verified memcpy use cases, */
2212 /* resulting in version 6.1 */
2213 /* */
2214 /**************************************************************************/
_nx_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2215 UINT _nx_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2216 {
2217
2218 UINT index;
2219 UINT domain_name_size;
2220
2221
2222 /* Check the size. */
2223 if (_nx_utility_string_length_check((CHAR *)domain_name, &domain_name_size, NX_MDNS_DOMAIN_NAME_MAX))
2224 {
2225 return(NX_MDNS_DATA_SIZE_ERROR);
2226 }
2227
2228 /* Get the mDNS mutex. */
2229 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2230
2231 /* Save the new domain name. */
2232 memcpy(&mdns_ptr -> nx_mdns_domain_name[0], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2233 mdns_ptr -> nx_mdns_domain_name[domain_name_size] = NX_NULL;
2234
2235 /* Initialize the struct. */
2236 memset(_nx_mdns_dns_sd, 0, NX_MDNS_DNS_SD_MAX);
2237
2238 /* Update the services dns-sd. */
2239 memcpy(_nx_mdns_dns_sd, "_services._dns-sd._udp.", (sizeof("_services._dns-sd._udp.") - 1)); /* Use case of memcpy is verified. */
2240 index = (sizeof("_services._dns-sd._udp.") - 1);
2241 memcpy(&_nx_mdns_dns_sd[index], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2242
2243 /* Release the mDNS mutex. */
2244 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2245
2246 /* Return a successful status. */
2247 return(NX_SUCCESS);
2248 }
2249
2250
2251 #ifndef NX_MDNS_DISABLE_SERVER
2252 /**************************************************************************/
2253 /* */
2254 /* FUNCTION RELEASE */
2255 /* */
2256 /* _nxe_mdns_service_add PORTABLE C */
2257 /* 6.1 */
2258 /* AUTHOR */
2259 /* */
2260 /* Yuxin Zhou, Microsoft Corporation */
2261 /* */
2262 /* DESCRIPTION */
2263 /* */
2264 /* This function checks for errors in the mDNS service add */
2265 /* function call. */
2266 /* */
2267 /* INPUT */
2268 /* */
2269 /* mdns_ptr Pointer to mDNS instance */
2270 /* name Service instance name */
2271 /* type The type of the service */
2272 /* subtype The subtype of the service */
2273 /* txt The txt string of the service */
2274 /* ttl The ttl of the service */
2275 /* priority The priority of target host */
2276 /* weights Service weight */
2277 /* port The port on this target host */
2278 /* is_unique The RR set of the service */
2279 /* interface_index The interface index */
2280 /* */
2281 /* OUTPUT */
2282 /* */
2283 /* status Completion status */
2284 /* */
2285 /* CALLS */
2286 /* */
2287 /* _nx_mdns_service_add Actual service add function */
2288 /* */
2289 /* CALLED BY */
2290 /* */
2291 /* Application Code */
2292 /* */
2293 /* RELEASE HISTORY */
2294 /* */
2295 /* DATE NAME DESCRIPTION */
2296 /* */
2297 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2298 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2299 /* resulting in version 6.1 */
2300 /* */
2301 /**************************************************************************/
_nxe_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2302 UINT _nxe_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2303 USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2304 {
2305
2306 UINT status;
2307
2308
2309 /* Check for invalid input pointers. */
2310 if (!mdns_ptr)
2311 {
2312 return(NX_PTR_ERROR);
2313 }
2314
2315 /* Check for invalid server attributes. */
2316 if ((mdns_ptr -> nx_mdns_id != NX_MDNS_ID) || (!port))
2317 {
2318 return(NX_MDNS_PARAM_ERROR);
2319 }
2320
2321 /* Check the size of the service name string. The last four characters in the
2322 service name are reserved so DNS-SD is able to append " (2)" during the conflict
2323 resolution process. */
2324 #if (NX_MDNS_SERVICE_NAME_MAX >= NX_MDNS_LABEL_MAX)
2325 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_LABEL_MAX - 4)))
2326 #else
2327 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_SERVICE_NAME_MAX - 4)))
2328 #endif
2329 {
2330 return(NX_MDNS_DATA_SIZE_ERROR);
2331 }
2332
2333 /* Check the type. */
2334 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2335 {
2336 return(NX_MDNS_DATA_SIZE_ERROR);
2337 }
2338
2339 /* Check the txt string size. */
2340 if (txt)
2341 {
2342 if (_nx_utility_string_length_check((CHAR *)txt, NX_NULL, NX_MDNS_NAME_MAX))
2343 {
2344 return(NX_MDNS_DATA_SIZE_ERROR);
2345 }
2346 }
2347
2348 /* Check the txt string size. */
2349 if (sub_type)
2350 {
2351 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
2352 {
2353 return(NX_MDNS_DATA_SIZE_ERROR);
2354 }
2355 }
2356
2357 /* Check the interface index. */
2358 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
2359 {
2360 return(NX_INVALID_INTERFACE);
2361 }
2362
2363 /* Call actual mDNS service add service. */
2364 status = _nx_mdns_service_add(mdns_ptr, name, type, sub_type, txt, ttl, priority,
2365 weights, port, is_unique, interface_index);
2366
2367 /* Return status. */
2368 return(status);
2369 }
2370
2371
2372 /**************************************************************************/
2373 /* */
2374 /* FUNCTION RELEASE */
2375 /* */
2376 /* _nx_mdns_service_add PORTABLE C */
2377 /* 6.1 */
2378 /* AUTHOR */
2379 /* */
2380 /* Yuxin Zhou, Microsoft Corporation */
2381 /* */
2382 /* DESCRIPTION */
2383 /* */
2384 /* This function adds the mDNS services, and the PTR, SRV and TXT */
2385 /* records into the local buffer. */
2386 /* */
2387 /* INPUT */
2388 /* */
2389 /* mdns_ptr Pointer to mDNS instance */
2390 /* name Service nstance name */
2391 /* type The type of the service */
2392 /* subtype The subtype of the service */
2393 /* txt The txt string of the service */
2394 /* ttl The ttl of the service */
2395 /* priority The priority of target host */
2396 /* weights Service weight */
2397 /* port The port on this target host */
2398 /* is_unique The RR set of the service */
2399 /* interface_index The interface index */
2400 /* */
2401 /* OUTPUT */
2402 /* */
2403 /* status Completion status */
2404 /* */
2405 /* CALLS */
2406 /* */
2407 /* tx_mutex_get Get the mDNS mutex */
2408 /* tx_mutex_put Put the mDNS mutex */
2409 /* _nx_mdns_service_name_assemble Assemble the service name */
2410 /* _nx_mdns_rr_srv_add Add the SRV resource record */
2411 /* _nx_mdns_rr_txt_add Add the TXT resource record */
2412 /* _nx_mdns_rr_ptr_add Add the PTR resource record */
2413 /* _nx_mdns_rr_delete Delete the resource record */
2414 /* */
2415 /* CALLED BY */
2416 /* */
2417 /* Application Code */
2418 /* */
2419 /* RELEASE HISTORY */
2420 /* */
2421 /* DATE NAME DESCRIPTION */
2422 /* */
2423 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2424 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2425 /* resulting in version 6.1 */
2426 /* */
2427 /**************************************************************************/
_nx_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2428 UINT _nx_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2429 USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2430 {
2431
2432 UINT status;
2433 UINT type_index;
2434 NX_MDNS_RR *srv_rr;
2435 NX_MDNS_RR *txt_rr;
2436 NX_MDNS_RR *ptr_rr;
2437 NX_MDNS_RR *dns_sd_rr;
2438 ULONG *head;
2439 NX_MDNS_RR *p;
2440 ULONG srv_ttl;
2441 ULONG txt_ttl;
2442 ULONG ptr_ttl;
2443 UINT string_length;
2444
2445
2446 /* Get the mDNS mutex. */
2447 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2448
2449 /* Check the ttl value. */
2450 if (ttl)
2451 {
2452
2453 /* Use user supplied TTL value if it is not zero. */
2454 srv_ttl = ttl;
2455 txt_ttl = ttl;
2456 ptr_ttl = ttl;
2457 }
2458 else
2459 {
2460
2461 /* Use the RFC recommended TTL values if user doesn't supply one. */
2462 srv_ttl = NX_MDNS_RR_TTL_HOST;
2463 txt_ttl = NX_MDNS_RR_TTL_OTHER;
2464 ptr_ttl = NX_MDNS_RR_TTL_OTHER;
2465 }
2466
2467 /* Construct the SRV name. */
2468 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2469
2470 /* Check the status. */
2471 if (status)
2472 {
2473
2474 /* Release the mDNS mutex. */
2475 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2476 return (status);
2477 }
2478
2479 /* Check string length. */
2480 if (_nx_utility_string_length_check((CHAR *)(&temp_string_buffer[0]), &string_length, NX_MDNS_NAME_MAX))
2481 {
2482
2483 /* Release the mDNS mutex. */
2484 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2485 return (NX_MDNS_DATA_SIZE_ERROR);
2486 }
2487
2488 /* Check whether the same service name exist. */
2489 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2490 head = (ULONG*)(*head);
2491
2492 /* Check the resource record. */
2493 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2494 {
2495 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2496 continue;
2497
2498 /* Check the interface. */
2499 if (p -> nx_mdns_rr_interface_index != interface_index)
2500 continue;
2501
2502 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
2503 {
2504
2505 /* Compare the service name. */
2506 if (!_nx_mdns_name_match(&temp_string_buffer[0], p -> nx_mdns_rr_name, string_length))
2507 {
2508
2509 /* Release the mDNS mutex. */
2510 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2511
2512 return(NX_MDNS_EXIST_SAME_SERVICE);
2513 }
2514 }
2515 }
2516
2517 /* Construct the SRV target name. */
2518 status = _nx_mdns_service_name_assemble(mdns_ptr -> nx_mdns_host_name, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
2519
2520 /* Check the status. */
2521 if (status)
2522 {
2523
2524 /* Release the mDNS mutex. */
2525 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2526 return (status);
2527 }
2528
2529 /* Add the SRV resource records message. */
2530 status = _nx_mdns_rr_srv_add(mdns_ptr, &temp_string_buffer[0], srv_ttl, is_unique, priority, weights, port, &target_string_buffer[0], &srv_rr, interface_index);
2531
2532 /* Check the status. */
2533 if (status)
2534 {
2535
2536 /* Release the mDNS mutex. */
2537 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2538 return(status);
2539 }
2540
2541 /* Add the TXT resource records message. */
2542 status = _nx_mdns_rr_txt_add(mdns_ptr, &temp_string_buffer[0], txt_ttl, is_unique, txt, &txt_rr, interface_index);
2543
2544 /* Check the status. */
2545 if (status)
2546 {
2547
2548 /* Delete the SRV records. */
2549 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2550
2551 /* Release the mDNS mutex. */
2552 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2553
2554 return(status);
2555 }
2556
2557 /* Add the dns-sd PTR resource records message. */
2558 status = _nx_mdns_rr_ptr_add(mdns_ptr, (UCHAR *)_nx_mdns_dns_sd, ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[type_index], NX_TRUE, &dns_sd_rr, interface_index);
2559
2560 /* Check the status. */
2561 if (status)
2562 {
2563
2564 /* Delete the TXT records. */
2565 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2566
2567 /* Delete the SRV records. */
2568 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2569
2570 /* Release the mDNS mutex. */
2571 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2572
2573 return(status);
2574 }
2575
2576 /* Add the PTR resource records message. */
2577 status = _nx_mdns_rr_ptr_add(mdns_ptr, &temp_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, &ptr_rr, interface_index);
2578
2579 /* Check the status. */
2580 if (status)
2581 {
2582
2583 /* Delete the TXT records. */
2584 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2585
2586 /* Delete the SRV records. */
2587 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2588
2589 /* Delete the DNS_SD PTR records. */
2590 _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2591
2592 /* Release the mDNS mutex. */
2593 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2594
2595 return(status);
2596 }
2597
2598 /* Add another PTR type for the subtype. */
2599 if (sub_type)
2600 {
2601
2602 /* Construct the PTR target name. */
2603 status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2604
2605 /* Check the status. */
2606 if (status)
2607 {
2608
2609 /* Release the mDNS mutex. */
2610 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2611
2612 return (status);
2613 }
2614
2615 /* Add the Sub PTR resource records message. */
2616 status = _nx_mdns_rr_ptr_add(mdns_ptr, &target_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, NX_NULL, interface_index);
2617
2618 /* Check the status. */
2619 if (status)
2620 {
2621
2622 /* Delete the PTR records. */
2623 _nx_mdns_rr_delete(mdns_ptr, ptr_rr);
2624
2625 /* Delete the DNS_SD PTR records. */
2626 _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2627
2628 /* Delete the SRV records. */
2629 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2630
2631 /* Delete the TXT records. */
2632 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2633
2634 /* Release the mDNS mutex. */
2635 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2636
2637 return(status);
2638 }
2639 }
2640
2641 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2642
2643 /* Add the NSEC resource record for service. */
2644 _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], NX_FALSE, NX_FALSE, NX_MDNS_ADD_NSEC_FOR_SERVICE, interface_index);
2645 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
2646
2647 /* Release the mDNS mutex. */
2648 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2649
2650 /* Return a successful status. */
2651 return(NX_SUCCESS);
2652 }
2653
2654
2655 /**************************************************************************/
2656 /* */
2657 /* FUNCTION RELEASE */
2658 /* */
2659 /* _nxe_mdns_service_delete PORTABLE C */
2660 /* 6.1 */
2661 /* AUTHOR */
2662 /* */
2663 /* Yuxin Zhou, Microsoft Corporation */
2664 /* */
2665 /* DESCRIPTION */
2666 /* */
2667 /* This function checks for errors in the mDNS service delete */
2668 /* function call. */
2669 /* */
2670 /* INPUT */
2671 /* */
2672 /* mdns_ptr Pointer to mDNS instance */
2673 /* name The name of the service */
2674 /* type The type of the service */
2675 /* subtype The subtype of the service */
2676 /* */
2677 /* OUTPUT */
2678 /* */
2679 /* status Completion status */
2680 /* */
2681 /* CALLS */
2682 /* */
2683 /* _nx_mdns_service_delete Actual service delete function*/
2684 /* */
2685 /* CALLED BY */
2686 /* */
2687 /* Application Code */
2688 /* */
2689 /* RELEASE HISTORY */
2690 /* */
2691 /* DATE NAME DESCRIPTION */
2692 /* */
2693 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2694 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2695 /* resulting in version 6.1 */
2696 /* */
2697 /**************************************************************************/
_nxe_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2698 UINT _nxe_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2699 {
2700
2701 UINT status;
2702
2703 /* Check for invalid input pointers. */
2704 if ((!mdns_ptr) || (!name) || (!type))
2705 {
2706 return(NX_PTR_ERROR);
2707 }
2708
2709 /* Check for invalid server attributes. */
2710 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2711 {
2712 return(NX_MDNS_PARAM_ERROR);
2713 }
2714
2715 /* Check the size. */
2716 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX) ||
2717 _nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2718 {
2719 return(NX_MDNS_DATA_SIZE_ERROR);
2720 }
2721
2722 /* Call actual mDNS service delete service. */
2723 status = _nx_mdns_service_delete(mdns_ptr, name, type, sub_type);
2724
2725 /* Return status. */
2726 return(status);
2727 }
2728
2729 /**************************************************************************/
2730 /* */
2731 /* FUNCTION RELEASE */
2732 /* */
2733 /* _nx_mdns_service_delete PORTABLE C */
2734 /* 6.1 */
2735 /* AUTHOR */
2736 /* */
2737 /* Yuxin Zhou, Microsoft Corporation */
2738 /* */
2739 /* DESCRIPTION */
2740 /* */
2741 /* This function deletes the mDNS services. */
2742 /* */
2743 /* INPUT */
2744 /* */
2745 /* mdns_ptr Pointer to mDNS instance */
2746 /* name The name of the service */
2747 /* type The type of the service */
2748 /* subtype The subtype of the service */
2749 /* */
2750 /* OUTPUT */
2751 /* */
2752 /* status Completion status */
2753 /* */
2754 /* CALLS */
2755 /* */
2756 /* _nx_mdns_service_delete_internal Actual service delete function*/
2757 /* */
2758 /* CALLED BY */
2759 /* */
2760 /* Application Code */
2761 /* */
2762 /* RELEASE HISTORY */
2763 /* */
2764 /* DATE NAME DESCRIPTION */
2765 /* */
2766 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2767 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2768 /* resulting in version 6.1 */
2769 /* */
2770 /**************************************************************************/
_nx_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2771 UINT _nx_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2772 {
2773
2774 UINT i;
2775 UINT status = NX_MDNS_NOT_ENABLED;
2776 UINT service_delete_success = NX_FALSE;
2777
2778 /* Delete service from all enabled interfaces. */
2779 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i ++)
2780 {
2781
2782 /* Call actual mDNS service delete service. */
2783 status = _nx_mdns_service_interface_delete(mdns_ptr, name, type, sub_type, i);
2784
2785 /* Check status. */
2786 if (status == NX_MDNS_SUCCESS)
2787 {
2788 service_delete_success = NX_TRUE;
2789 }
2790 }
2791
2792 /* Check if delete service on all enabled interface. */
2793 if (service_delete_success)
2794 return(NX_MDNS_SUCCESS);
2795 else
2796 return(status);
2797 }
2798
2799
2800 /**************************************************************************/
2801 /* */
2802 /* FUNCTION RELEASE */
2803 /* */
2804 /* _nx_mdns_service_interface_delete PORTABLE C */
2805 /* 6.1 */
2806 /* AUTHOR */
2807 /* */
2808 /* Yuxin Zhou, Microsoft Corporation */
2809 /* */
2810 /* DESCRIPTION */
2811 /* */
2812 /* This function deletes the mDNS services, and remove SRV and TXT */
2813 /* records from local buffer. */
2814 /* */
2815 /* INPUT */
2816 /* */
2817 /* mdns_ptr Pointer to mDNS instance */
2818 /* name The name of the service */
2819 /* type The type of the service */
2820 /* subtype The subtype of the service */
2821 /* interface_index The interface index */
2822 /* */
2823 /* OUTPUT */
2824 /* */
2825 /* status Completion status */
2826 /* */
2827 /* CALLS */
2828 /* */
2829 /* tx_mutex_get Get the mDNS mutex */
2830 /* tx_mutex_put Put the mDNS mutex */
2831 /* _nx_mdns_service_name_assemble Assemble the service name */
2832 /* _nx_mdns_name_match Match the name string */
2833 /* _nx_mdns_rr_delete Delete the resource record */
2834 /* */
2835 /* CALLED BY */
2836 /* */
2837 /* Application Code */
2838 /* */
2839 /* RELEASE HISTORY */
2840 /* */
2841 /* DATE NAME DESCRIPTION */
2842 /* */
2843 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2844 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2845 /* resulting in version 6.1 */
2846 /* */
2847 /**************************************************************************/
_nx_mdns_service_interface_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT interface_index)2848 UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index)
2849 {
2850
2851 UINT status;
2852 UINT found;
2853 UINT delete_flag;
2854 UINT type_index;
2855 ULONG *head;
2856 NX_MDNS_RR *p;
2857 UINT rr_name_length;
2858 UINT rr_ptr_name_length;
2859
2860 NX_PARAMETER_NOT_USED(sub_type);
2861
2862 /* Get the mDNS mutex. */
2863 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2864
2865 /* Initialize the parameters. */
2866 type_index = 0;
2867 delete_flag = NX_FALSE;
2868
2869 /* Construct the SRV name. */
2870 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2871
2872 /* Check the status. */
2873 if (status)
2874 {
2875
2876 /* Release the mDNS mutex. */
2877 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2878 return (status);
2879 }
2880
2881 /* Get head. */
2882 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2883 head = (ULONG*)(*head);
2884
2885 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2886 {
2887
2888 /* Clear the found value. */
2889 found = NX_FALSE;
2890
2891 /* Check the interface index. */
2892 if (p -> nx_mdns_rr_interface_index != interface_index)
2893 continue;
2894
2895 /* Check whether the resource record is valid. */
2896 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2897 continue;
2898
2899 /* Check string length. */
2900 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
2901 {
2902 continue;
2903 }
2904
2905 /* Compare the RDATA. */
2906 switch (p -> nx_mdns_rr_type)
2907 {
2908
2909 case NX_MDNS_RR_TYPE_SRV:
2910 case NX_MDNS_RR_TYPE_TXT:
2911 {
2912 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2913 {
2914 found = NX_TRUE;
2915 delete_flag = NX_TRUE;
2916 }
2917 break;
2918 }
2919 case NX_MDNS_RR_TYPE_PTR:
2920 {
2921
2922 /* Check string length. */
2923 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), &rr_ptr_name_length, NX_MDNS_NAME_MAX))
2924 {
2925 break;
2926 }
2927
2928 /* Find the PTR and Sub PTR resource record which pointer to the SRV resource record.*/
2929 if (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[0], rr_ptr_name_length))
2930 {
2931 found = NX_TRUE;
2932 }
2933
2934 /* Find one DNS-SD PRT which pointer to the PTR resource record. */
2935 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)) &&
2936 (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[type_index], rr_ptr_name_length)))
2937 {
2938
2939 /* Check the count. */
2940 if (p -> nx_mdns_rr_count)
2941 {
2942 p -> nx_mdns_rr_count --;
2943 }
2944 else
2945 {
2946
2947 /* Delete this resource record directly. */
2948 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2949 }
2950 }
2951 break;
2952 }
2953
2954 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2955 case NX_MDNS_RR_TYPE_NSEC:
2956 {
2957 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2958 {
2959
2960 /* Delete this resource record directly. */
2961 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2962 }
2963 break;
2964 }
2965 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
2966 }
2967
2968 if (found)
2969 {
2970
2971 /* Delete the resource records. */
2972 status = _nx_mdns_rr_delete(mdns_ptr, p);
2973
2974 /* Check the status. */
2975 if (status)
2976 {
2977 /* Release the mDNS mutex. */
2978 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2979
2980 return(status);
2981 }
2982 }
2983 }
2984
2985 /* Release the mDNS mutex. */
2986 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2987
2988 if (delete_flag == NX_TRUE)
2989 return(NX_MDNS_SUCCESS);
2990 else
2991 return(NX_MDNS_ERROR);
2992 }
2993 #endif /* NX_MDNS_DISABLE_SERVER */
2994
2995
2996 #ifndef NX_MDNS_DISABLE_CLIENT
2997 /**************************************************************************/
2998 /* */
2999 /* FUNCTION RELEASE */
3000 /* */
3001 /* _nxe_mdns_service_one_shot_query PORTABLE C */
3002 /* 6.1 */
3003 /* AUTHOR */
3004 /* */
3005 /* Yuxin Zhou, Microsoft Corporation */
3006 /* */
3007 /* DESCRIPTION */
3008 /* */
3009 /* This function checks for errors in the mDNS resource record query */
3010 /* add function call. */
3011 /* */
3012 /* INPUT */
3013 /* */
3014 /* mdns_ptr Pointer to mDNS instance */
3015 /* name The name of the service */
3016 /* type The type of the service */
3017 /* subtype The subtype of the service */
3018 /* service Pointer to response service */
3019 /* timeout The timeour for service query */
3020 /* */
3021 /* OUTPUT */
3022 /* */
3023 /* status Completion status */
3024 /* */
3025 /* CALLS */
3026 /* */
3027 /* _nx_mdns_service_one_shot_query Actual query service function */
3028 /* */
3029 /* CALLED BY */
3030 /* */
3031 /* Application Code */
3032 /* */
3033 /* RELEASE HISTORY */
3034 /* */
3035 /* DATE NAME DESCRIPTION */
3036 /* */
3037 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3038 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3039 /* resulting in version 6.1 */
3040 /* */
3041 /**************************************************************************/
_nxe_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3042 UINT _nxe_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3043 {
3044
3045 UINT status;
3046
3047
3048 /* Check for invalid input pointers. */
3049 if ((!mdns_ptr) || (!type) || (!service))
3050 {
3051 return(NX_PTR_ERROR);
3052 }
3053
3054 /* Check for mDNS started flag. */
3055 if (!mdns_ptr -> nx_mdns_started)
3056 {
3057 return(NX_MDNS_NOT_STARTED);
3058 }
3059
3060 /* Check for name. */
3061 if (name)
3062 {
3063
3064 /* Check the name size. */
3065 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3066 {
3067 return(NX_MDNS_DATA_SIZE_ERROR);
3068 }
3069 }
3070
3071 /* Check the type size. */
3072 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3073 {
3074 return(NX_MDNS_DATA_SIZE_ERROR);
3075 }
3076
3077 /* Check the sub type. */
3078 if (sub_type)
3079 {
3080
3081 /* Check the name size. */
3082 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3083 {
3084 return(NX_MDNS_DATA_SIZE_ERROR);
3085 }
3086 }
3087
3088 /* Call actual mDNS create service. */
3089 status = _nx_mdns_service_one_shot_query(mdns_ptr, name, type, sub_type, service, timeout);
3090
3091 /* Return status. */
3092 return(status);
3093 }
3094
3095
3096 /**************************************************************************/
3097 /* */
3098 /* FUNCTION RELEASE */
3099 /* */
3100 /* _nx_mdns_service_one_shot_query PORTABLE C */
3101 /* 6.1.11 */
3102 /* AUTHOR */
3103 /* */
3104 /* Yuxin Zhou, Microsoft Corporation */
3105 /* */
3106 /* DESCRIPTION */
3107 /* */
3108 /* This function starts service one-shot query on all enabled */
3109 /* interfaces. */
3110 /* */
3111 /* INPUT */
3112 /* */
3113 /* mdns_ptr Pointer to mDNS instance */
3114 /* name The name of the service */
3115 /* type The type of the service */
3116 /* subtype The subtype of the service */
3117 /* service Pointer to response service */
3118 /* timeout The timeour for service query */
3119 /* */
3120 /* OUTPUT */
3121 /* */
3122 /* status Completion status */
3123 /* */
3124 /* CALLS */
3125 /* */
3126 /* tx_mutex_get Get the mDNS mutex */
3127 /* tx_mutex_put Put the mDNS mutex */
3128 /* _nx_mdns_service_name_assemble Assemble the service name */
3129 /* _nx_mdns_service_name_resolve Resolve the service name */
3130 /* _nx_mdns_query Send the One Shot query */
3131 /* _nx_mdns_service_addition_info_get Get additional info of service*/
3132 /* */
3133 /* CALLED BY */
3134 /* */
3135 /* Application Code */
3136 /* */
3137 /* RELEASE HISTORY */
3138 /* */
3139 /* DATE NAME DESCRIPTION */
3140 /* */
3141 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3142 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
3143 /* verified memcpy use cases, */
3144 /* resulting in version 6.1 */
3145 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3146 /* fixed compiler warnings, */
3147 /* resulting in version 6.1.11 */
3148 /* */
3149 /**************************************************************************/
_nx_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3150 UINT _nx_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3151 {
3152
3153 UINT type_index;
3154 UINT status;
3155 NX_MDNS_RR *answer_rr;
3156 UCHAR *query_name;
3157 USHORT query_type;
3158 UINT i;
3159 UINT name_length;
3160
3161
3162 /* Get the mDNS mutex. */
3163 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3164
3165 /* Initialize the struct. */
3166 memset(service, 0, sizeof(NX_MDNS_SERVICE));
3167
3168 /* Loop to start one-shot query on all enabled interfaces until get the answer or query timeout. */
3169 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3170 {
3171
3172 /* Check if this interface is enabled. */
3173 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3174 continue;
3175
3176 /* Step1. Construct the query name and set the query type. */
3177 if (name)
3178 {
3179
3180 /* Construct the SRV name. */
3181 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3182
3183 /* Check the status. */
3184 if (status)
3185 {
3186
3187 /* Release the mDNS mutex. */
3188 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3189 return(status);
3190 }
3191
3192 /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT). */
3193 query_name = temp_string_buffer;
3194 query_type = NX_MDNS_RR_TYPE_ALL;
3195 }
3196 else
3197 {
3198
3199 /* Construct the PTR name. */
3200 status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3201
3202 /* Check the status. */
3203 if (status)
3204 {
3205
3206 /* Release the mDNS mutex. */
3207 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3208 return (status);
3209 }
3210
3211 /* Set the query name and query type. */
3212 query_name = &temp_string_buffer[type_index];
3213 query_type = NX_MDNS_RR_TYPE_PTR;
3214 }
3215
3216 /* Step2. Start one shot query. */
3217 status = _nx_mdns_one_shot_query(mdns_ptr, query_name, query_type, &answer_rr, timeout, i);
3218
3219 /* Check the status. */
3220 if ((status == NX_SUCCESS) ||
3221 (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3222 (status == NX_MDNS_EXIST_SHARED_RR))
3223 {
3224
3225 /* Check the query type. */
3226 if (name)
3227 {
3228
3229 /* Store the service name from SRV record. */
3230 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_name, &name_length, NX_MDNS_NAME_MAX))
3231 {
3232
3233 /* Release the mDNS mutex. */
3234 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3235 return (NX_MDNS_DATA_SIZE_ERROR);
3236 }
3237 memcpy((char *)(service -> buffer), (char*)(answer_rr -> nx_mdns_rr_name), name_length); /* Use case of memcpy is verified. */
3238 }
3239 else
3240 {
3241
3242 /* Store the service name from PTR record. */
3243 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &name_length, NX_MDNS_NAME_MAX))
3244 {
3245
3246 /* Release the mDNS mutex. */
3247 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3248 return (NX_MDNS_DATA_SIZE_ERROR);
3249 }
3250 memcpy((CHAR *)(service -> buffer), (CHAR *)(answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), name_length); /* Use case of memcpy is verified. */
3251 }
3252
3253 /* Get the additional information of service. */
3254 _nx_mdns_service_addition_info_get(mdns_ptr, service -> buffer, service, i);
3255
3256 /* Reslove the service name. */
3257 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
3258
3259 /* Check status. */
3260 if (status)
3261 continue;
3262
3263 /* Release the mDNS mutex. */
3264 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3265
3266 /* Return success. */
3267 return (NX_MDNS_SUCCESS);
3268 }
3269 }
3270
3271 /* Release the mDNS mutex. */
3272 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3273
3274 /* Return error. */
3275 return (NX_MDNS_ERROR);
3276 }
3277
3278
3279 /**************************************************************************/
3280 /* */
3281 /* FUNCTION RELEASE */
3282 /* */
3283 /* _nx_mdns_one_shot_query PORTABLE C */
3284 /* 6.1.11 */
3285 /* AUTHOR */
3286 /* */
3287 /* Yuxin Zhou, Microsoft Corporation */
3288 /* */
3289 /* DESCRIPTION */
3290 /* */
3291 /* This function adds the mDNS resource record into remote buffer, */
3292 /* mDNS thread send the query message. */
3293 /* */
3294 /* INPUT */
3295 /* */
3296 /* mdns_ptr Pointer to mDNS instance */
3297 /* name The resource record name */
3298 /* type The resource record type */
3299 /* out_rr Pointer to response RR */
3300 /* one_shot One shot or continuous */
3301 /* wait_option Wait option */
3302 /* */
3303 /* OUTPUT */
3304 /* */
3305 /* status Completion status */
3306 /* */
3307 /* CALLS */
3308 /* */
3309 /* tx_mutex_get Get the mDNS mutex */
3310 /* tx_mutex_put Put the mDNS mutex */
3311 /* _tx_thread_system_suspend Suspend the thread */
3312 /* _nx_mdns_query_check Check the query RR */
3313 /* _nx_mdns_cache_add_string Add the string into cache */
3314 /* _nx_mdns_cache_delete_string Delete the string from cache */
3315 /* _nx_mdns_cache_add_resource_record Add the resource record */
3316 /* into cache */
3317 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
3318 /* from cache */
3319 /* */
3320 /* CALLED BY */
3321 /* */
3322 /* Application Code */
3323 /* */
3324 /* RELEASE HISTORY */
3325 /* */
3326 /* DATE NAME DESCRIPTION */
3327 /* */
3328 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3329 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3330 /* resulting in version 6.1 */
3331 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3332 /* corrected the random value, */
3333 /* fixed the issue of timer, */
3334 /* resulting in version 6.1.11 */
3335 /* */
3336 /**************************************************************************/
_nx_mdns_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,NX_MDNS_RR ** out_rr,ULONG wait_option,UINT interface_index)3337 static UINT _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index)
3338 {
3339
3340 UINT status;
3341 NX_MDNS_RR *rr;
3342 NX_MDNS_RR *insert_rr;
3343 NX_MDNS_RR temp_resource_record;
3344 UINT name_length;
3345
3346
3347 /* Clear the return record. */
3348 *out_rr = NX_NULL;
3349
3350 /* Check the query RR. */
3351 status = _nx_mdns_query_check(mdns_ptr, name, type, NX_TRUE, &rr, interface_index);
3352
3353 /* Check the state. */
3354 if (status)
3355 {
3356
3357 /* Whether exists unique resource record in cache. */
3358 if ((status == NX_MDNS_EXIST_UNIQUE_RR) ||
3359 (status == NX_MDNS_EXIST_SHARED_RR))
3360 {
3361 *out_rr = rr;
3362 return (NX_MDNS_SUCCESS);
3363 }
3364 else
3365 {
3366 return(status);
3367 }
3368 }
3369
3370 if (wait_option != 0)
3371 {
3372
3373 /* Initialize the struct. */
3374 memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3375
3376 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3377 {
3378 return (NX_MDNS_DATA_SIZE_ERROR);
3379 }
3380
3381 /* Add the name. */
3382 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3383 (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3384
3385 /* Check for error. */
3386 if (status)
3387 {
3388 return(status);
3389 }
3390
3391 /* Add the parameters. */
3392 temp_resource_record.nx_mdns_rr_type = type;
3393 temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3394
3395 /* Set the resource record status. */
3396 temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3397
3398 /* Remote resource record, set the owner flag. */
3399 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3400
3401 /* Set the interface index. */
3402 temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3403
3404 /* Add the resource record. */
3405 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3406
3407 /* Check for error. */
3408 if (status)
3409 {
3410
3411 /* Delete the same strings. */
3412 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3413 return(status);
3414 }
3415
3416 /* A multicast DNS querier should also delay the first query of the series by
3417 a randomly chosen amount in the range 20-120ms. */
3418 insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3419 insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3420
3421 /* Set the mDNS timer. */
3422 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3423
3424 /* Release the mDNS mutex to process response. */
3425 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3426
3427 /* Suspend the thread on this mDNS query attempt. */
3428 _nx_mdns_query_thread_suspend(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), _nx_mdns_query_cleanup, mdns_ptr, out_rr, wait_option);
3429
3430 /* Get the mDNS mutex. */
3431 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3432
3433 /* Determine if a packet was received successfully. */
3434 if (_tx_thread_current_ptr -> tx_thread_suspend_status != NX_MDNS_SUCCESS)
3435 {
3436
3437 /* Delete the query resource record. */
3438 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, insert_rr);
3439 }
3440
3441 /* Return the status. */
3442 return(_tx_thread_current_ptr -> tx_thread_suspend_status);
3443 }
3444 else
3445 {
3446
3447 /* Immediate return, return error completion. */
3448 return(NX_MDNS_NO_RR);
3449 }
3450 }
3451
3452
3453 /**************************************************************************/
3454 /* */
3455 /* FUNCTION RELEASE */
3456 /* */
3457 /* _nxe_mdns_service_continuous_query PORTABLE C */
3458 /* 6.1 */
3459 /* AUTHOR */
3460 /* */
3461 /* Yuxin Zhou, Microsoft Corporation */
3462 /* */
3463 /* DESCRIPTION */
3464 /* */
3465 /* This function checks for errors in the mDNS resource record query */
3466 /* add function call. */
3467 /* */
3468 /* INPUT */
3469 /* */
3470 /* mdns_ptr Pointer to mDNS instance */
3471 /* name The name of the service */
3472 /* type The type of the service */
3473 /* subtype The subtype of the service */
3474 /* */
3475 /* OUTPUT */
3476 /* */
3477 /* status Completion status */
3478 /* */
3479 /* CALLS */
3480 /* */
3481 /* _nx_mdns_service_continuous_query Actual mDNS query RR function */
3482 /* */
3483 /* CALLED BY */
3484 /* */
3485 /* Application Code */
3486 /* */
3487 /* RELEASE HISTORY */
3488 /* */
3489 /* DATE NAME DESCRIPTION */
3490 /* */
3491 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3492 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3493 /* resulting in version 6.1 */
3494 /* */
3495 /**************************************************************************/
_nxe_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3496 UINT _nxe_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3497 {
3498
3499 UINT status;
3500
3501
3502 /* Check for invalid input pointers. */
3503 if (!mdns_ptr)
3504 {
3505 return(NX_PTR_ERROR);
3506 }
3507
3508 /* Check for invalid server attributes. */
3509 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3510 {
3511 return(NX_MDNS_PARAM_ERROR);
3512 }
3513
3514 /* Check for mDNS stareted flag. */
3515 if (!mdns_ptr -> nx_mdns_started)
3516 {
3517 return(NX_MDNS_NOT_STARTED);
3518 }
3519
3520 /* Check the type. If the type is null,indicate lookup the all service type, the name and sub type must be null. */
3521 if (!type)
3522 {
3523 if ((name) || (sub_type))
3524 {
3525 return(NX_MDNS_PARAM_ERROR);
3526 }
3527 }
3528 else
3529 {
3530
3531 /* Check the name, If the name is non-null, the sub type must be null. */
3532 if ((name) && (sub_type))
3533 {
3534 return(NX_MDNS_PARAM_ERROR);
3535 }
3536 }
3537
3538 /* Check the name. */
3539 if (name)
3540 {
3541
3542 /* Check the name size. */
3543 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3544 {
3545 return(NX_MDNS_DATA_SIZE_ERROR);
3546 }
3547 }
3548
3549 /* Check the type. */
3550 if (type)
3551 {
3552
3553 /* Check the type size. */
3554 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3555 {
3556 return(NX_MDNS_DATA_SIZE_ERROR);
3557 }
3558 }
3559
3560 /* Check the sub type. */
3561 if (sub_type)
3562 {
3563
3564 /* Check the sub type size. */
3565 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3566 {
3567 return(NX_MDNS_DATA_SIZE_ERROR);
3568 }
3569 }
3570
3571 /* Call actual mDNS create service. */
3572 status = _nx_mdns_service_continuous_query(mdns_ptr, name, type, sub_type);
3573
3574 /* Return status. */
3575 return(status);
3576 }
3577
3578
3579 /**************************************************************************/
3580 /* */
3581 /* FUNCTION RELEASE */
3582 /* */
3583 /* _nx_mdns_service_continuous_query PORTABLE C */
3584 /* 6.1 */
3585 /* AUTHOR */
3586 /* */
3587 /* Yuxin Zhou, Microsoft Corporation */
3588 /* */
3589 /* DESCRIPTION */
3590 /* */
3591 /* This function starts service continuous query on all enabled */
3592 /* interfaces. */
3593 /* */
3594 /* INPUT */
3595 /* */
3596 /* mdns_ptr Pointer to mDNS instance */
3597 /* name The name of the service */
3598 /* type The type of the service */
3599 /* subtype The subtype of the service */
3600 /* */
3601 /* OUTPUT */
3602 /* */
3603 /* status Completion status */
3604 /* */
3605 /* CALLS */
3606 /* */
3607 /* tx_mutex_get Get the mDNS mutex */
3608 /* tx_mutex_put Put the mDNS mutex */
3609 /* _nx_mdns_service_name_assemble Assemble the service name */
3610 /* _nx_mdns_service_name_resolve Resolve the service name */
3611 /* _nx_mdns_query Send the One Shot query */
3612 /* _nx_mdns_service_addition_info_get Get additional info of service*/
3613 /* */
3614 /* CALLED BY */
3615 /* */
3616 /* Application Code */
3617 /* */
3618 /* RELEASE HISTORY */
3619 /* */
3620 /* DATE NAME DESCRIPTION */
3621 /* */
3622 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3623 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3624 /* resulting in version 6.1 */
3625 /* */
3626 /**************************************************************************/
_nx_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3627 UINT _nx_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3628 {
3629
3630 UINT status = NX_MDNS_ERROR;
3631 UINT type_index;
3632 UCHAR *query_name;
3633 USHORT query_type;
3634 UINT query_success = NX_FALSE;
3635 UINT i;
3636
3637
3638 /* Get the mDNS mutex. */
3639 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3640
3641 /* Step1. Construct the query name and set the query type. */
3642 /* Check the type. if the type is null, indicate search all service. */
3643 if (!type)
3644 {
3645
3646 /* Set the query name and query type. */
3647 query_name = (UCHAR *)_nx_mdns_dns_sd;
3648 query_type = NX_MDNS_RR_TYPE_PTR;
3649 }
3650 else if (name)
3651 {
3652
3653 /* Construct the SRV name. */
3654 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3655
3656 /* Check the status. */
3657 if (status)
3658 {
3659
3660 /* Release the mDNS mutex. */
3661 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3662 return (status);
3663 }
3664
3665 /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT). */
3666 query_name = temp_string_buffer;
3667 query_type = NX_MDNS_RR_TYPE_ALL;
3668 }
3669 else
3670 {
3671
3672 /* Construct the PTR name. */
3673 status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3674
3675 /* Check the status. */
3676 if (status)
3677 {
3678
3679 /* Release the mDNS mutex. */
3680 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3681 return (status);
3682 }
3683
3684 /* Set the query name and query type. */
3685 query_name = &temp_string_buffer[type_index];
3686 query_type = NX_MDNS_RR_TYPE_PTR;
3687 }
3688
3689 /* Step2. Loop to start continuous query on all enabled interfaces. */
3690 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3691 {
3692
3693 /* Check if this interface is enabled. */
3694 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3695 continue;
3696
3697 /* Start continuous query. */
3698 status = _nx_mdns_continuous_query(mdns_ptr, query_name, query_type, i);
3699
3700 /* Check the status. */
3701 if ((status == NX_SUCCESS) ||
3702 (status == NX_MDNS_EXIST_SAME_QUERY) ||
3703 (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3704 (status == NX_MDNS_EXIST_SHARED_RR))
3705 query_success = NX_TRUE;
3706 }
3707
3708 /* Release the mDNS mutex. */
3709 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3710
3711 /* Check if start continuous query success. */
3712 if (query_success)
3713 return (NX_MDNS_SUCCESS);
3714 else
3715 return(status);
3716 }
3717
3718
3719 /**************************************************************************/
3720 /* */
3721 /* FUNCTION RELEASE */
3722 /* */
3723 /* _nx_mdns_continuous_query PORTABLE C */
3724 /* 6.1.11 */
3725 /* AUTHOR */
3726 /* */
3727 /* Yuxin Zhou, Microsoft Corporation */
3728 /* */
3729 /* DESCRIPTION */
3730 /* */
3731 /* This function starts continuous query on specified interfaces. */
3732 /* */
3733 /* INPUT */
3734 /* */
3735 /* mdns_ptr Pointer to mDNS instance */
3736 /* interface_index The interface index */
3737 /* name The resource record name */
3738 /* type The resource record type */
3739 /* */
3740 /* OUTPUT */
3741 /* */
3742 /* status Completion status */
3743 /* */
3744 /* CALLS */
3745 /* */
3746 /* tx_mutex_get Get the mDNS mutex */
3747 /* tx_mutex_put Put the mDNS mutex */
3748 /* _nx_mdns_query_check Check the query RR */
3749 /* _nx_mdns_cache_add_string Add the string into cache */
3750 /* _nx_mdns_cache_delete_string Delete the string from cache */
3751 /* _nx_mdns_cache_add_resource_record Add the resource record */
3752 /* into cache */
3753 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
3754 /* from cache */
3755 /* */
3756 /* CALLED BY */
3757 /* */
3758 /* Application Code */
3759 /* */
3760 /* RELEASE HISTORY */
3761 /* */
3762 /* DATE NAME DESCRIPTION */
3763 /* */
3764 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3765 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3766 /* resulting in version 6.1 */
3767 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3768 /* corrected the random value, */
3769 /* fixed the issue of timer, */
3770 /* resulting in version 6.1.11 */
3771 /* */
3772 /**************************************************************************/
_nx_mdns_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT interface_index)3773 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index)
3774 {
3775
3776 UINT status;
3777 NX_MDNS_RR *insert_rr;
3778 NX_MDNS_RR temp_resource_record;
3779 UINT name_length;
3780
3781
3782 /* Check the query RR. */
3783 status = _nx_mdns_query_check(mdns_ptr, name, type, NX_FALSE, NX_NULL, interface_index);
3784
3785 /* Check the state. */
3786 if (status)
3787 {
3788 return(status);
3789 }
3790
3791 /* Initialize the struct. */
3792 memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3793
3794 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3795 {
3796 return (NX_MDNS_DATA_SIZE_ERROR);
3797 }
3798
3799 /* Add the name. */
3800 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3801 (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3802
3803 /* Check for error. */
3804 if (status)
3805 {
3806 return(status);
3807 }
3808
3809 /* Add the parameters. */
3810 temp_resource_record.nx_mdns_rr_type = type;
3811 temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3812
3813 /* Set the resource record status. */
3814 temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3815
3816 /* Remote resource record, set the owner flag. */
3817 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3818
3819 /* Continuous query, set the query type flag. */
3820 if ((type != NX_MDNS_RR_TYPE_A) &&
3821 (type != NX_MDNS_RR_TYPE_AAAA))
3822 {
3823 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_CONTINUOUS_QUERY);
3824 }
3825
3826 /* Set the interface index. */
3827 temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3828
3829 /* Add the resource record. */
3830 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3831
3832 /* Check for error. */
3833 if (status)
3834 {
3835
3836 /* Delete the same strings. */
3837 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3838 return(status);
3839 }
3840
3841 /* A multicast DNS querier should also delay the first query of the series by
3842 a randomly chosen amount in the range 20-120ms. */
3843 insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3844 insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3845
3846 /* Set the mDNS timer. */
3847 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3848
3849 /* Return success. */
3850 return NX_SUCCESS;
3851 }
3852
3853
3854 /**************************************************************************/
3855 /* */
3856 /* FUNCTION RELEASE */
3857 /* */
3858 /* _nxe_mdns_service_query_stop PORTABLE C */
3859 /* 6.1 */
3860 /* AUTHOR */
3861 /* */
3862 /* Yuxin Zhou, Microsoft Corporation */
3863 /* */
3864 /* DESCRIPTION */
3865 /* */
3866 /* This function checks for errors in the mDNS resource record query */
3867 /* add function call. */
3868 /* */
3869 /* INPUT */
3870 /* */
3871 /* mdns_ptr Pointer to mDNS instance */
3872 /* name The name of the service */
3873 /* type The type of the service */
3874 /* subtype The subtype of the service */
3875 /* */
3876 /* OUTPUT */
3877 /* */
3878 /* status Completion status */
3879 /* */
3880 /* CALLS */
3881 /* */
3882 /* _nx_mdns_service_query_stop Actual query RR function */
3883 /* */
3884 /* CALLED BY */
3885 /* */
3886 /* Application Code */
3887 /* */
3888 /* RELEASE HISTORY */
3889 /* */
3890 /* DATE NAME DESCRIPTION */
3891 /* */
3892 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3893 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3894 /* resulting in version 6.1 */
3895 /* */
3896 /**************************************************************************/
_nxe_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3897 UINT _nxe_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3898 {
3899
3900 UINT status;
3901
3902
3903 /* Check for invalid input pointers. */
3904 if (!mdns_ptr)
3905 {
3906 return(NX_PTR_ERROR);
3907 }
3908
3909 /* Check for invalid server attributes. */
3910 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3911 {
3912 return(NX_MDNS_PARAM_ERROR);
3913 }
3914
3915 if (name)
3916 {
3917
3918 /* Check the size. */
3919 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
3920 {
3921 return(NX_MDNS_DATA_SIZE_ERROR);
3922 }
3923 }
3924
3925 /* Call actual mDNS create service. */
3926 status = _nx_mdns_service_query_stop(mdns_ptr, name, type, sub_type);
3927
3928 /* Return status. */
3929 return(status);
3930 }
3931
3932
3933 /**************************************************************************/
3934 /* */
3935 /* FUNCTION RELEASE */
3936 /* */
3937 /* _nx_mdns_service_query_stop PORTABLE C */
3938 /* 6.1 */
3939 /* AUTHOR */
3940 /* */
3941 /* Yuxin Zhou, Microsoft Corporation */
3942 /* */
3943 /* DESCRIPTION */
3944 /* */
3945 /* This function adds the mDNS resource record into peer service cache,*/
3946 /* mDNS thread send the query message using continuous type. */
3947 /* */
3948 /* INPUT */
3949 /* */
3950 /* mdns_ptr Pointer to mDNS instance */
3951 /* name The name of the service */
3952 /* type The type of the service */
3953 /* subtype The subtype of the service */
3954 /* */
3955 /* OUTPUT */
3956 /* */
3957 /* status Completion status */
3958 /* */
3959 /* CALLS */
3960 /* */
3961 /* tx_mutex_get Get the mDNS mutex */
3962 /* tx_mutex_put Put the mDNS mutex */
3963 /* _nx_mdns_service_name_assemble Assemble the service name */
3964 /* _nx_mdns_name_match Match the name string */
3965 /* _nx_mdns_rr_delete Delete the resource record */
3966 /* */
3967 /* CALLED BY */
3968 /* */
3969 /* Application Code */
3970 /* */
3971 /* RELEASE HISTORY */
3972 /* */
3973 /* DATE NAME DESCRIPTION */
3974 /* */
3975 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3976 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3977 /* resulting in version 6.1 */
3978 /* */
3979 /**************************************************************************/
_nx_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3980 UINT _nx_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3981 {
3982
3983 UINT status;
3984 UINT type_index = 0;
3985 UINT query_stop = NX_FALSE;
3986 ULONG *head;
3987 NX_MDNS_RR *p;
3988 UINT rr_name_length;
3989
3990
3991 /* Get the mDNS mutex. */
3992 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3993
3994 if (type)
3995 {
3996 if (name)
3997 {
3998
3999 /* Construct the SRV name. */
4000 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4001
4002 /* Check the status. */
4003 if (status)
4004 {
4005
4006 /* Release the mDNS mutex. */
4007 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4008 return (status);
4009 }
4010 }
4011 else
4012 {
4013
4014 /* Construct the PTR name. */
4015 status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4016
4017 /* Check the status. */
4018 if (status)
4019 {
4020
4021 /* Release the mDNS mutex. */
4022 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4023 return (status);
4024 }
4025 }
4026 }
4027
4028 /* Get the remote buffer head. */
4029 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4030
4031 if (!head)
4032 {
4033
4034 /* Release the mDNS mutex. */
4035 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4036
4037 /* Return a successful status. */
4038 return(NX_MDNS_CACHE_ERROR);
4039 }
4040
4041 /* Set the pointer. */
4042 head = (ULONG*)(*head);
4043
4044 /* Loop to delete query resource record. */
4045 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
4046 {
4047
4048 /* Check the resource record state. */
4049 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
4050 continue;
4051
4052 /* Check string length. */
4053 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
4054 {
4055 continue;
4056 }
4057
4058 if (!type)
4059 {
4060 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
4061 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
4062 {
4063
4064 /* Delete the resource records. */
4065 status = _nx_mdns_rr_delete(mdns_ptr, p);
4066
4067 /* Check status. */
4068 if (status == NX_MDNS_SUCCESS)
4069 query_stop = NX_TRUE;
4070 }
4071 }
4072 else
4073 {
4074 if (name)
4075 {
4076 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) &&
4077 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length)))
4078 {
4079
4080 /* Delete the resource records. */
4081 status = _nx_mdns_rr_delete(mdns_ptr, p);
4082
4083 /* Check status. */
4084 if (status == NX_MDNS_SUCCESS)
4085 query_stop = NX_TRUE;
4086 }
4087 }
4088 else
4089 {
4090 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)&&
4091 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[type_index], rr_name_length)))
4092 {
4093
4094 /* Delete the resource records. */
4095 status = _nx_mdns_rr_delete(mdns_ptr, p);
4096
4097 /* Check status. */
4098 if (status == NX_MDNS_SUCCESS)
4099 query_stop = NX_TRUE;
4100 }
4101 }
4102 }
4103 }
4104
4105 /* Release the mDNS mutex. */
4106 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4107
4108 /* Check if stop service continuous query. */
4109 if (query_stop == NX_TRUE)
4110 return(NX_MDNS_SUCCESS);
4111 else
4112 return(NX_MDNS_ERROR);
4113 }
4114
4115
4116 /**************************************************************************/
4117 /* */
4118 /* FUNCTION RELEASE */
4119 /* */
4120 /* _nxe_mdns_service_lookup PORTABLE C */
4121 /* 6.1 */
4122 /* AUTHOR */
4123 /* */
4124 /* Yuxin Zhou, Microsoft Corporation */
4125 /* */
4126 /* DESCRIPTION */
4127 /* */
4128 /* This function checks for errors in the mDNS resource record query */
4129 /* add function call. */
4130 /* */
4131 /* INPUT */
4132 /* */
4133 /* mdns_ptr Pointer to mDNS instance */
4134 /* name The name of the service */
4135 /* type The type of the service */
4136 /* subtype The subtype of the service */
4137 /* service_index The index of the service */
4138 /* service Pointer to Service instance */
4139 /* */
4140 /* OUTPUT */
4141 /* */
4142 /* status Completion status */
4143 /* */
4144 /* CALLS */
4145 /* */
4146 /* _nx_mdns_service_lookup Actual mDNS query RR function */
4147 /* */
4148 /* CALLED BY */
4149 /* */
4150 /* Application Code */
4151 /* */
4152 /* RELEASE HISTORY */
4153 /* */
4154 /* DATE NAME DESCRIPTION */
4155 /* */
4156 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4157 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4158 /* resulting in version 6.1 */
4159 /* */
4160 /**************************************************************************/
_nxe_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4161 UINT _nxe_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4162 {
4163
4164 UINT status;
4165
4166
4167 /* Check for invalid input pointers. */
4168 if (!mdns_ptr)
4169 {
4170 return(NX_PTR_ERROR);
4171 }
4172
4173 /* Check for invalid server attributes. */
4174 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4175 {
4176 return(NX_MDNS_PARAM_ERROR);
4177 }
4178
4179 if (name)
4180 {
4181
4182 /* Check the size. */
4183 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
4184 {
4185 return(NX_MDNS_DATA_SIZE_ERROR);
4186 }
4187 }
4188
4189 /* Call actual mDNS create service. */
4190 status = _nx_mdns_service_lookup(mdns_ptr, name, type, sub_type, service_index, service);
4191
4192 /* Return status. */
4193 return(status);
4194 }
4195
4196
4197 /**************************************************************************/
4198 /* */
4199 /* FUNCTION RELEASE */
4200 /* */
4201 /* _nx_mdns_service_lookup PORTABLE C */
4202 /* 6.1.11 */
4203 /* AUTHOR */
4204 /* */
4205 /* Yuxin Zhou, Microsoft Corporation */
4206 /* */
4207 /* DESCRIPTION */
4208 /* */
4209 /* This function adds the mDNS resource record into peer service cache,*/
4210 /* mDNS thread send the query message using continuous type. */
4211 /* */
4212 /* INPUT */
4213 /* */
4214 /* mdns_ptr Pointer to mDNS instance */
4215 /* name The name of the service */
4216 /* type The type of the service */
4217 /* subtype The subtype of the service */
4218 /* service_index The index of the service */
4219 /* service Pointer to Service instance */
4220 /* */
4221 /* OUTPUT */
4222 /* */
4223 /* status Completion status */
4224 /* */
4225 /* CALLS */
4226 /* */
4227 /* tx_mutex_get Get the mDNS mutex */
4228 /* tx_mutex_put Put the mDNS mutex */
4229 /* tx_time_get Get the time */
4230 /* _nx_mdns_service_name_assemble Assemble the service name */
4231 /* _nx_mdns_service_name_resolve Resolve the service name */
4232 /* _nx_mdns_service_addition_info_get Get additional info of service*/
4233 /* _nx_mdns_name_match Match the name string */
4234 /* */
4235 /* CALLED BY */
4236 /* */
4237 /* Application Code */
4238 /* */
4239 /* RELEASE HISTORY */
4240 /* */
4241 /* DATE NAME DESCRIPTION */
4242 /* */
4243 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4244 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4245 /* verified memcpy use cases, */
4246 /* resulting in version 6.1 */
4247 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
4248 /* fixed compiler warnings, */
4249 /* resulting in version 6.1.11 */
4250 /* */
4251 /**************************************************************************/
_nx_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4252 UINT _nx_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4253 {
4254
4255 UINT status;
4256 UINT type_index;
4257 UINT dns_sd_flag;
4258 UINT sub_type_flag;
4259 UINT index;
4260 UINT count;
4261 UINT found;
4262 UCHAR *srv_name = NX_NULL;
4263 UCHAR *ptr;
4264 UCHAR *tmp_sub_type;
4265 UCHAR *tmp_type;
4266 UCHAR *tmp_domain;
4267 NX_MDNS_RR *p = NX_NULL;
4268 NX_MDNS_RR *p1;
4269 ULONG *head, *tail;
4270 UCHAR i;
4271 UINT interface_index = 0;
4272 UINT temp_string_length;
4273 UINT dns_sd_length;
4274 UINT srv_name_length;
4275 UINT target_string_length;
4276
4277
4278 /* Get the mDNS mutex. */
4279 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4280
4281 /* Zero out the content of service */
4282 memset(service, 0, sizeof(NX_MDNS_SERVICE));
4283
4284 /* Initialize the struct. */
4285 count = 0;
4286 found = NX_FALSE;
4287
4288 /* Check the type. */
4289 if (type)
4290 {
4291 if (name)
4292 {
4293
4294 /* Construct the Service name. */
4295 status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4296
4297 }
4298 else
4299 {
4300
4301 /* Construct the Service name. */
4302 status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4303 }
4304 /* Check the status. */
4305 if (status)
4306 {
4307
4308 /* Release the mDNS mutex. */
4309 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4310 return (status);
4311 }
4312
4313 /* Check string length. */
4314 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
4315 {
4316
4317 /* Release the mDNS mutex. */
4318 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4319 return (NX_MDNS_DATA_SIZE_ERROR);
4320 }
4321 }
4322
4323 /* Check the DNS-SD string. */
4324 if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_length, NX_MDNS_DNS_SD_MAX))
4325 {
4326
4327 /* Release the mDNS mutex. */
4328 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4329 return (NX_MDNS_DATA_SIZE_ERROR);
4330 }
4331
4332 /* Loop to search local and peer cache. */
4333 for(i = 0; i < 2; i++)
4334 {
4335
4336 /* Set the pointer. */
4337 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
4338 {
4339 #ifndef NX_MDNS_DISABLE_SERVER
4340 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
4341 #else
4342 continue;
4343 #endif /* NX_MDNS_DISABLE_SERVER */
4344 }
4345 else
4346 {
4347 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4348 }
4349
4350 if(head == NX_NULL)
4351 continue;
4352
4353 /* Set the pointer. */
4354 tail = (ULONG*)(*head);
4355
4356 /* Check the resource record. */
4357 for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
4358 {
4359
4360 /* Check whether the resource record is valid. */
4361 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4362 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4363 continue;
4364
4365 if((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) || (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4366 {
4367
4368 if(type)
4369 {
4370 if (_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], temp_string_length))
4371 continue;
4372 }
4373 else if(p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
4374 continue;
4375
4376 if(name && (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4377 {
4378
4379 /* Store the service name. */
4380 srv_name = p -> nx_mdns_rr_name;
4381 interface_index = p -> nx_mdns_rr_interface_index;
4382 }
4383 else
4384 {
4385
4386 /* Set the service name pointer. */
4387 srv_name = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name;
4388 interface_index = p -> nx_mdns_rr_interface_index;
4389 }
4390
4391 /* Check string length. */
4392 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
4393 continue;
4394
4395 /* Store the service name. */
4396 memcpy((CHAR *)(service -> buffer), (CHAR *)srv_name, srv_name_length + 1); /* Use case of memcpy is verified. */
4397
4398 /* Reslove the service name and check the PTR rdata name. Ignore the PTR when the PTR rdata does not pointer the service. */
4399 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
4400
4401 if (status)
4402 continue;
4403
4404 if(type == NX_NULL)
4405 {
4406
4407 /* Set the parameters. */
4408 sub_type_flag = NX_FALSE;
4409 dns_sd_flag = NX_FALSE;
4410 index = 0;
4411
4412 /* Check the PTR resource record with sub type. */
4413 ptr = p -> nx_mdns_rr_name;
4414 while (*ptr != '\0')
4415 {
4416 if (*ptr == '.')
4417 {
4418 if (!_nx_mdns_name_match(ptr - index, (UCHAR *)"_sub", 4))
4419 {
4420 sub_type_flag = NX_TRUE;
4421 break;
4422 }
4423 index = 0;
4424 }
4425 else
4426 index ++;
4427 ptr ++;
4428 }
4429 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_length))
4430 {
4431 dns_sd_flag = NX_TRUE;
4432 }
4433
4434 /* Check the DNS-SD PTR reousrce record. */
4435 if ((dns_sd_flag == NX_TRUE) ||
4436 (sub_type_flag == NX_TRUE))
4437 {
4438
4439 /* Find the PTR resource record which pointer to the service. */
4440 for(p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
4441 {
4442
4443 /* Check whether the resource record is valid. */
4444 if ((p1 == p) ||
4445 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4446 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4447 continue;
4448
4449 /* Check the interface index. */
4450 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
4451 continue;
4452
4453 if (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
4454 {
4455 if ((dns_sd_flag == NX_TRUE))
4456 {
4457
4458 /* Check string length. */
4459 if (_nx_utility_string_length_check((CHAR *)(p1 -> nx_mdns_rr_name), &target_string_length, NX_MDNS_NAME_MAX))
4460 {
4461 continue;
4462 }
4463
4464 /* Set the pointer. */
4465 memcpy((CHAR *)&target_string_buffer[0], (CHAR *)(p1 -> nx_mdns_rr_name), target_string_length + 1); /* Use case of memcpy is verified. */
4466
4467 /* Reslove the type. */
4468 status = _nx_mdns_service_name_resolve(&target_string_buffer[0], &tmp_sub_type, &tmp_type, &tmp_domain);
4469
4470 if (status)
4471 continue;
4472
4473 /* Check string length. */
4474 if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4475 {
4476 continue;
4477 }
4478
4479 /* Construct the type and doamin, _http._tcp.local. */
4480 *(tmp_type + target_string_length) = '.';
4481
4482 /* Check string length. */
4483 if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4484 {
4485 continue;
4486 }
4487
4488 /* Compare the DNS_SD rdata. */
4489 if (!_nx_mdns_name_match(tmp_type, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, target_string_length))
4490 {
4491
4492 /* Exist resource record including more info. */
4493 count --;
4494 break;
4495 }
4496 }
4497 else
4498 {
4499
4500 /* Exist the PTR RR which pointer to the same service. */
4501 if (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
4502 {
4503 count --;
4504 break;
4505 }
4506 }
4507 }
4508 }
4509 }
4510 }
4511
4512 /* Check the count state. */
4513 if (count == service_index)
4514 {
4515 /* Yes, find. */
4516 found = NX_TRUE;
4517 break;
4518 }
4519 count ++;
4520 }
4521 }
4522
4523 /* Check if find the service. */
4524 if (found == NX_TRUE)
4525 {
4526 break;
4527 }
4528 }
4529
4530 if (found)
4531 {
4532
4533 /* Update the elasped time. */
4534 p -> nx_mdns_rr_elapsed_time = tx_time_get();
4535
4536 /* Get the additional information. */
4537 _nx_mdns_service_addition_info_get(mdns_ptr, srv_name, service, interface_index);
4538
4539 /* Release the mDNS mutex. */
4540 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4541 return(NX_MDNS_SUCCESS);
4542 }
4543 else
4544 {
4545 /* Release the mDNS mutex. */
4546 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4547 return(NX_MDNS_NO_MORE_ENTRIES);
4548 }
4549 }
4550
4551
4552 /**************************************************************************/
4553 /* */
4554 /* FUNCTION RELEASE */
4555 /* */
4556 /* _nxe_mdns_peer_cache_clear PORTABLE C */
4557 /* 6.1 */
4558 /* AUTHOR */
4559 /* */
4560 /* Yuxin Zhou, Microsoft Corporation */
4561 /* */
4562 /* DESCRIPTION */
4563 /* */
4564 /* This function checks for errors in the mDNS peer service cache */
4565 /* clear function call. */
4566 /* */
4567 /* INPUT */
4568 /* */
4569 /* mdns_ptr Pointer to mDNS instance */
4570 /* */
4571 /* OUTPUT */
4572 /* */
4573 /* status Completion status */
4574 /* */
4575 /* CALLS */
4576 /* */
4577 /* _nx_mdns_peer_cache_clear Actual peer cache clear */
4578 /* function */
4579 /* */
4580 /* CALLED BY */
4581 /* */
4582 /* Application Code */
4583 /* */
4584 /* RELEASE HISTORY */
4585 /* */
4586 /* DATE NAME DESCRIPTION */
4587 /* */
4588 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4589 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4590 /* resulting in version 6.1 */
4591 /* */
4592 /**************************************************************************/
_nxe_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4593 UINT _nxe_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4594 {
4595
4596 UINT status;
4597
4598
4599 /* Check for invalid input pointers. */
4600 if (!mdns_ptr)
4601 {
4602 return(NX_PTR_ERROR);
4603 }
4604
4605 /* Check for invalid server attributes. */
4606 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4607 {
4608 return(NX_MDNS_PARAM_ERROR);
4609 }
4610
4611 /* Call actual mDNS create service. */
4612 status = _nx_mdns_peer_cache_clear(mdns_ptr);
4613
4614 /* Return status. */
4615 return(status);
4616 }
4617
4618
4619 /**************************************************************************/
4620 /* */
4621 /* FUNCTION RELEASE */
4622 /* */
4623 /* _nx_mdns_peer_cache_clear PORTABLE C */
4624 /* 6.1 */
4625 /* AUTHOR */
4626 /* */
4627 /* Yuxin Zhou, Microsoft Corporation */
4628 /* */
4629 /* DESCRIPTION */
4630 /* */
4631 /* This function clears the mDNS peer service cache. */
4632 /* */
4633 /* INPUT */
4634 /* */
4635 /* mdns_ptr Pointer to mDNS instance */
4636 /* */
4637 /* OUTPUT */
4638 /* */
4639 /* status Completion status */
4640 /* */
4641 /* CALLS */
4642 /* */
4643 /* tx_mutex_get Get the mDNS mutex */
4644 /* tx_mutex_put Put the mDNS mutex */
4645 /* _nx_mdns_cache_initialize Initialize the cache */
4646 /* */
4647 /* CALLED BY */
4648 /* */
4649 /* Application Code */
4650 /* */
4651 /* RELEASE HISTORY */
4652 /* */
4653 /* DATE NAME DESCRIPTION */
4654 /* */
4655 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4656 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4657 /* resulting in version 6.1 */
4658 /* */
4659 /**************************************************************************/
_nx_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4660 UINT _nx_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4661 {
4662
4663 UINT status;
4664
4665
4666 /* Get the mDNS mutex. */
4667 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4668
4669 status = _nx_mdns_cache_initialize(mdns_ptr, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_peer_service_cache, mdns_ptr -> nx_mdns_peer_service_cache_size);
4670
4671 /* Release the mDNS mutex. */
4672 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4673
4674 /* Return a error status. */
4675 return(status);
4676 }
4677
4678
4679 /**************************************************************************/
4680 /* */
4681 /* FUNCTION RELEASE */
4682 /* */
4683 /* _nxe_mdns_host_address_get PORTABLE C */
4684 /* 6.1 */
4685 /* AUTHOR */
4686 /* */
4687 /* Yuxin Zhou, Microsoft Corporation */
4688 /* */
4689 /* DESCRIPTION */
4690 /* */
4691 /* This function checks for errors in the mDNS host address get */
4692 /* function call. */
4693 /* */
4694 /* INPUT */
4695 /* */
4696 /* mdns_ptr Pointer to mDNS instance */
4697 /* name The name of the service */
4698 /* type The type of the service */
4699 /* subtype The subtype of the service */
4700 /* service Pointer to response service */
4701 /* timeout The timeour for service query */
4702 /* */
4703 /* OUTPUT */
4704 /* */
4705 /* status Completion status */
4706 /* */
4707 /* CALLS */
4708 /* */
4709 /* _nx_mdns_host_address_get Actual mDNS host address */
4710 /* get function */
4711 /* */
4712 /* CALLED BY */
4713 /* */
4714 /* Application Code */
4715 /* */
4716 /* RELEASE HISTORY */
4717 /* */
4718 /* DATE NAME DESCRIPTION */
4719 /* */
4720 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4721 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
4722 /* buffer length verification, */
4723 /* resulting in version 6.1 */
4724 /* */
4725 /**************************************************************************/
_nxe_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4726 UINT _nxe_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4727 {
4728
4729 UINT status;
4730
4731
4732 /* Check for invalid input pointers. */
4733 if ((!mdns_ptr) || (!host_name))
4734 {
4735 return(NX_PTR_ERROR);
4736 }
4737
4738 /* Check for mDNS started flag. */
4739 if (!mdns_ptr -> nx_mdns_started)
4740 {
4741 return(NX_MDNS_NOT_STARTED);
4742 }
4743
4744 /* Call actual mDNS create service. */
4745 status = _nx_mdns_host_address_get(mdns_ptr, host_name, ipv4_address, ipv6_address, timeout);
4746
4747 /* Return status. */
4748 return(status);
4749 }
4750
4751
4752 /**************************************************************************/
4753 /* */
4754 /* FUNCTION RELEASE */
4755 /* */
4756 /* _nx_mdns_host_address_get PORTABLE C */
4757 /* 6.1 */
4758 /* AUTHOR */
4759 /* */
4760 /* Yuxin Zhou, Microsoft Corporation */
4761 /* */
4762 /* DESCRIPTION */
4763 /* */
4764 /* This function adds the mDNS query record into peer buffer, */
4765 /* mDNS thread send the query message using one-shot type. */
4766 /* */
4767 /* INPUT */
4768 /* */
4769 /* mdns_ptr Pointer to mDNS instance */
4770 /* name The name of the service */
4771 /* type The type of the service */
4772 /* subtype The subtype of the service */
4773 /* service Pointer to response service */
4774 /* timeout The timeour for service query */
4775 /* */
4776 /* OUTPUT */
4777 /* */
4778 /* status Completion status */
4779 /* */
4780 /* CALLS */
4781 /* */
4782 /* tx_mutex_get Get the mDNS mutex */
4783 /* tx_mutex_put Put the mDNS mutex */
4784 /* tx_time_get Get the mDNS time */
4785 /* _nx_mdns_host_check Check the host info */
4786 /* _nx_mdns_answer_wait Wait the answer */
4787 /* _nx_mdns_cache_add_query Add the query into cache */
4788 /* _nx_mdns_cache_delete_query Delete the query from cache */
4789 /* */
4790 /* CALLED BY */
4791 /* */
4792 /* Application Code */
4793 /* */
4794 /* RELEASE HISTORY */
4795 /* */
4796 /* DATE NAME DESCRIPTION */
4797 /* */
4798 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4799 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4800 /* verified memcpy use cases, */
4801 /* resulting in version 6.1 */
4802 /* */
4803 /**************************************************************************/
_nx_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4804 UINT _nx_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4805 {
4806
4807 UINT status;
4808 ULONG start_time;
4809 ULONG current_time;
4810 ULONG elapsed_time;
4811 ULONG wait_time = timeout;
4812 NX_MDNS_RR *a_rr;
4813 NX_MDNS_RR *aaaa_rr;
4814 UCHAR host_name_query[NX_MDNS_NAME_MAX + 1];
4815 UINT i = 0;
4816 UCHAR domain_flag = NX_FALSE;
4817 UINT answer = NX_FALSE;
4818 UINT domain_name_length;
4819
4820
4821 /* Check string length. */
4822 if (_nx_utility_string_length_check((CHAR *)host_name, NX_NULL, NX_MDNS_HOST_NAME_MAX))
4823 {
4824 return(NX_MDNS_DATA_SIZE_ERROR);
4825 }
4826
4827 /* Get the mDNS mutex. */
4828 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
4829
4830 /* Clear the buffer. */
4831 memset(host_name_query, 0, NX_MDNS_NAME_MAX + 1);
4832
4833 /* Copy the host name into host name query buffer. */
4834 while(host_name[i] != NX_NULL)
4835 {
4836 host_name_query[i] = host_name[i];
4837 if (host_name[i] == '.')
4838 {
4839
4840 /* Update the flag. */
4841 domain_flag = NX_TRUE;
4842 }
4843 i++;
4844 }
4845
4846 /* Check if include the domain. */
4847 if (domain_flag == NX_FALSE)
4848 {
4849 host_name_query[i++] = '.';
4850
4851 /* Check string length. */
4852 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &domain_name_length, NX_MDNS_DOMAIN_NAME_MAX))
4853 {
4854
4855 /* Release the mDNS mutex. */
4856 tx_mutex_put(&(mdns_ptr->nx_mdns_mutex));
4857 return (NX_MDNS_DATA_SIZE_ERROR);
4858 }
4859
4860 memcpy((char*)(&host_name_query[i]), (const char*)mdns_ptr -> nx_mdns_domain_name, domain_name_length + 1); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX and NX_MDNS_DOMAIN_NAME_MAX are limited in nxd_mdns.h. */
4861 }
4862
4863 /* Initialize the value. */
4864 if (ipv4_address)
4865 *ipv4_address = NX_NULL;
4866 if (ipv6_address)
4867 memset(ipv6_address, 0, 16);
4868
4869 /* Start host address query on all enabled interfaces until get the answer or query timeout. */
4870 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
4871 {
4872
4873 /* Check if this interface is enabled. */
4874 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
4875 continue;
4876
4877 /* Get the query start time. */
4878 wait_time = timeout;
4879 start_time = tx_time_get();
4880
4881 /* Get the host IPv4 address. */
4882 if (ipv4_address)
4883 {
4884
4885 /* One shot query for host name. */
4886 status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_A, &a_rr, wait_time, i);
4887
4888 /* Check the status. */
4889 if (status == NX_MDNS_SUCCESS)
4890 {
4891
4892 /* Set the IPv4 address. */
4893 *ipv4_address = a_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
4894 answer = NX_TRUE;
4895 }
4896 }
4897
4898 /* Get the host IPv6 address. */
4899 if (ipv6_address)
4900 {
4901
4902 /* How much time has elapsed? */
4903 current_time = tx_time_get();
4904
4905 /* Has the time wrapped? */
4906 if (current_time >= start_time)
4907 {
4908 /* No, simply subtract to get the elapsed time. */
4909 elapsed_time = current_time - start_time;
4910 }
4911 else
4912 {
4913
4914 /* Yes it has. Time has rolled over the 32-bit boundary. */
4915 elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time;
4916 }
4917
4918 /* Update the timeout. */
4919 if (wait_time > elapsed_time)
4920 wait_time -= elapsed_time;
4921 else
4922 wait_time = 0;
4923
4924 /* Lookup the service. */
4925 status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_AAAA, &aaaa_rr, wait_time, i);
4926
4927 /* Check the status. */
4928 if (status == NX_MDNS_SUCCESS)
4929 {
4930
4931 /* Set the IPv6 address. */
4932 *ipv6_address = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[0];
4933 *(ipv6_address + 1) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[1];
4934 *(ipv6_address + 2) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[2];
4935 *(ipv6_address + 3) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[3];
4936 answer = NX_TRUE;
4937 }
4938 }
4939
4940 /* Check if get IPv4 address or IPv6 address. */
4941 if (answer == NX_TRUE)
4942 {
4943
4944 /* Release the mDNS mutex. */
4945 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4946 return (NX_MDNS_SUCCESS);
4947 }
4948 }
4949
4950 /* Release the mDNS mutex. */
4951 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4952 return (NX_MDNS_ERROR);
4953 }
4954 #endif /* NX_MDNS_DISABLE_CLIENT */
4955
4956
4957 #ifndef NX_MDNS_DISABLE_SERVER
4958 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
4959 /**************************************************************************/
4960 /* */
4961 /* FUNCTION RELEASE */
4962 /* */
4963 /* _nx_mdns_rr_a_aaaa_add PORTABLE C */
4964 /* 6.1 */
4965 /* AUTHOR */
4966 /* */
4967 /* Yuxin Zhou, Microsoft Corporation */
4968 /* */
4969 /* DESCRIPTION */
4970 /* */
4971 /* This function adds the mDNS A/AAAA resource record into local cache.*/
4972 /* */
4973 /* INPUT */
4974 /* */
4975 /* mdns_ptr Pointer to mDNS instance */
4976 /* set The resource record set */
4977 /* address The resource record address */
4978 /* insert_rr Pointer to insert resource */
4979 /* record */
4980 /* name Host name */
4981 /* ttl The resource record ttl */
4982 /* */
4983 /* OUTPUT */
4984 /* */
4985 /* status Completion status */
4986 /* */
4987 /* CALLS */
4988 /* */
4989 /* tx_mutex_get Get the mDNS mutex */
4990 /* tx_mutex_put Put the mDNS mutex */
4991 /* _nx_mdns_timer_set Set the mDNS timer */
4992 /* _nx_mdns_cache_add_string Add the string into cache */
4993 /* _nx_mdns_cache_delete_string Delete the string from cache */
4994 /* _nx_mdns_cache_add_resource_record Add the resource record */
4995 /* into cache */
4996 /* */
4997 /* CALLED BY */
4998 /* */
4999 /* _nx_mdns_host_name_register Register the host name */
5000 /* */
5001 /* RELEASE HISTORY */
5002 /* */
5003 /* DATE NAME DESCRIPTION */
5004 /* */
5005 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5006 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5007 /* resulting in version 6.1 */
5008 /* */
5009 /**************************************************************************/
_nx_mdns_rr_a_aaaa_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG * address,UINT addr_length,UCHAR type,UINT interface_index)5010 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index)
5011 {
5012 UINT status;
5013 NX_MDNS_RR *insert_rr;
5014 USHORT rr_type;
5015 NX_MDNS_RR temp_resource_record;
5016
5017
5018 /* Set the resource record type. */
5019 if(addr_length == 4)
5020 rr_type = NX_MDNS_RR_TYPE_A;
5021 else
5022 rr_type = NX_MDNS_RR_TYPE_AAAA;
5023
5024 /* Set the resource record parameters. */
5025 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, rr_type, NX_MDNS_RR_TTL_HOST, addr_length, NX_MDNS_RR_SET_UNIQUE, type, NX_FALSE, &temp_resource_record, interface_index);
5026
5027 /* Check for error. */
5028 if (status)
5029 {
5030 return(status);
5031 }
5032
5033 /* Add the parameters. */
5034 if(rr_type == NX_MDNS_RR_TYPE_A)
5035 {
5036 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = *address;
5037 }
5038 else
5039 {
5040 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = *address;
5041 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = *(address +1);
5042 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = *(address + 2);
5043 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = *(address + 3);
5044 }
5045
5046 /* Add the resource record. */
5047 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5048
5049 /* Check for error. */
5050 if (status)
5051 {
5052
5053 /* Delete the name strings. */
5054 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5055 return(status);
5056 }
5057
5058 /* Set the mDNS timer. */
5059 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
5060
5061 /* Return a successful status. */
5062 return(NX_SUCCESS);
5063 }
5064 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
5065
5066
5067 /**************************************************************************/
5068 /* */
5069 /* FUNCTION RELEASE */
5070 /* */
5071 /* _nx_mdns_rr_ptr_add PORTABLE C */
5072 /* 6.1 */
5073 /* AUTHOR */
5074 /* */
5075 /* Yuxin Zhou, Microsoft Corporation */
5076 /* */
5077 /* DESCRIPTION */
5078 /* */
5079 /* This function adds the mDNS PTR resource record into local buffer. */
5080 /* */
5081 /* INPUT */
5082 /* */
5083 /* mdns_ptr Pointer to mDNS instance */
5084 /* name The resource record name */
5085 /* ttl The resource record ttl */
5086 /* set The resource record set */
5087 /* ptr_name The domain name */
5088 /* insert_rr Pointer to insert resource */
5089 /* record */
5090 /* */
5091 /* OUTPUT */
5092 /* */
5093 /* status Completion status */
5094 /* */
5095 /* CALLS */
5096 /* */
5097 /* tx_mutex_get Get the mDNS mutex */
5098 /* tx_mutex_put Put the mDNS mutex */
5099 /* _nx_mdns_timer_set Set the mDNS timer */
5100 /* _nx_mdns_cache_add_string Add the string into cache */
5101 /* _nx_mdns_cache_delete_string Delete the string from cache */
5102 /* _nx_mdns_cache_add_resource_record Add the resource record */
5103 /* into cache */
5104 /* */
5105 /* CALLED BY */
5106 /* */
5107 /* Application Code */
5108 /* */
5109 /* RELEASE HISTORY */
5110 /* */
5111 /* DATE NAME DESCRIPTION */
5112 /* */
5113 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5114 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5115 /* resulting in version 6.1 */
5116 /* */
5117 /**************************************************************************/
_nx_mdns_rr_ptr_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * ptr_name,UCHAR is_valid,NX_MDNS_RR ** insert_rr,UINT interface_index)5118 static UINT _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index)
5119 {
5120
5121 UINT status;
5122 NX_MDNS_RR *ptr_rr;
5123 NX_MDNS_RR temp_resource_record;
5124 UINT ptr_name_length;
5125
5126
5127 if (_nx_utility_string_length_check((CHAR *)ptr_name, &ptr_name_length, NX_MDNS_NAME_MAX))
5128 {
5129 return (NX_MDNS_DATA_SIZE_ERROR);
5130 }
5131
5132 /* Get the mDNS mutex. */
5133 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5134
5135 /* Set the resource record parameters. Rdata length: PTR name, string should include the first'.' and last '\0'. */
5136 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_PTR, ttl, (ptr_name_length + 2), set, NX_TRUE, is_valid, &temp_resource_record, interface_index);
5137
5138 /* Check for error. */
5139 if (status)
5140 {
5141
5142 /* Release the mDNS mutex. */
5143 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5144
5145 return(status);
5146 }
5147
5148 /* Add the ptr name. */
5149 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, ptr_name, ptr_name_length,
5150 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name),
5151 NX_FALSE, NX_TRUE);
5152
5153 /* Check for error. */
5154 if (status)
5155 {
5156
5157 /* Delete the strings. */
5158 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5159
5160 /* Release the mDNS mutex. */
5161 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5162
5163 return(status);
5164 }
5165
5166 /* Add the resource record. */
5167 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &ptr_rr, NX_NULL);
5168
5169 /* Check for error. */
5170 if (status)
5171 {
5172
5173 /* Delete the same strings. */
5174 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5175
5176 /* Delete the same strings. */
5177 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, 0);
5178
5179 /* Release the mDNS mutex. */
5180 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5181
5182 return(status);
5183 }
5184
5185 /* Set the mDNS timer. */
5186 _nx_mdns_timer_set(mdns_ptr, ptr_rr, ptr_rr -> nx_mdns_rr_timer_count);
5187
5188 if (insert_rr)
5189 *insert_rr = ptr_rr;
5190
5191 /* Release the mDNS mutex. */
5192 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5193
5194 /* Return a successful status. */
5195 return(NX_SUCCESS);
5196 }
5197
5198
5199 /**************************************************************************/
5200 /* */
5201 /* FUNCTION RELEASE */
5202 /* */
5203 /* _nx_mdns_rr_srv_add PORTABLE C */
5204 /* 6.1 */
5205 /* AUTHOR */
5206 /* */
5207 /* Yuxin Zhou, Microsoft Corporation */
5208 /* */
5209 /* DESCRIPTION */
5210 /* */
5211 /* This function adds the mDNS SRV resource record into local buffer. */
5212 /* */
5213 /* INPUT */
5214 /* */
5215 /* mdns_ptr Pointer to mDNS instance */
5216 /* name Service nstance name */
5217 /* ttl The ttl of the service */
5218 /* set The resource record set */
5219 /* priority The priority of target host */
5220 /* weights Service weight */
5221 /* port The port on this target host */
5222 /* target The target host */
5223 /* insert_rr Pointer to insert record */
5224 /* */
5225 /* OUTPUT */
5226 /* */
5227 /* status Completion status */
5228 /* */
5229 /* CALLS */
5230 /* */
5231 /* tx_mutex_get Get the mDNS mutex */
5232 /* tx_mutex_put Put the mDNS mutex */
5233 /* _nx_mdns_timer_set Set the mDNS timer */
5234 /* _nx_mdns_cache_add_string Add the string into cache */
5235 /* _nx_mdns_cache_delete_string Delete the string from cache */
5236 /* _nx_mdns_cache_add_resource_record Add the resource record */
5237 /* into cache */
5238 /* */
5239 /* CALLED BY */
5240 /* */
5241 /* Application Code */
5242 /* */
5243 /* RELEASE HISTORY */
5244 /* */
5245 /* DATE NAME DESCRIPTION */
5246 /* */
5247 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5248 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5249 /* resulting in version 6.1 */
5250 /* */
5251 /**************************************************************************/
_nx_mdns_rr_srv_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,USHORT priority,USHORT weights,USHORT port,UCHAR * target,NX_MDNS_RR ** insert_rr,UINT interface_index)5252 static UINT _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority,
5253 USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index)
5254 {
5255
5256 UINT status;
5257 NX_MDNS_RR *srv_rr;
5258 NX_MDNS_RR temp_resource_record;
5259 UINT target_length;
5260
5261 if (_nx_utility_string_length_check((CHAR *)target, &target_length, NX_MDNS_NAME_MAX))
5262 {
5263 return (NX_MDNS_DATA_SIZE_ERROR);
5264 }
5265
5266 /* Get the mDNS mutex. */
5267 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5268
5269 /* Set the resource record parameters. Rdata length: PRIORITY, WEIGHTS, PORT, TARGET, name string should include the first'.' and last '\0'. */
5270 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_SRV, ttl, target_length + 8, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5271
5272 /* Check for error. */
5273 if (status)
5274 {
5275 /* Release the mDNS mutex. */
5276 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5277
5278 return(status);
5279 }
5280
5281 /* Add the name. */
5282 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, target, target_length,
5283 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
5284 NX_FALSE, NX_TRUE);
5285
5286 /* Check for error. */
5287 if (status)
5288 {
5289
5290 /* Delete the same strings. */
5291 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5292
5293 /* Release the mDNS mutex. */
5294 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5295
5296 return(status);
5297 }
5298
5299 /* Set the SRV parameters. */
5300 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = priority;
5301 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = weights;
5302 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = port;
5303
5304 /* Add the resource record. */
5305 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &srv_rr, NX_NULL);
5306
5307 /* Check for error. */
5308 if (status)
5309 {
5310 /* Delete the same strings. */
5311 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5312
5313 /* Delete the same strings. */
5314 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
5315
5316 /* Release the mDNS mutex. */
5317 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5318
5319 return(status);
5320 }
5321
5322 /* Set the mDNS timer. */
5323 _nx_mdns_timer_set(mdns_ptr, srv_rr, srv_rr -> nx_mdns_rr_timer_count);
5324
5325 if (insert_rr)
5326 *insert_rr = srv_rr;
5327
5328 /* Release the mDNS mutex. */
5329 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5330
5331 /* Return a successful status. */
5332 return(NX_SUCCESS);
5333 }
5334
5335
5336 /**************************************************************************/
5337 /* */
5338 /* FUNCTION RELEASE */
5339 /* */
5340 /* _nx_mdns_rr_txt_add PORTABLE C */
5341 /* 6.1 */
5342 /* AUTHOR */
5343 /* */
5344 /* Yuxin Zhou, Microsoft Corporation */
5345 /* */
5346 /* DESCRIPTION */
5347 /* */
5348 /* This function adds the mDNS TXT resource record into local buffer. */
5349 /* the TXT records are formatted in a "key=value" notation with ";" */
5350 /* acting as separator when more then one key is available. */
5351 /* */
5352 /* INPUT */
5353 /* */
5354 /* mdns_ptr Pointer to mDNS instance */
5355 /* name The resource record name */
5356 /* ttl The resource record ttl */
5357 /* set The resource record set */
5358 /* txt The txt string */
5359 /* insert_rr Pointer to insert record */
5360 /* */
5361 /* OUTPUT */
5362 /* */
5363 /* status Completion status */
5364 /* */
5365 /* CALLS */
5366 /* */
5367 /* tx_mutex_get Get the mDNS mutex */
5368 /* tx_mutex_put Put the mDNS mutex */
5369 /* _nx_mdns_timer_set Set the mDNS timer */
5370 /* _nx_mdns_cache_add_string Add the string into cache */
5371 /* _nx_mdns_cache_delete_string Delete the string from cache */
5372 /* _nx_mdns_cache_add_resource_record Add the resource record */
5373 /* into the cache */
5374 /* */
5375 /* CALLED BY */
5376 /* */
5377 /* Application Code */
5378 /* */
5379 /* RELEASE HISTORY */
5380 /* */
5381 /* DATE NAME DESCRIPTION */
5382 /* */
5383 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5384 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5385 /* resulting in version 6.1 */
5386 /* */
5387 /**************************************************************************/
_nx_mdns_rr_txt_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * txt,NX_MDNS_RR ** insert_rr,UINT interface_index)5388 static UINT _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index)
5389 {
5390
5391 UINT status;
5392 NX_MDNS_RR *txt_rr;
5393 NX_MDNS_RR temp_resource_record;
5394 UINT txt_length;
5395
5396
5397 /* Get the mDNS mutex. */
5398 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5399
5400 /* Set the resource record parameters. */
5401 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_TXT, ttl, 0, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5402
5403 /* Check for error. */
5404 if (status)
5405 {
5406 /* Release the mDNS mutex. */
5407 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5408
5409 return(status);
5410 }
5411
5412 if (txt)
5413 {
5414
5415 /* Check string length. */
5416 if (_nx_utility_string_length_check((CHAR *)txt, &txt_length, NX_MDNS_NAME_MAX))
5417 {
5418
5419 /* Release the mDNS mutex. */
5420 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5421 return (NX_MDNS_DATA_SIZE_ERROR);
5422 }
5423
5424 /* Calculate the text string.inlcude the one byte label. */
5425 temp_resource_record.nx_mdns_rr_rdata_length = (USHORT)(txt_length + 1);
5426
5427 /* Add the name. */
5428 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, txt, txt_length,
5429 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data),
5430 NX_FALSE, NX_TRUE);
5431
5432 /* Check for error. */
5433 if (status)
5434 {
5435
5436 /* Delete the same strings. */
5437 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5438
5439 /* Release the mDNS mutex. */
5440 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5441
5442 return(status);
5443 }
5444 }
5445 else
5446 {
5447 temp_resource_record.nx_mdns_rr_rdata_length = 1;
5448 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = NX_NULL;
5449 }
5450
5451 /* Add the resource record. */
5452 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &txt_rr, NX_NULL);
5453
5454 /* Check for error. */
5455 if (status)
5456 {
5457
5458 /* Delete the same strings. */
5459 _nx_mdns_cache_delete_string(mdns_ptr,NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5460
5461 if (txt)
5462 {
5463
5464 /* Delete the same strings. */
5465 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data, 0);
5466 }
5467
5468 /* Release the mDNS mutex. */
5469 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5470
5471 return(status);
5472 }
5473
5474 /* Set the mDNS timer. */
5475 _nx_mdns_timer_set(mdns_ptr, txt_rr, txt_rr -> nx_mdns_rr_timer_count);
5476
5477 if (insert_rr)
5478 *insert_rr = txt_rr;
5479
5480 /* Release the mDNS mutex. */
5481 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5482
5483 /* Return a successful status. */
5484 return(NX_SUCCESS);
5485 }
5486
5487
5488 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
5489 /**************************************************************************/
5490 /* */
5491 /* FUNCTION RELEASE */
5492 /* */
5493 /* _nx_mdns_rr_nsec_add PORTABLE C */
5494 /* 6.1 */
5495 /* AUTHOR */
5496 /* */
5497 /* Yuxin Zhou, Microsoft Corporation */
5498 /* */
5499 /* DESCRIPTION */
5500 /* */
5501 /* This function adds the mDNS A resource record into local cache. */
5502 /* */
5503 /* INPUT */
5504 /* */
5505 /* mdns_ptr Pointer to mDNS instance */
5506 /* name The resource record name */
5507 /* add_a Flag for adding A record */
5508 /* add_aaaa Flag for adding AAAA record */
5509 /* type Type for host or service */
5510 /* */
5511 /* OUTPUT */
5512 /* */
5513 /* status Completion status */
5514 /* */
5515 /* CALLS */
5516 /* */
5517 /* tx_mutex_get Get the mDNS mutex */
5518 /* tx_mutex_put Put the mDNS mutex */
5519 /* _nx_mdns_timer_set Set the mDNS timer */
5520 /* _nx_mdns_cache_add_string Add the string into cache */
5521 /* _nx_mdns_cache_delete_string Delete the string from cache */
5522 /* _nx_mdns_cache_add_resource_record Add the resource record */
5523 /* into cache */
5524 /* */
5525 /* CALLED BY */
5526 /* */
5527 /* _nx_mdns_host_name_register Register the host name */
5528 /* */
5529 /* RELEASE HISTORY */
5530 /* */
5531 /* DATE NAME DESCRIPTION */
5532 /* */
5533 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5534 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5535 /* resulting in version 6.1 */
5536 /* */
5537 /**************************************************************************/
_nx_mdns_rr_nsec_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR add_a,UCHAR add_aaaa,UCHAR type,UINT interface_index)5538 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index)
5539 {
5540 UINT status;
5541 NX_MDNS_RR *insert_rr;
5542 UCHAR bitmap_length = 0;
5543 ULONG rdata_length = 0;
5544 NX_MDNS_RR temp_resource_record;
5545 UINT name_length;
5546
5547
5548 /* Check string length. */
5549 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5550 {
5551 return (NX_MDNS_DATA_SIZE_ERROR);
5552 }
5553
5554 /* Add the next domain name, include the first'.' and last '\0'. */
5555 rdata_length = name_length + 2;
5556
5557 /* Add the window block and bitmap length. */
5558 rdata_length += 2;
5559
5560 /* Add the NSEC with A/AAAA Bitmap. */
5561 if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5562 {
5563 /* Set the Bitmaps length. */
5564 if (add_aaaa == NX_TRUE)
5565 bitmap_length = 4;
5566 else
5567 bitmap_length = 1;
5568 }
5569 else
5570 {
5571
5572 /* Add the NSEC with SRV/TXT Bitmap. */
5573 bitmap_length = 5;
5574 }
5575
5576 /* Add the Bitmaps. */
5577 rdata_length += bitmap_length;
5578
5579 /* Set the resource record parameters. */
5580 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_NSEC, NX_MDNS_RR_TTL_HOST, rdata_length,
5581 NX_MDNS_RR_SET_UNIQUE, NX_FALSE, NX_TRUE, &temp_resource_record, interface_index);
5582
5583 /* Check for error. */
5584 if (status)
5585 {
5586 return(status);
5587 }
5588
5589 /* Add the next domain name. */
5590 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5591 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain),
5592 NX_FALSE, NX_TRUE);
5593
5594 /* Check for error. */
5595 if (status)
5596 {
5597 /* Delete the same strings. */
5598 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5599
5600 return(status);
5601 }
5602
5603 /* Set the window block and bitmap length. */
5604 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block = 0;
5605 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length = bitmap_length;
5606
5607 /* Add the Bitmap for host. */
5608 if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5609 {
5610
5611 /* Encode the Bitmap. */
5612 if ((add_a == NX_TRUE) && (add_aaaa == NX_TRUE))
5613 {
5614
5615 /* Add the A Bitmap. */
5616 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5617
5618 /* Add the AAAA Bitmap. */
5619 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5620 }
5621 else if ((add_a == NX_TRUE))
5622 {
5623
5624 /* Add the A Bit map. */
5625 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5626 }
5627 else
5628 {
5629
5630 /* Add the AAAA Bitmap. */
5631 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5632 }
5633 }
5634 else
5635 {
5636 /* Add the TXT Bitmap for service. */
5637 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[2] = 128;
5638
5639 /* Add the SRV Bitmap for service. */
5640 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[4] = 64;
5641
5642 }
5643
5644 /* Add the resource record. */
5645 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5646
5647 /* Check for error. */
5648 if (status)
5649 {
5650 /* Delete the same strings. */
5651 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5652
5653 /* Delete the same strings. */
5654 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain, 0);
5655
5656 return(status);
5657 }
5658
5659 /* Return a successful status. */
5660 return(NX_SUCCESS);
5661 }
5662 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
5663
5664
5665 /**************************************************************************/
5666 /* */
5667 /* FUNCTION RELEASE */
5668 /* */
5669 /* _nx_mdns_rr_parameter_set PORTABLE C */
5670 /* 6.1.11 */
5671 /* AUTHOR */
5672 /* */
5673 /* Yuxin Zhou, Microsoft Corporation */
5674 /* */
5675 /* DESCRIPTION */
5676 /* */
5677 /* This function sets the parameters of resource record. */
5678 /* */
5679 /* INPUT */
5680 /* */
5681 /* mdns_ptr Pointer to mDNS instance */
5682 /* name The resource record name */
5683 /* type The resource record type */
5684 /* ttl The resource record ttl */
5685 /* rdata_lenth The resource record length */
5686 /* set The resource record set */
5687 /* is_register Register flag */
5688 /* is_valid Valid flag */
5689 /* rr_record Pointer to resource record */
5690 /* */
5691 /* OUTPUT */
5692 /* */
5693 /* status Completion status */
5694 /* */
5695 /* CALLS */
5696 /* */
5697 /* None */
5698 /* */
5699 /* CALLED BY */
5700 /* */
5701 /* Application Code */
5702 /* */
5703 /* RELEASE HISTORY */
5704 /* */
5705 /* DATE NAME DESCRIPTION */
5706 /* */
5707 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5708 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5709 /* resulting in version 6.1 */
5710 /* 04-25-2022 Yuxin Zhou Modified comment(s), */
5711 /* fixed the issue of timer, */
5712 /* resulting in version 6.1.11 */
5713 /* */
5714 /**************************************************************************/
_nx_mdns_rr_parameter_set(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,ULONG ttl,UINT rdata_length,UCHAR set,UCHAR is_register,UCHAR is_valid,NX_MDNS_RR * rr_record,UINT interface_index)5715 static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length,
5716 UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index)
5717 {
5718
5719 UINT status;
5720 UINT name_length;
5721
5722
5723 /* Check string length. */
5724 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5725 {
5726 return (NX_MDNS_DATA_SIZE_ERROR);
5727 }
5728
5729 /* Initialize the struct. */
5730 memset(rr_record, 0, sizeof(NX_MDNS_RR));
5731
5732 /* Add the name. */
5733 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5734 (VOID **)(&rr_record -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
5735
5736 /* Check for error. */
5737 if (status)
5738 return(status);
5739
5740 /* Set the parameters. */
5741 rr_record -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
5742 rr_record -> nx_mdns_rr_type = type;
5743 rr_record -> nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
5744 rr_record -> nx_mdns_rr_ttl = ttl;
5745 rr_record -> nx_mdns_rr_rdata_length = (USHORT)rdata_length;
5746
5747 /* Set the resource record as uniqure. */
5748 if (set == NX_MDNS_RR_SET_UNIQUE)
5749 rr_record -> nx_mdns_rr_word = (rr_record -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_UNIQUE);
5750
5751 /* Check for mDNS started flag. */
5752 if (mdns_ptr -> nx_mdns_started)
5753 {
5754
5755 /* Check the valid flag for PTR resource record. */
5756 if (is_valid == NX_TRUE)
5757 {
5758 /* Set the resource record state. */
5759 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
5760 }
5761 else
5762 {
5763
5764 /* The is_register value be used for A/AAAA type, the value being NX_TRUE indicates the operation is to register the host name(probing and announcing the A/AAAA). The value being NX_FALSE indicates the operation is an address change, (announcing the A/AAAA). */
5765 if ((set == NX_MDNS_RR_SET_UNIQUE) && (is_register == NX_TRUE))
5766 {
5767
5768 /* Set the resource record status. */
5769 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
5770 rr_record -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
5771 rr_record -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
5772 }
5773 else
5774 {
5775
5776 /* Set the resource record state. */
5777 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
5778 rr_record -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
5779 rr_record -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
5780
5781 /* Check the announcing max time. */
5782 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
5783 rr_record -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
5784 else
5785 rr_record -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
5786
5787 /* Set the retransmit count. */
5788 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
5789 rr_record -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
5790 else
5791 rr_record -> nx_mdns_rr_retransmit_count = 1;
5792 }
5793 }
5794 }
5795 else
5796 {
5797
5798 /* Set the resource record status. */
5799 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
5800 }
5801
5802 return(NX_MDNS_SUCCESS);
5803 }
5804 #endif /* NX_MDNS_DISABLE_SERVER */
5805
5806
5807 /**************************************************************************/
5808 /* */
5809 /* FUNCTION RELEASE */
5810 /* */
5811 /* _nx_mdns_rr_delete PORTABLE C */
5812 /* 6.1 */
5813 /* AUTHOR */
5814 /* */
5815 /* Yuxin Zhou, Microsoft Corporation */
5816 /* */
5817 /* DESCRIPTION */
5818 /* */
5819 /* This function deletes the mDNS resource record from the */
5820 /* local bufferor remote buffer according to the resource record set. */
5821 /* */
5822 /* INPUT */
5823 /* */
5824 /* mdns_ptr Pointer to mDNS instance */
5825 /* record_rr The resource record */
5826 /* */
5827 /* OUTPUT */
5828 /* */
5829 /* status Completion status */
5830 /* */
5831 /* CALLS */
5832 /* */
5833 /* tx_mutex_get Get the mDNS mutex */
5834 /* tx_mutex_put Put the mDNS mutex */
5835 /* _nx_mdns_timer_set Set the mDNS timer */
5836 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
5837 /* from cache */
5838 /* */
5839 /* CALLED BY */
5840 /* */
5841 /* Application Code */
5842 /* */
5843 /* RELEASE HISTORY */
5844 /* */
5845 /* DATE NAME DESCRIPTION */
5846 /* */
5847 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5848 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5849 /* resulting in version 6.1 */
5850 /* */
5851 /**************************************************************************/
_nx_mdns_rr_delete(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)5852 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
5853 {
5854
5855 UINT status = NX_MDNS_SUCCESS;
5856
5857 #ifndef NX_MDNS_DISABLE_CLIENT
5858 ULONG *head;
5859 NX_MDNS_RR *p;
5860 #endif /* NX_MDNS_DISABLE_CLIENT */
5861
5862 /* Get the mDNS mutex. */
5863 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5864
5865
5866 /* Check for mDNS started flag. */
5867 if (mdns_ptr -> nx_mdns_started)
5868 {
5869
5870 /* Check the RR owner. */
5871 if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5872 {
5873
5874 #ifndef NX_MDNS_DISABLE_SERVER
5875 if ((record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
5876 (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
5877 {
5878
5879 /* Set the state to send Goodbye packet. */
5880 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
5881
5882 /* Set the retransmit count. */
5883 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
5884
5885 /* Set the timer count. */
5886 record_rr -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
5887
5888 /* Set the delete flag. */
5889 record_rr -> nx_mdns_rr_word = (record_rr -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
5890
5891 /* Set the mDNS timer. */
5892 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
5893 }
5894 else
5895 {
5896
5897 /* Delete the resource records. */
5898 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5899 }
5900
5901 #endif /* NX_MDNS_DISABLE_SERVER */
5902 }
5903 else
5904 {
5905
5906 #ifndef NX_MDNS_DISABLE_CLIENT
5907 if (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
5908 {
5909
5910 /* Set the pointer. */
5911 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
5912
5913 if(head)
5914 {
5915 head = (ULONG*)(*head);
5916
5917 /* Check the remote resource record, stop the updating resource record. */
5918 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
5919 {
5920
5921 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
5922 continue;
5923
5924 if (p == record_rr)
5925 continue;
5926
5927 if ((p -> nx_mdns_rr_name == record_rr -> nx_mdns_rr_name) &&
5928 (p -> nx_mdns_rr_type == record_rr -> nx_mdns_rr_type) &&
5929 (p -> nx_mdns_rr_class == record_rr -> nx_mdns_rr_class))
5930 {
5931
5932 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)
5933 {
5934
5935 /* Clear the Updating flag. */
5936 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_UPDATING));
5937 }
5938
5939 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
5940 {
5941 if (p -> nx_mdns_rr_retransmit_count)
5942 {
5943
5944 /* mDNS querier need not update the RR, The original updating ttl is at 80%, 85%, 90%, 95%. Update the timer.*/
5945 /* timer_count: P, timer_count: C, rr_ttl: T.
5946 P = P + C * T * 5%. */
5947 p -> nx_mdns_rr_timer_count = (p -> nx_mdns_rr_timer_count + p -> nx_mdns_rr_retransmit_count * p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 /100);
5948
5949 /* Clear the retransmit count. */
5950 p -> nx_mdns_rr_retransmit_count = 0;
5951
5952 /* Set the mDNS timer. */
5953 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
5954 }
5955 }
5956 }
5957 }
5958 }
5959 }
5960
5961 /* Delete the resource record. */
5962 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5963
5964 #endif /* NX_MDNS_DISABLE_CLIENT */
5965 }
5966 }
5967 else
5968 {
5969 /* Check the RR owner. */
5970 if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5971 {
5972
5973 #ifndef NX_MDNS_DISABLE_SERVER
5974 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5975 #endif /* NX_MDNS_DISABLE_SERVER */
5976 }
5977 else
5978 {
5979
5980 #ifndef NX_MDNS_DISABLE_CLIENT
5981 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5982 #endif /* NX_MDNS_DISABLE_CLIENT */
5983 }
5984 }
5985
5986 /* Release the mDNS mutex. */
5987 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5988
5989 /* Return status. */
5990 return (status);
5991 }
5992
5993
5994 #ifndef NX_MDNS_DISABLE_SERVER
5995 /**************************************************************************/
5996 /* */
5997 /* FUNCTION RELEASE */
5998 /* */
5999 /* _nx_mdns_local_cache_clear PORTABLE C */
6000 /* 6.1 */
6001 /* AUTHOR */
6002 /* */
6003 /* Yuxin Zhou, Microsoft Corporation */
6004 /* */
6005 /* DESCRIPTION */
6006 /* */
6007 /* This function deletes the mDNS instance. */
6008 /* */
6009 /* INPUT */
6010 /* */
6011 /* mdns_ptr Pointer to mDNS instance */
6012 /* */
6013 /* OUTPUT */
6014 /* */
6015 /* status Completion status */
6016 /* */
6017 /* CALLS */
6018 /* */
6019 /* _nx_mdns_local_cache_clear Actual local cache clear */
6020 /* function */
6021 /* */
6022 /* CALLED BY */
6023 /* */
6024 /* Application Code */
6025 /* */
6026 /* RELEASE HISTORY */
6027 /* */
6028 /* DATE NAME DESCRIPTION */
6029 /* */
6030 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6031 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6032 /* resulting in version 6.1 */
6033 /* */
6034 /**************************************************************************/
_nxe_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6035 UINT _nxe_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6036 {
6037
6038 UINT status;
6039
6040
6041 /* Check for invalid input pointers. */
6042 if (!mdns_ptr)
6043 {
6044 return(NX_PTR_ERROR);
6045 }
6046
6047 /* Check for invalid server attributes. */
6048 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
6049 {
6050 return(NX_MDNS_PARAM_ERROR);
6051 }
6052
6053 /* Call actual mDNS local cache clear service. */
6054 status = _nx_mdns_local_cache_clear(mdns_ptr);
6055
6056 /* Return status. */
6057 return(status);
6058 }
6059
6060
6061 /**************************************************************************/
6062 /* */
6063 /* FUNCTION RELEASE */
6064 /* */
6065 /* _nx_mdns_local_cache_clear PORTABLE C */
6066 /* 6.1 */
6067 /* AUTHOR */
6068 /* */
6069 /* Yuxin Zhou, Microsoft Corporation */
6070 /* */
6071 /* DESCRIPTION */
6072 /* */
6073 /* This function clears the mDNS local cache. */
6074 /* */
6075 /* INPUT */
6076 /* */
6077 /* mdns_ptr Pointer to mDNS instance */
6078 /* */
6079 /* OUTPUT */
6080 /* */
6081 /* status Completion status */
6082 /* */
6083 /* CALLS */
6084 /* */
6085 /* _nx_mdns_timer_set Set the mDNS timer */
6086 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
6087 /* from cache */
6088 /* */
6089 /* CALLED BY */
6090 /* */
6091 /* Application Code */
6092 /* */
6093 /* RELEASE HISTORY */
6094 /* */
6095 /* DATE NAME DESCRIPTION */
6096 /* */
6097 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6098 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6099 /* resulting in version 6.1 */
6100 /* */
6101 /**************************************************************************/
_nx_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6102 UINT _nx_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6103 {
6104
6105 UINT status = NX_MDNS_SUCCESS;
6106 ULONG *head;
6107 NX_MDNS_RR *p;
6108
6109
6110 /* Get the mDNS mutex. */
6111 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
6112
6113 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6114 head = (ULONG*)(*head);
6115
6116 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
6117 {
6118
6119 /* Delete the resource records. */
6120 status = _nx_mdns_rr_delete(mdns_ptr, p);
6121
6122 /* Check the status. */
6123 if (status)
6124 break;
6125 }
6126
6127 /* Release the mDNS mutex. */
6128 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
6129
6130 /* Return a successful status. */
6131 return(status);
6132 }
6133 #endif /* NX_MDNS_DISABLE_SERVER */
6134
6135
6136 /**************************************************************************/
6137 /* */
6138 /* FUNCTION RELEASE */
6139 /* */
6140 /* _nx_mdns_service_name_resolve PORTABLE C */
6141 /* 6.1 */
6142 /* AUTHOR */
6143 /* */
6144 /* Yuxin Zhou, Microsoft Corporation */
6145 /* */
6146 /* DESCRIPTION */
6147 /* */
6148 /* This function resloves the service name, type, domain. */
6149 /* */
6150 /* INPUT */
6151 /* */
6152 /* srv_name Pointer to SRV name */
6153 /* name The name of the service */
6154 /* type The type of to the service */
6155 /* domain The domain */
6156 /* */
6157 /* OUTPUT */
6158 /* */
6159 /* status Completion status */
6160 /* */
6161 /* CALLS */
6162 /* */
6163 /* tx_mutex_get Get the mDNS mutex */
6164 /* tx_mutex_put Put the mDNS mutex */
6165 /* */
6166 /* CALLED BY */
6167 /* */
6168 /* mDNS component */
6169 /* */
6170 /* RELEASE HISTORY */
6171 /* */
6172 /* DATE NAME DESCRIPTION */
6173 /* */
6174 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6175 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6176 /* resulting in version 6.1 */
6177 /* */
6178 /**************************************************************************/
_nx_mdns_service_name_resolve(UCHAR * srv_name,UCHAR ** name,UCHAR ** type,UCHAR ** domain)6179 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain)
6180 {
6181
6182 UINT i;
6183 UINT count;
6184 UINT prepend_index;
6185 UINT append_index;
6186 UINT type_index;
6187 UINT domain_index;
6188 UCHAR *pointer;
6189 UINT protocol_length;
6190
6191
6192 /* Initialize the parameters. */
6193 count = 0;
6194 prepend_index = 0;
6195 append_index = 0;
6196 type_index = 0;
6197 domain_index = 0;
6198
6199 /* Set the service name pointer. */
6200 pointer = srv_name;
6201
6202 /* Service Instance name, */
6203 /* <Instance>.<sn>._tcp.<domain> :
6204 name: <Instance>
6205 type: <sn>._tcp
6206 domain: <domain>. */
6207 while (*srv_name != '\0')
6208 {
6209
6210 /* Update the index. */
6211 append_index ++;
6212
6213 if (*srv_name == '.')
6214 {
6215
6216 /* Set the value. */
6217 i = 0;
6218
6219 while (nx_mdns_app_protocol[i])
6220 {
6221
6222 /* Check string length. */
6223 if (_nx_utility_string_length_check(nx_mdns_app_protocol[i], &protocol_length, NX_MDNS_TYPE_MAX))
6224 {
6225 continue;
6226 }
6227
6228 /* Find the key string. "_tcp" , "_udp" etc. */
6229 if (!_nx_mdns_name_match(pointer + prepend_index, (UCHAR *)(nx_mdns_app_protocol[i]), protocol_length))
6230 {
6231
6232 /* Get the <domain> pointer. */
6233 /* EL-PC.Test._http._tcp.local
6234 type index pointer to the _http._tcp,
6235 domain_index pointer to the local. */
6236 domain_index = append_index;
6237
6238 /* Set the name pointer. */
6239 if (type_index)
6240 {
6241 *name = pointer;
6242
6243 /* Set the trailing null of name. */
6244 *(pointer + type_index -1) = '\0';
6245 }
6246 else
6247 {
6248 *name = NX_NULL;
6249 }
6250
6251 /* Set the type pointer. */
6252 *type = pointer + type_index;
6253
6254 /* Set the trailing null of type. */
6255 *(pointer + domain_index -1) = '\0';
6256
6257 /* Set the type pointer. */
6258 *domain = pointer + domain_index;
6259
6260 return(NX_MDNS_SUCCESS);
6261 }
6262 i ++;
6263 }
6264
6265 /* Update the '.' count. */
6266 count ++;
6267
6268 /* The type index is pointer to the <sn>. */
6269 if (count != 1)
6270 {
6271
6272 /* Update the type index. */
6273 type_index = prepend_index;
6274 }
6275
6276 prepend_index = append_index;
6277 }
6278
6279 srv_name ++;
6280 }
6281
6282 return(NX_MDNS_ERROR);
6283 }
6284
6285
6286 /**************************************************************************/
6287 /* */
6288 /* FUNCTION RELEASE */
6289 /* */
6290 /* _nx_mdns_service_name_assemble PORTABLE C */
6291 /* 6.1 */
6292 /* AUTHOR */
6293 /* */
6294 /* Yuxin Zhou, Microsoft Corporation */
6295 /* */
6296 /* DESCRIPTION */
6297 /* */
6298 /* This function resloves the service name, type, domain. */
6299 /* */
6300 /* INPUT */
6301 /* */
6302 /* srv_name Pointer to SRV name */
6303 /* name The name of the service */
6304 /* type The type of to the service */
6305 /* domain The domain */
6306 /* */
6307 /* OUTPUT */
6308 /* */
6309 /* status Completion status */
6310 /* */
6311 /* CALLS */
6312 /* */
6313 /* tx_mutex_get Get the mDNS mutex */
6314 /* tx_mutex_put Put the mDNS mutex */
6315 /* */
6316 /* CALLED BY */
6317 /* */
6318 /* mDNS component */
6319 /* */
6320 /* RELEASE HISTORY */
6321 /* */
6322 /* DATE NAME DESCRIPTION */
6323 /* */
6324 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6325 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6326 /* buffer length verification, */
6327 /* verified memcpy use cases, */
6328 /* resulting in version 6.1 */
6329 /* */
6330 /**************************************************************************/
_nx_mdns_service_name_assemble(UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * domain,UCHAR * record_buffer,UINT buffer_size,UINT * type_index)6331 static UINT _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index)
6332 {
6333
6334 UINT index;
6335 UINT length;
6336
6337 /* Initialize the struct. */
6338 index = 0;
6339 memset(record_buffer, 0, buffer_size);
6340 if (type_index)
6341 {
6342 *type_index = 0;
6343 }
6344
6345 /* Construct the service name. */
6346
6347 /* Add the name. */
6348 if (name)
6349 {
6350
6351 /* Check string length. */
6352 if (_nx_utility_string_length_check((CHAR *)name, &length, NX_MDNS_NAME_MAX))
6353 {
6354 return (NX_MDNS_DATA_SIZE_ERROR);
6355 }
6356
6357 /* Verify buffer length. */
6358 if (index + length + 1 > buffer_size)
6359 {
6360 return (NX_MDNS_DATA_SIZE_ERROR);
6361 }
6362
6363 memcpy((CHAR *)(record_buffer + index), (const char*)name, length); /* Use case of memcpy is verified. */
6364 index += length;
6365
6366 *(record_buffer + index) = '.';
6367 index ++;
6368 }
6369
6370 /* Add the sub type. */
6371 if (sub_type)
6372 {
6373
6374 /* Check string length. */
6375 if (_nx_utility_string_length_check((CHAR *)sub_type, &length, NX_MDNS_LABEL_MAX))
6376 {
6377 return (NX_MDNS_DATA_SIZE_ERROR);
6378 }
6379
6380 /* Verify buffer length. */
6381 if (index + length + 1 + 4 + 1 > buffer_size)
6382 {
6383 return (NX_MDNS_DATA_SIZE_ERROR);
6384 }
6385
6386 if (type_index)
6387 {
6388 *type_index = index;
6389 }
6390 memcpy((CHAR *)(record_buffer + index), (const char*)sub_type, length); /* Use case of memcpy is verified. */
6391 index += length;
6392 *(record_buffer + index) = '.';
6393 index ++;
6394
6395 /* Add the key word "_sub". */
6396 memcpy((CHAR *)(record_buffer + index), (const char*)"_sub", 4); /* Use case of memcpy is verified. */
6397 index += 4;
6398 *(record_buffer + index) = '.';
6399 index ++;
6400 }
6401
6402 /* Add the type. */
6403 if (type)
6404 {
6405
6406 /* Check string length. */
6407 if (_nx_utility_string_length_check((CHAR *)type, &length, NX_MDNS_TYPE_MAX))
6408 {
6409 return (NX_MDNS_DATA_SIZE_ERROR);
6410 }
6411
6412 /* Verify buffer length. */
6413 if (index + length + 1 > buffer_size)
6414 {
6415 return (NX_MDNS_DATA_SIZE_ERROR);
6416 }
6417
6418 /* Set the type index. */
6419 if ((type_index) &&
6420 (!sub_type))
6421 {
6422 *type_index = index;
6423 }
6424
6425 memcpy((CHAR *)record_buffer + index, (const char*)type, length); /* Use case of memcpy is verified. */
6426 index += length;
6427 *(record_buffer + index) = '.';
6428 index ++;
6429 }
6430
6431 /* Add the domain. */
6432 if (domain)
6433 {
6434
6435 /* Check string length. */
6436 if (_nx_utility_string_length_check((CHAR *)domain, &length, NX_MDNS_DOMAIN_NAME_MAX))
6437 {
6438 return (NX_MDNS_DATA_SIZE_ERROR);
6439 }
6440
6441 /* Verify buffer length. */
6442 if (index + length > buffer_size)
6443 {
6444 return (NX_MDNS_DATA_SIZE_ERROR);
6445 }
6446
6447 memcpy((CHAR *)(record_buffer + index), (const char*)domain, length); /* Use case of memcpy is verified. */
6448 index += length;
6449 }
6450
6451 return(NX_MDNS_SUCCESS);
6452 }
6453
6454
6455 #ifndef NX_MDNS_DISABLE_SERVER
6456 /**************************************************************************/
6457 /* */
6458 /* FUNCTION RELEASE */
6459 /* */
6460 /* nx_mdns_host_name_register PORTABLE C */
6461 /* 6.1 */
6462 /* AUTHOR */
6463 /* */
6464 /* Yuxin Zhou, Microsoft Corporation */
6465 /* */
6466 /* DESCRIPTION */
6467 /* */
6468 /* This function resloves the service name, type, domain. */
6469 /* */
6470 /* INPUT */
6471 /* */
6472 /* mdns_ptr Pointer to mDNS instance */
6473 /* type The type of operation */
6474 /* interface_index The interface index */
6475 /* */
6476 /* OUTPUT */
6477 /* */
6478 /* status Completion status */
6479 /* */
6480 /* CALLS */
6481 /* */
6482 /* tx_mutex_get Get the mDNS mutex */
6483 /* tx_mutex_put Put the mDNS mutex */
6484 /* _nx_mdns_rr_a_aaaa_add Add the A/AAAA resource record*/
6485 /* */
6486 /* CALLED BY */
6487 /* */
6488 /* _nx_mdns_enable Enable mDNS */
6489 /* _nx_mdns_address_change_process Process address change */
6490 /* */
6491 /* RELEASE HISTORY */
6492 /* */
6493 /* DATE NAME DESCRIPTION */
6494 /* */
6495 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6496 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6497 /* verified memcpy use cases, */
6498 /* resulting in version 6.1 */
6499 /* */
6500 /**************************************************************************/
_nx_mdns_host_name_register(NX_MDNS * mdns_ptr,UCHAR type,UINT interface_index)6501 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index)
6502 {
6503
6504 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
6505 UINT status;
6506 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
6507 NX_IP *ip_ptr;
6508 UINT index = 0;
6509 UCHAR add_a = NX_FALSE;
6510 UCHAR add_aaaa = NX_FALSE;
6511 UINT host_name_length;
6512
6513 #ifdef NX_MDNS_ENABLE_IPV6
6514 NXD_IPV6_ADDRESS *ipv6_address_ptr;
6515 #endif /* NX_MDNS_ENABLE_IPV6 */
6516
6517
6518 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
6519 NX_PARAMETER_NOT_USED(type);
6520 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6 */
6521
6522 /* Check string length. */
6523 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_host_name, &host_name_length, NX_MDNS_HOST_NAME_MAX))
6524 {
6525 return (NX_MDNS_DATA_SIZE_ERROR);
6526 }
6527
6528 /* Construct the A/AAAA name. */
6529 memcpy((CHAR *)(&temp_string_buffer[index]), (const char*)mdns_ptr -> nx_mdns_host_name, host_name_length); /* Use case of memcpy is verified. */
6530 index += host_name_length;
6531
6532 temp_string_buffer[index] = '.';
6533 index ++;
6534 memcpy((CHAR *)(&temp_string_buffer[index]), (CHAR *)"local", sizeof("local")); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h.*/
6535
6536 /* Set the ip pointer. */
6537 ip_ptr = mdns_ptr -> nx_mdns_ip_ptr;
6538
6539 /* Get the IP mutex. */
6540 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
6541
6542 #ifndef NX_DISABLE_IPV4
6543 /* Add the A resource records message. */
6544 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
6545 {
6546
6547 /* Add the A resource records message. */
6548 status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], &(ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address),
6549 NX_MDNS_IPV4_ADDRESS_LENGTH, type, interface_index);
6550
6551 /* Check the status. */
6552 if (status)
6553 {
6554
6555 /* Release the IP mutex. */
6556 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6557
6558 return(status);
6559 }
6560
6561 /* Set the flag. */
6562 add_a = NX_TRUE;
6563 }
6564 #endif /* NX_DISABLE_IPV4 */
6565
6566 #ifdef NX_MDNS_ENABLE_IPV6
6567 /* Get the IPv6 address pointer.*/
6568 ipv6_address_ptr = ip_ptr -> nx_ip_interface[interface_index].nxd_interface_ipv6_address_list_head;
6569
6570 while(ipv6_address_ptr)
6571 {
6572
6573 if (ipv6_address_ptr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)
6574 {
6575
6576 /* Add the AAAA resource records message. */
6577 status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], (ULONG *)(&ipv6_address_ptr -> nxd_ipv6_address[0]),
6578 NX_MDNS_IPV6_ADDRESS_LENGTH, type, interface_index);
6579
6580 /* Check the status. */
6581 if (status)
6582 {
6583
6584 /* Release the IP mutex. */
6585 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6586
6587 return(status);
6588 }
6589
6590 /* Set the flag. */
6591 add_aaaa = NX_TRUE;
6592 }
6593
6594 /* Update the pointer. */
6595 ipv6_address_ptr = ipv6_address_ptr -> nxd_ipv6_address_next;
6596 }
6597 #endif /* NX_MDNS_ENABLE_IPV6 */
6598
6599 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
6600
6601 /* Add the NSEC resource record. */
6602 if ((add_a == NX_TRUE) || (add_aaaa == NX_TRUE))
6603 _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], add_a, add_aaaa, NX_MDNS_ADD_NSEC_FOR_HOST, interface_index);
6604 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
6605
6606 /* Release the IP mutex. */
6607 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6608
6609 /* Return a successful status. */
6610 return(NX_SUCCESS);
6611 }
6612 #endif /* NX_MDNS_DISABLE_SERVER */
6613
6614
6615 /**************************************************************************/
6616 /* */
6617 /* FUNCTION RELEASE */
6618 /* */
6619 /* _nx_mdns_timer_entry PORTABLE C */
6620 /* 6.1 */
6621 /* AUTHOR */
6622 /* */
6623 /* Yuxin Zhou, Microsoft Corporation */
6624 /* */
6625 /* DESCRIPTION */
6626 /* */
6627 /* This function handles waking up the mDNS helper thread to process */
6628 /* the timer event on a periodic basis. */
6629 /* */
6630 /* INPUT */
6631 /* */
6632 /* mdns_value mDNS instance for a ulong */
6633 /* */
6634 /* OUTPUT */
6635 /* */
6636 /* None */
6637 /* */
6638 /* CALLS */
6639 /* */
6640 /* tx_event_flags_set Set event flags */
6641 /* */
6642 /* CALLED BY */
6643 /* */
6644 /* ThreadX system timer thread */
6645 /* */
6646 /* RELEASE HISTORY */
6647 /* */
6648 /* DATE NAME DESCRIPTION */
6649 /* */
6650 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6651 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6652 /* resulting in version 6.1 */
6653 /* */
6654 /**************************************************************************/
_nx_mdns_timer_entry(ULONG mdns_value)6655 static VOID _nx_mdns_timer_entry(ULONG mdns_value)
6656 {
6657
6658 NX_MDNS *mdns_ptr;
6659
6660
6661 /* Setup mDNS pointer from the input value. */
6662 mdns_ptr = (NX_MDNS *) mdns_value;
6663
6664 /* Set the timer event. */
6665 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_TIMER_EVENT, TX_OR);
6666
6667 return;
6668 }
6669
6670
6671 /**************************************************************************/
6672 /* */
6673 /* FUNCTION RELEASE */
6674 /* */
6675 /* _nx_mdns_timer_set PORTABLE C */
6676 /* 6.1 */
6677 /* AUTHOR */
6678 /* */
6679 /* Yuxin Zhou, Microsoft Corporation */
6680 /* */
6681 /* DESCRIPTION */
6682 /* */
6683 /* This function process all resource records according to the state, */
6684 /* Set the flags to send the probing, announcing, query, response and */
6685 /* goodbye mDNS message. Delete the resource record when the resource */
6686 /* record is invalid. */
6687 /* */
6688 /* INPUT */
6689 /* */
6690 /* mdns_ptr Pointer to mDNS instance */
6691 /* */
6692 /* OUTPUT */
6693 /* */
6694 /* status Completion status */
6695 /* */
6696 /* CALLS */
6697 /* */
6698 /* tx_timer_info_get Get the timer info */
6699 /* tx_timer_deactivate Deactivate the timer */
6700 /* tx_timer_change Change the timer */
6701 /* tx_timer_activate Activate the timer */
6702 /* */
6703 /* CALLED BY */
6704 /* */
6705 /* _nx_mdns_enable Enable the mDNS */
6706 /* _nx_mdns_rr_a_aaaa_add Add the A/AAAA resource record*/
6707 /* _nx_mdns_rr_ptr_add Add the ptr resource record */
6708 /* _nx_mdns_rr_srv_add Add the srv resource record */
6709 /* _nx_mdns_rr_txt_add Add the txt resource record */
6710 /* _nx_mdns_rr_delete Delete the resource record */
6711 /* _nx_mdns_local_cache_clear Clear the local cache */
6712 /* _nx_mdns_query Send the continuous query */
6713 /* _nx_mdns_packet_process Process mDNS packet */
6714 /* _nx_mdns_conflict_process Process the conflict */
6715 /* */
6716 /* RELEASE HISTORY */
6717 /* */
6718 /* DATE NAME DESCRIPTION */
6719 /* */
6720 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6721 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6722 /* resulting in version 6.1 */
6723 /* */
6724 /**************************************************************************/
_nx_mdns_timer_set(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr,ULONG timer_count)6725 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr, ULONG timer_count)
6726 {
6727
6728
6729 TX_INTERRUPT_SAVE_AREA
6730 ULONG remaining_ticks;
6731 ULONG schedule_count;
6732 UINT active;
6733
6734 if (timer_count)
6735 {
6736
6737 /* Disable interrupt */
6738 TX_DISABLE
6739
6740 /* Get the remaining_ticks of mDNS timer;*/
6741 tx_timer_info_get(&mdns_ptr -> nx_mdns_timer, TX_NULL, &active, &remaining_ticks, TX_NULL, TX_NULL);
6742
6743 /* If the timer is not active, the remaining ticks and schedule count are set to 0. */
6744 if(active == NX_FALSE)
6745 {
6746 remaining_ticks = 0;
6747 schedule_count = 0;
6748 }
6749 else
6750 {
6751
6752 /* Get the reschedule timer count of last timer. */
6753 schedule_count = mdns_ptr -> nx_mdns_timer_min_count;
6754 }
6755
6756 /* Check the timer. if exceed the timer count range, update the timer. */
6757 if((timer_count < remaining_ticks) || active == NX_FALSE)
6758 {
6759
6760 /* Set the minimum timer count.
6761 The minimum timer count indicate the intervals between last timer event and next timer event. */
6762 mdns_ptr -> nx_mdns_timer_min_count = (schedule_count - remaining_ticks) + timer_count;
6763
6764 /* Change the timer ticks with minimum timer count.*/
6765 tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
6766 tx_timer_change(&(mdns_ptr -> nx_mdns_timer), timer_count, timer_count );
6767 tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
6768 }
6769
6770 /* Update the Resource record life timer count*/
6771 record_rr -> nx_mdns_rr_timer_count = (schedule_count - remaining_ticks) + timer_count;
6772
6773 /* Restore interrupts. */
6774 TX_RESTORE
6775 }
6776 }
6777
6778
6779 /**************************************************************************/
6780 /* */
6781 /* FUNCTION RELEASE */
6782 /* */
6783 /* _nx_mdns_timer_event_process PORTABLE C */
6784 /* 6.1.11 */
6785 /* AUTHOR */
6786 /* */
6787 /* Yuxin Zhou, Microsoft Corporation */
6788 /* */
6789 /* DESCRIPTION */
6790 /* */
6791 /* This function process all resource records according to the state, */
6792 /* Set the flags to send the probing, announcing, query, response and */
6793 /* goodbye mDNS message. Delete the resource record when the resource */
6794 /* record is invalid. */
6795 /* */
6796 /* INPUT */
6797 /* */
6798 /* mdns_ptr Pointer to mDNS instance */
6799 /* */
6800 /* OUTPUT */
6801 /* */
6802 /* status Completion status */
6803 /* */
6804 /* CALLS */
6805 /* */
6806 /* tx_event_flags_set Set event flags to wake mDNS */
6807 /* tx_timer_deactivate Deactivate the timer */
6808 /* tx_timer_change Change the timer */
6809 /* tx_timer_activate Activate the timer */
6810 /* _nx_mdns_service_name_resolve Resolve the service name */
6811 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
6812 /* from the cache */
6813 /* */
6814 /* CALLED BY */
6815 /* */
6816 /* _nx_mdns_thread_entry Processing thread for mDNS */
6817 /* */
6818 /* RELEASE HISTORY */
6819 /* */
6820 /* DATE NAME DESCRIPTION */
6821 /* */
6822 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6823 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6824 /* verified memcpy use cases, */
6825 /* resulting in version 6.1 */
6826 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
6827 /* corrected the random value, */
6828 /* fixed the issue of timer, */
6829 /* resulting in version 6.1.11 */
6830 /* */
6831 /**************************************************************************/
_nx_mdns_timer_event_process(NX_MDNS * mdns_ptr)6832 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr)
6833 {
6834
6835 ULONG event_flags = 0;
6836 ULONG timer_min_count = 0xFFFFFFFF;
6837 ULONG *head, *tail;
6838 NX_MDNS_RR *p;
6839 UCHAR i;
6840
6841 #ifndef NX_MDNS_DISABLE_CLIENT
6842 ULONG remaining_ticks;
6843 #endif /* NX_MDNS_DISABLE_CLIENT */
6844
6845 #ifndef NX_MDNS_DISABLE_SERVER
6846 UINT status;
6847 NX_MDNS_RR *p1;
6848 UCHAR *service_name;
6849 UCHAR *service_type;
6850 UCHAR *service_domain;
6851 UINT rr_name_length;
6852 #endif /* NX_MDNS_DISABLE_SERVER */
6853
6854
6855 for(i = 0; i < 2; i++)
6856 {
6857
6858 /* Set the pointer. */
6859 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
6860 {
6861 #ifndef NX_MDNS_DISABLE_SERVER
6862 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6863 #else
6864 continue;
6865 #endif /* NX_MDNS_DISABLE_SERVER */
6866 }
6867 else
6868 {
6869 #ifndef NX_MDNS_DISABLE_CLIENT
6870 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
6871 #else
6872 continue;
6873 #endif /* NX_MDNS_DISABLE_CLIENT */
6874 }
6875
6876 if(head == NX_NULL)
6877 continue;
6878
6879 tail = (ULONG*)(*head);
6880
6881 /* Check the remote resource record lifetime. */
6882 for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
6883 {
6884
6885 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
6886 continue;
6887
6888 /* Update the remaining ticks of peer resource record. */
6889 if (((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
6890 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)))
6891 {
6892 if (p -> nx_mdns_rr_remaining_ticks > mdns_ptr -> nx_mdns_timer_min_count)
6893 {
6894 p -> nx_mdns_rr_remaining_ticks -= mdns_ptr -> nx_mdns_timer_min_count;
6895 }
6896 else
6897 {
6898 p -> nx_mdns_rr_remaining_ticks = 0;
6899 }
6900 }
6901
6902 /* Calculate the time interval for two responses.*/
6903 if (p -> nx_mdns_rr_response_interval > mdns_ptr -> nx_mdns_timer_min_count)
6904 {
6905 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count);
6906
6907 /* Compare the timer count.and set the minimum timer count. */
6908 if ((p -> nx_mdns_rr_response_interval != 0) &&
6909 (p -> nx_mdns_rr_response_interval < timer_min_count))
6910 {
6911 timer_min_count = p -> nx_mdns_rr_response_interval;
6912 }
6913 }
6914 else
6915 {
6916 p -> nx_mdns_rr_response_interval = 0;
6917 }
6918
6919 /* If the timer count is zero, means do not do anything */
6920 if (p -> nx_mdns_rr_timer_count == 0)
6921 continue;
6922
6923 if (p -> nx_mdns_rr_timer_count > mdns_ptr -> nx_mdns_timer_min_count)
6924 {
6925 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_timer_count - mdns_ptr -> nx_mdns_timer_min_count;
6926
6927 /* Check the timer count range. */
6928 if (p -> nx_mdns_rr_timer_count <= NX_MDNS_TIMER_COUNT_RANGE)
6929 {
6930 p -> nx_mdns_rr_timer_count = 0;
6931 }
6932 else
6933 {
6934 /* Compare the timer count.and set the minimum timer count. */
6935 if (p -> nx_mdns_rr_timer_count < timer_min_count)
6936 {
6937 timer_min_count = p -> nx_mdns_rr_timer_count;
6938 }
6939 }
6940 }
6941 else
6942 {
6943 p -> nx_mdns_rr_timer_count = 0;
6944 }
6945
6946 /* If the timer count is zero, means the timeout. */
6947 if (p -> nx_mdns_rr_timer_count != 0)
6948 continue;
6949
6950 /* Check the state. */
6951 switch (p -> nx_mdns_rr_state)
6952 {
6953
6954 #ifndef NX_MDNS_DISABLE_SERVER
6955 case NX_MDNS_RR_STATE_PROBING:
6956 {
6957
6958 /* mDNS Server probing the RRs at 0ms, 250ms, 500ms. RFC6762, Section8.1, Page26. */
6959 if (p -> nx_mdns_rr_retransmit_count)
6960 {
6961
6962 /* Set the send flag.*/
6963 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
6964
6965 /* Set the probing flag. */
6966 event_flags = event_flags | NX_MDNS_PROBING_SEND_EVENT;
6967
6968 /* Set the timer count. 250ms. */
6969 p -> nx_mdns_rr_timer_count = NX_MDNS_PROBING_TIMER_COUNT;
6970
6971 /* Compare the timer count.and set the minimum timer count. */
6972 if (p -> nx_mdns_rr_timer_count < timer_min_count)
6973 {
6974 timer_min_count = p -> nx_mdns_rr_timer_count;
6975 }
6976 }
6977 else
6978 {
6979
6980 /* Probing complete, and move to the next step, Announcing. */
6981 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
6982
6983 /* Set the first announcing timer interval. */
6984 p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
6985
6986 /* Set the retransmit count. */
6987 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
6988 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
6989 else
6990 p -> nx_mdns_rr_retransmit_count = 1;
6991
6992 /* Set the next timer count. */
6993 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
6994
6995 /* Check the announcing max time. */
6996 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
6997 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
6998 else
6999 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
7000
7001 /* Yes, probing complete, add the related PTR resource records. */
7002 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
7003 {
7004
7005 /* Check string length. */
7006 if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
7007 {
7008 break;
7009 }
7010
7011 /* Store the service name. */
7012 memcpy((CHAR *)(&temp_string_buffer[0]), (const char*)p -> nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
7013
7014 /* Reslove the service name. */
7015 status = _nx_mdns_service_name_resolve(&temp_string_buffer[0], &service_name, &service_type, &service_domain);
7016
7017 /* Check the status. */
7018 if (status)
7019 {
7020 break;
7021 }
7022
7023 /* Service name registered success, invoke the notify function. */
7024 if (mdns_ptr -> nx_mdns_probing_notify)
7025 {
7026 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, service_name, NX_MDNS_LOCAL_SERVICE_REGISTERED_SUCCESS);
7027 }
7028 }
7029
7030 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A)
7031 {
7032
7033 /* Service name registered success, invoke the notify function. */
7034 if (mdns_ptr -> nx_mdns_probing_notify)
7035 {
7036 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, mdns_ptr -> nx_mdns_host_name, NX_MDNS_LOCAL_HOST_REGISTERED_SUCCESS);
7037 }
7038 }
7039
7040 /* Probing complete, Has been wating for 250ms, Directly announcing the resource record. */
7041 p --;
7042 }
7043 break;
7044 }
7045
7046 case NX_MDNS_RR_STATE_ANNOUNCING:
7047 {
7048
7049 /* mDNS Server Announcing the Resource records. */
7050 if (p -> nx_mdns_rr_retransmit_count)
7051 {
7052
7053 /* Set the send flag to send the probing. */
7054 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7055
7056 /* Set the announcing flag. */
7057 event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7058
7059 /* Yes, probing complete, add the related PTR resource records and NSEC resource records. */
7060 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
7061 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
7062 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
7063 {
7064
7065 for (p1 = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p1 < tail; p1++)
7066 {
7067
7068 /* Check the state. */
7069 if (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
7070 continue;
7071
7072 /* Check the interface. */
7073 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
7074 continue;
7075
7076 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7077 if ((p1 ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
7078 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name))
7079 {
7080
7081 /* Set the send flag to send the probing. */
7082 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7083 }
7084 #endif /*NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7085
7086 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
7087 (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
7088 (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_name))
7089 {
7090
7091 /* Set the send flag to send the probing. */
7092 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7093 }
7094 }
7095 }
7096
7097 /* Check last the retransmit in this period announcing. */
7098 if (p -> nx_mdns_rr_retransmit_count - 1)
7099 {
7100
7101 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7102 {
7103
7104 /* Set the timer count. */
7105 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_announcing_retrans_interval;
7106
7107 /* Compare the timer count and set the minimum timer count. */
7108 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7109 {
7110 timer_min_count = p -> nx_mdns_rr_timer_count;
7111 }
7112 }
7113 }
7114 else
7115 {
7116 if (p -> nx_mdns_rr_announcing_max_time)
7117 {
7118
7119 /* Update the timer count. */
7120 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7121
7122 /* Calculate the next timer count. */
7123 p -> nx_mdns_rr_retransmit_lifetime = (ULONG)(p -> nx_mdns_rr_retransmit_lifetime * (ULONG)(2 << (mdns_ptr -> nx_mdns_announcing_factor - 1)));
7124
7125 /* Check the announcing period time interval. */
7126 if (p -> nx_mdns_rr_retransmit_lifetime > mdns_ptr -> nx_mdns_announcing_period_interval)
7127 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period_interval;
7128
7129 /* Set the retransmit count. */
7130 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7131 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
7132 else
7133 p -> nx_mdns_rr_retransmit_count = 1;
7134
7135 /* Set the retransmit count. */
7136 p -> nx_mdns_rr_retransmit_count++;
7137
7138 /* Check the announcing time. */
7139 if (p -> nx_mdns_rr_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
7140 p -> nx_mdns_rr_announcing_max_time--;
7141
7142 /* Compare the timer count and set the minimum timer count. */
7143 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7144 {
7145 timer_min_count = p -> nx_mdns_rr_timer_count;
7146 }
7147 }
7148 else
7149 {
7150
7151 /* Announcing complete, Update the resource record state valid, . */
7152 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
7153
7154 /* Clear the timer count. */
7155 p -> nx_mdns_rr_timer_count = 0;
7156 }
7157 }
7158 }
7159 break;
7160 }
7161
7162 case NX_MDNS_RR_STATE_GOODBYE:
7163 {
7164
7165 /* mDNS Server send Goodbye packet. */
7166 if (p -> nx_mdns_rr_retransmit_count)
7167 {
7168
7169 /* Set the send flag to send the probing. */
7170 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7171
7172 /* Set the announcing flag. */
7173 event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7174
7175 /* Set the timer count. */
7176 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
7177
7178 /* Compare the timer count.and set the minimum timer count. */
7179 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7180 {
7181 timer_min_count = p -> nx_mdns_rr_timer_count;
7182 }
7183 }
7184 else
7185 {
7186
7187 /* Check for RR delete flag. */
7188 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE)
7189 {
7190
7191 /* Delete the resource records. */
7192 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
7193 }
7194 else
7195 {
7196
7197 /* Suspend the resource record. */
7198 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
7199 p -> nx_mdns_rr_timer_count = 0;
7200 }
7201 }
7202 break;
7203 }
7204 #endif /* NX_MDNS_DISABLE_SERVER */
7205
7206
7207 case NX_MDNS_RR_STATE_VALID:
7208 {
7209
7210 if(i == NX_MDNS_CACHE_TYPE_PEER)
7211 {
7212 /* Set the resource record status. */
7213 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_UPDATING;
7214
7215 /* Check the updating flag. */
7216 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UPDATING)
7217 {
7218
7219 /* Set the retransmit count. */
7220 p -> nx_mdns_rr_retransmit_count = NX_MDNS_RR_UPDATE_COUNT;
7221
7222 /* 50% of the record lifetime has elapsed,the querier should plan to issure a query at 80%-82% of the record lifetime */
7223 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (((ULONG)NX_RAND()) % 3)) / 100;
7224 }
7225 else
7226 {
7227 /* Set the retransmit count. */
7228 p -> nx_mdns_rr_retransmit_count = 0;
7229
7230 /* 50% of the record lifetime has elapsed, Delete the resource record at 100% of the record lifetime */
7231 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
7232 }
7233
7234 /* Compare the timer count.and set the minimum timer count. */
7235 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7236 {
7237 timer_min_count = p -> nx_mdns_rr_timer_count;
7238 }
7239 }
7240
7241 /* Check the send flag. */
7242 else
7243 {
7244 if (p -> nx_mdns_rr_send_flag)
7245 {
7246
7247 /* Set the send flag to send the response. */
7248 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7249
7250 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7251 /* Clear the NSEC additional send. */
7252 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7253 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7254 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7255
7256 /* mDNS Responder MUST NOT multicast a record until at least one second has elapsed since the last time that record was multicast. RFC6762, Section6, Page16. */
7257 /* Set the next response time interval. */
7258 p -> nx_mdns_rr_response_interval = (ULONG)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE);
7259
7260 /* Compare the timer count.and set the minimum timer count. */
7261 if (p -> nx_mdns_rr_response_interval < timer_min_count)
7262 {
7263 timer_min_count = p -> nx_mdns_rr_response_interval;
7264 }
7265
7266 /* Set the announcing flag. */
7267 event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7268 }
7269
7270 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7271 else
7272 {
7273 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7274 {
7275 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send)
7276 {
7277 p -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_ADDITIONAL;
7278 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7279
7280 /* Set the announcing flag. */
7281 event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7282 }
7283 }
7284 }
7285 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7286 }
7287 break;
7288 }
7289
7290
7291 #ifndef NX_MDNS_DISABLE_CLIENT
7292 case NX_MDNS_RR_STATE_QUERY:
7293 {
7294
7295 /* mDNS Client did not receive the response, send the query again. */
7296 if (!p -> nx_mdns_rr_timer_count)
7297 {
7298
7299 /* Check the Duplicate Question. If the flag set, Host should not send the query until the next timeout. */
7300 if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DUPLICATE_QUERY))
7301 {
7302
7303 /* Set the send flag to send the query. */
7304 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7305
7306 /* Set the query flag. */
7307 event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7308 }
7309
7310 /* Clear the duplicate flag. */
7311 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
7312
7313 /* Double the next timer count. */
7314 p -> nx_mdns_rr_retransmit_lifetime = p -> nx_mdns_rr_retransmit_lifetime << 1;
7315
7316 /* The interval between the first two queries MUST be at least one second. RFC6762, Section5.2, Page9. */
7317 if (p -> nx_mdns_rr_retransmit_lifetime < NX_MDNS_QUERY_MIN_TIMER_COUNT)
7318 {
7319 p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MIN_TIMER_COUNT;
7320 }
7321
7322 /* When the interval between queries reaches or exceeds 60 minutes, a querier MAY cap the interval to a maximum of 60 minutes. RFC6762, Section5.2, Page10. */
7323 if (p -> nx_mdns_rr_retransmit_lifetime > NX_MDNS_QUERY_MAX_TIMER_COUNT)
7324 {
7325 p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MAX_TIMER_COUNT;
7326 }
7327
7328 /* Update the timer count. */
7329 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7330
7331 /* Compare the timer count.and set the minimum timer count. */
7332 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7333 {
7334 timer_min_count = p -> nx_mdns_rr_timer_count;
7335 }
7336 }
7337 break;
7338 }
7339
7340 case NX_MDNS_RR_STATE_UPDATING:
7341 {
7342
7343 /* The querier should plan to issure a query at 80%-82% of the record lifetime, and then if no answer is received,
7344 at 85%-87%, 90%-92% and 95%-97%. the record is deleted when it reaches 100% of its lifetime. RFC6762, Section5.2, Page10. */
7345 if (p -> nx_mdns_rr_retransmit_count)
7346 {
7347
7348 /* Set the send flag to retransmit its query. */
7349 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7350
7351 /* Set the query flag. */
7352 event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7353
7354 /* Update the timer count. Client should send the updating message every 5% of ttl. */
7355 if (p -> nx_mdns_rr_retransmit_count == 1)
7356 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_remaining_ticks;
7357 else
7358 {
7359 remaining_ticks = p -> nx_mdns_rr_remaining_ticks;
7360 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 / 100;
7361
7362 /* Get the remaining ticks in 5% of TTL. */
7363 while(remaining_ticks > p -> nx_mdns_rr_timer_count)
7364 remaining_ticks -= p -> nx_mdns_rr_timer_count;
7365
7366 p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(((ULONG)NX_RAND()) % 3) / 100);
7367 }
7368
7369 /* Compare the timer count.and set the minimum timer count. */
7370 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7371 {
7372 timer_min_count = p -> nx_mdns_rr_timer_count;
7373 }
7374 }
7375 else
7376 {
7377
7378 /* Delete the resource record. */
7379 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7380 }
7381 break;
7382 }
7383
7384 case NX_MDNS_RR_STATE_DELETE:
7385 case NX_MDNS_RR_STATE_POOF_DELETE:
7386 {
7387
7388 /* Delete the resource record. */
7389 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7390 break;
7391 }
7392 #endif /* NX_MDNS_DISABLE_CLIENT */
7393
7394 default:
7395 {
7396 break;
7397 }
7398 }
7399 }
7400 }
7401
7402 /* If the specified timer rate is different with the new timer min count,then update it.*/
7403 if (mdns_ptr -> nx_mdns_timer_min_count != timer_min_count)
7404 {
7405
7406 /* Set the minimum timer count.*/
7407 mdns_ptr -> nx_mdns_timer_min_count = timer_min_count;
7408
7409 /* Deactivate the timer. */
7410 tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
7411
7412 if (timer_min_count != 0xFFFFFFFF)
7413 {
7414
7415 /* Change the timer ticks with minimum timer count.*/
7416 tx_timer_change(&(mdns_ptr -> nx_mdns_timer),
7417 mdns_ptr -> nx_mdns_timer_min_count,
7418 mdns_ptr -> nx_mdns_timer_min_count);
7419 tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
7420 }
7421 }
7422
7423 /* Set the event to send mDNS query. */
7424 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), event_flags, TX_OR);
7425 }
7426
7427
7428 /**************************************************************************/
7429 /* */
7430 /* FUNCTION RELEASE */
7431 /* */
7432 /* _nx_mdns_udp_receive_notify PORTABLE C */
7433 /* 6.1 */
7434 /* AUTHOR */
7435 /* */
7436 /* Yuxin Zhou, Microsoft Corporation */
7437 /* */
7438 /* DESCRIPTION */
7439 /* */
7440 /* This function is the mDNS UDP receive notify callback. */
7441 /* */
7442 /* INPUT */
7443 /* */
7444 /* socket_ptr Pointer to udp socket */
7445 /* */
7446 /* OUTPUT */
7447 /* */
7448 /* None */
7449 /* */
7450 /* CALLS */
7451 /* */
7452 /* tx_event_flags_set Set event flags */
7453 /* */
7454 /* CALLED BY */
7455 /* */
7456 /* UDP receive callback */
7457 /* */
7458 /* RELEASE HISTORY */
7459 /* */
7460 /* DATE NAME DESCRIPTION */
7461 /* */
7462 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7463 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7464 /* resulting in version 6.1 */
7465 /* */
7466 /**************************************************************************/
_nx_mdns_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)7467 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
7468 {
7469
7470
7471 NX_PARAMETER_NOT_USED(socket_ptr);
7472
7473 /* Check the mDNS. */
7474 if(_nx_mdns_created_ptr)
7475 {
7476
7477 /* Set the receive UDP packet notify. */
7478 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_PKT_RX_EVENT, TX_OR);
7479 }
7480
7481 return;
7482 }
7483
7484 #ifndef NX_MDNS_DISABLE_SERVER
7485 #ifndef NX_DISABLE_IPV4
7486 /**************************************************************************/
7487 /* */
7488 /* FUNCTION RELEASE */
7489 /* */
7490 /* _nx_mdns_ip_address_change_notify PORTABLE C */
7491 /* 6.1 */
7492 /* AUTHOR */
7493 /* */
7494 /* Yuxin Zhou, Microsoft Corporation */
7495 /* */
7496 /* DESCRIPTION */
7497 /* */
7498 /* This function is the mDNS UDP receive notify callback. */
7499 /* */
7500 /* INPUT */
7501 /* */
7502 /* socket_ptr Pointer to udp socket */
7503 /* */
7504 /* OUTPUT */
7505 /* */
7506 /* None */
7507 /* */
7508 /* CALLS */
7509 /* */
7510 /* tx_event_flags_set Set event flags */
7511 /* */
7512 /* CALLED BY */
7513 /* */
7514 /* UDP receive callback */
7515 /* */
7516 /* RELEASE HISTORY */
7517 /* */
7518 /* DATE NAME DESCRIPTION */
7519 /* */
7520 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7521 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7522 /* resulting in version 6.1 */
7523 /* */
7524 /**************************************************************************/
_nx_mdns_ip_address_change_notify(NX_IP * ip_ptr,VOID * additional_info)7525 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info)
7526 {
7527
7528
7529 NX_PARAMETER_NOT_USED(ip_ptr);
7530 NX_PARAMETER_NOT_USED(additional_info);
7531
7532 /* Check the mDNS. */
7533 if(_nx_mdns_created_ptr)
7534 {
7535
7536 /* Set the address change event event. */
7537 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7538 }
7539
7540 return;
7541 }
7542 #endif /* NX_DISABLE_IPV4 */
7543
7544
7545 /**************************************************************************/
7546 /* */
7547 /* FUNCTION RELEASE */
7548 /* */
7549 /* _nx_mdns_ipv6_address_change_notify PORTABLE C */
7550 /* 6.1 */
7551 /* AUTHOR */
7552 /* */
7553 /* Yuxin Zhou, Microsoft Corporation */
7554 /* */
7555 /* DESCRIPTION */
7556 /* */
7557 /* This function is the mDNS UDP receive notify callback. */
7558 /* */
7559 /* INPUT */
7560 /* */
7561 /* socket_ptr Pointer to udp socket */
7562 /* */
7563 /* OUTPUT */
7564 /* */
7565 /* None */
7566 /* */
7567 /* CALLS */
7568 /* */
7569 /* tx_event_flags_set Set event flags */
7570 /* */
7571 /* CALLED BY */
7572 /* */
7573 /* UDP receive callback */
7574 /* */
7575 /* RELEASE HISTORY */
7576 /* */
7577 /* DATE NAME DESCRIPTION */
7578 /* */
7579 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7580 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7581 /* resulting in version 6.1 */
7582 /* */
7583 /**************************************************************************/
7584 #ifdef NX_MDNS_ENABLE_IPV6
_nx_mdns_ipv6_address_change_notify(NX_IP * ip_ptr,UINT method,UINT interface_index,UINT index,ULONG * ipv6_address)7585 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address)
7586 {
7587
7588 NX_PARAMETER_NOT_USED(ip_ptr);
7589 NX_PARAMETER_NOT_USED(method);
7590 NX_PARAMETER_NOT_USED(interface_index);
7591 NX_PARAMETER_NOT_USED(index);
7592 NX_PARAMETER_NOT_USED(ipv6_address);
7593
7594 /* Check the mDNS. */
7595 if(_nx_mdns_created_ptr)
7596 {
7597
7598 /* Set the address change event. */
7599 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7600 }
7601 return;
7602 }
7603 #endif /* NX_MDNS_ENABLE_IPV6 */
7604 #endif /* NX_MDNS_DISABLE_SERVER */
7605
7606
7607 /**************************************************************************/
7608 /* */
7609 /* FUNCTION RELEASE */
7610 /* */
7611 /* _nx_mdns_thread_entry PORTABLE C */
7612 /* 6.1 */
7613 /* AUTHOR */
7614 /* */
7615 /* Yuxin Zhou, Microsoft Corporation */
7616 /* */
7617 /* DESCRIPTION */
7618 /* */
7619 /* This function is the entry point for the mDNS helper thread. */
7620 /* mDNS helper thread is responsible for processing mDNS events. */
7621 /* Receive and send the mDNS packet. */
7622 /* */
7623 /* INPUT */
7624 /* */
7625 /* mdns_value Pointer to mDNS instance */
7626 /* */
7627 /* OUTPUT */
7628 /* */
7629 /* None */
7630 /* */
7631 /* CALLS */
7632 /* */
7633 /* tx_mutex_get Get the mDNS mutex */
7634 /* tx_mutex_put Put the mDNS mutex */
7635 /* tx_event_flags_get Get the mDNS events */
7636 /* nx_udp_socket_receive Receive the mDNS packet */
7637 /* nx_packet_release Release the mDNS packet */
7638 /* _nx_mdns_packet_process Process mDNS packet */
7639 /* _nx_mdns_announcing_send Send announcing message */
7640 /* _nx_mdns_probing_send Send probing message */
7641 /* _nx_mdns_query_send Send query message */
7642 /* _nx_mdns_response_send Send response message */
7643 /* _nx_mdns_timer_event_process Process the mDNS timer event */
7644 /* _nx_mdns_address_change_process Process the address change */
7645 /* */
7646 /* CALLED BY */
7647 /* */
7648 /* ThreadX Scheduler */
7649 /* */
7650 /* RELEASE HISTORY */
7651 /* */
7652 /* DATE NAME DESCRIPTION */
7653 /* */
7654 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7655 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7656 /* resulting in version 6.1 */
7657 /* */
7658 /**************************************************************************/
_nx_mdns_thread_entry(ULONG mdns_value)7659 static VOID _nx_mdns_thread_entry(ULONG mdns_value)
7660 {
7661
7662 NX_MDNS *mdns_ptr;
7663 NX_PACKET *packet_ptr;
7664 ULONG mdns_events;
7665 UINT status;
7666 UINT interface_index;
7667
7668
7669 /* Setup mDNS pointer from the input value. */
7670 mdns_ptr = (NX_MDNS *) mdns_value;
7671
7672 /* Get the mDNS mutex. */
7673 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7674
7675 /* Loop to process events for this mDNS instance. */
7676 while(1)
7677 {
7678
7679 /* Release the mDNS mutex. */
7680 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
7681
7682 /* Pickup mDNS event flags. */
7683 tx_event_flags_get(&mdns_ptr -> nx_mdns_events,
7684 NX_MDNS_ALL_EVENTS, TX_OR_CLEAR,
7685 &mdns_events, TX_WAIT_FOREVER);
7686
7687 /* Get the mDNS mutex. */
7688 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7689
7690 /* Check for an UDP packet receive event. */
7691 if (mdns_events & NX_MDNS_PKT_RX_EVENT)
7692 {
7693 while (1)
7694 {
7695
7696 /* Receive a UDP packet. */
7697 status = _nx_udp_socket_receive(&mdns_ptr -> nx_mdns_socket,
7698 &packet_ptr, TX_NO_WAIT);
7699
7700 /* Check status. */
7701 if (status != NX_SUCCESS)
7702 break;
7703
7704 #ifndef NX_DISABLE_PACKET_CHAIN
7705
7706 /* Discard the chained packets. */
7707 if (packet_ptr -> nx_packet_next)
7708 {
7709 nx_packet_release(packet_ptr);
7710 continue;
7711 }
7712 #endif
7713
7714 /* Get the interface. */
7715 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
7716 {
7717 interface_index = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
7718 }
7719 else
7720 {
7721 interface_index = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_index;
7722 }
7723
7724 /* Check the interface. */
7725 if (!mdns_ptr -> nx_mdns_interface_enabled[interface_index])
7726 {
7727 /* Release the packet since mDNS is not enabled on this interface. */
7728 nx_packet_release(packet_ptr);
7729 continue;
7730 }
7731
7732 /* Yes, Get the mDNS packet, process it. */
7733 _nx_mdns_packet_process(mdns_ptr, packet_ptr, interface_index);
7734
7735 /* Release the packet. */
7736 nx_packet_release(packet_ptr);
7737 }
7738 }
7739
7740 /* Loop to send mDNS message for each interface. */
7741 for (interface_index = 0; interface_index < NX_MAX_PHYSICAL_INTERFACES; interface_index++)
7742 {
7743
7744 /* Check if this interface is enabled.
7745 Exception: Goodbye message can be sent out after disable. */
7746 if ((!mdns_ptr -> nx_mdns_interface_enabled[interface_index]) &&
7747 (!(mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)))
7748 continue;
7749
7750 #ifndef NX_MDNS_DISABLE_SERVER
7751
7752 /* Check for an mDNS probing send event. */
7753 if (mdns_events & NX_MDNS_PROBING_SEND_EVENT)
7754 {
7755
7756 /* Send probing. */
7757 _nx_mdns_probing_send(mdns_ptr, interface_index);
7758 }
7759
7760 /* Check for an mDNS announcing send event. */
7761 if (mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)
7762 {
7763
7764 /* Send announcing. */
7765 _nx_mdns_announcing_send(mdns_ptr, interface_index);
7766 }
7767
7768 /* Check for an mDNS response send event. */
7769 if (mdns_events & NX_MDNS_RESPONSE_SEND_EVENT)
7770 {
7771
7772 /* Send response. */
7773 _nx_mdns_response_send(mdns_ptr, interface_index);
7774 }
7775 #endif /* NX_MDNS_DISABLE_SERVER */
7776
7777 #ifndef NX_MDNS_DISABLE_CLIENT
7778 /* Check for an mDNS query send event. */
7779 if (mdns_events & NX_MDNS_QUERY_SEND_EVENT)
7780 {
7781
7782 /* Send query. */
7783 _nx_mdns_query_send(mdns_ptr, interface_index);
7784 }
7785 #endif /* NX_MDNS_DISABLE_CLIENT */
7786 }
7787
7788 #ifndef NX_MDNS_DISABLE_SERVER
7789
7790 /* Check for an mDNS address change event. */
7791 if (mdns_events & NX_MDNS_ADDRESS_CHANGE_EVENT)
7792 {
7793
7794 /* Process the address change event. */
7795 _nx_mdns_address_change_process(mdns_ptr);
7796 }
7797 #endif /* NX_MDNS_DISABLE_SERVER */
7798
7799 /* Check for an mDNS timer process event. */
7800 if (mdns_events & NX_MDNS_TIMER_EVENT)
7801 {
7802
7803 /* Process the timer event. */
7804 _nx_mdns_timer_event_process(mdns_ptr);
7805 }
7806 }
7807 }
7808
7809
7810 /**************************************************************************/
7811 /* */
7812 /* FUNCTION RELEASE */
7813 /* */
7814 /* _nx_mdns_packet_process PORTABLE C */
7815 /* 6.1.11 */
7816 /* AUTHOR */
7817 /* */
7818 /* Yuxin Zhou, Microsoft Corporation */
7819 /* */
7820 /* DESCRIPTION */
7821 /* */
7822 /* This function checks the interface and the IP address of received */
7823 /* packet, then preocesses the packet. */
7824 /* */
7825 /* INPUT */
7826 /* */
7827 /* mdns_ptr Pointer to mDNS instance */
7828 /* packet_ptr Pointer to mDNS packet */
7829 /* */
7830 /* OUTPUT */
7831 /* */
7832 /* status Completion status */
7833 /* */
7834 /* CALLS */
7835 /* */
7836 /* nx_packet_release Release the mDNS packet */
7837 /* _tx_thread_system_resume Resume thread service */
7838 /* _nx_mdns_timer_set Set the mDNS timer */
7839 /* _nx_mdns_name_string_decode Decode the name size */
7840 /* _nx_mdns_name_size_calculate Calculate the name size */
7841 /* _nx_mdns_rr_size_get Get the resource record size */
7842 /* _nx_mdns_conflict_process Process the mDNS conflict */
7843 /* _nx_mdns_cache_find_resource_record Find the mDNS resource record */
7844 /* _nx_mdns_packet_address_check Check the address and port */
7845 /* _nx_mdns_packet_rr_process Process resource record */
7846 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
7847 /* from cache */
7848 /* nxd_udp_packet_info_extract Extract the packet info */
7849 /* */
7850 /* CALLED BY */
7851 /* */
7852 /* _nx_mdns_thread_entry Processing thread for mDNS */
7853 /* */
7854 /* RELEASE HISTORY */
7855 /* */
7856 /* DATE NAME DESCRIPTION */
7857 /* */
7858 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7859 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7860 /* resulting in version 6.1 */
7861 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
7862 /* packet length verification, */
7863 /* resulting in version 6.1.4 */
7864 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
7865 /* corrected the random value, */
7866 /* fixed the issue of timer, */
7867 /* resulting in version 6.1.11 */
7868 /* */
7869 /**************************************************************************/
_nx_mdns_packet_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)7870 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
7871 {
7872
7873 USHORT mdns_flags;
7874 UCHAR *data_ptr;
7875 USHORT question_count;
7876 USHORT authority_count;
7877 USHORT answer_count;
7878 UINT index;
7879 NX_MDNS_RR *rr_search;
7880 NX_MDNS_RR temp_resource_record;
7881
7882 #ifndef NX_MDNS_DISABLE_SERVER
7883 ULONG *head;
7884 NX_MDNS_RR *p;
7885 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7886 ULONG match_count;
7887 NX_MDNS_RR *nsec_rr;
7888 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7889 #endif /* NX_MDNS_DISABLE_SERVER */
7890
7891
7892 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
7893 /* Check the address and port. */
7894 if (_nx_mdns_packet_address_check(packet_ptr))
7895 {
7896 return(NX_MDNS_ERROR);
7897 }
7898 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
7899
7900 /* Check the packet length. */
7901 if (packet_ptr -> nx_packet_length < NX_MDNS_QDSECT_OFFSET)
7902 {
7903 return(NX_MDNS_ERROR);
7904 }
7905
7906 /* Extract the message type which should be the first byte. */
7907 mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
7908
7909 /* Get the question count. */
7910 question_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET);
7911
7912 /* Determine if we have any 'answers' to our DNS query. */
7913 answer_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET);
7914
7915 /* Also check if there are any 'hints' from the Authoritative nameserver. */
7916 authority_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET);
7917
7918 /* Update the answer count. Ignore the authority count and additional count for query message. */
7919 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7920 {
7921 answer_count = (USHORT)(answer_count + authority_count);
7922
7923 /* Include Additional section as well */
7924 answer_count = (USHORT)(answer_count + NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET));
7925 }
7926
7927 /* Skip the Header. Point at the start of the question. */
7928 data_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
7929
7930 /* Process all the Question Section. */
7931 for (index = 0; index < question_count; index++)
7932 {
7933
7934 /* Check for data_ptr. */
7935 if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
7936 break;
7937
7938 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7939 {
7940
7941 /* Multicast DNS responses MUST NOT contain any question in the Question Section,
7942 Any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. RFC6762, Section6, Page14. */
7943 data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
7944 }
7945 else
7946 {
7947
7948 #ifndef NX_MDNS_DISABLE_CLIENT
7949
7950 /* Step1, mDNS Client process the Duplicate Question Suppression, RFC6762, Section7.3, Page24. */
7951 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
7952 {
7953
7954 /* Check the class top bit "QM". */
7955 if ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_RR_CLASS_TOP_BIT) != NX_MDNS_RR_CLASS_TOP_BIT)
7956 {
7957
7958 /* Find the same resource record in remote buffer. */
7959 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
7960 {
7961
7962 /* Duplicate Question Suppression. */
7963 if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
7964 {
7965
7966 if (_nx_mdns_known_answer_find(mdns_ptr, rr_search) == NX_MDNS_NO_KNOWN_ANSWER)
7967 {
7968
7969 /* Yes, set the duplicate flag. process this flag in timer event process function. */
7970 rr_search -> nx_mdns_rr_word = rr_search -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DUPLICATE_QUERY;
7971 }
7972 }
7973
7974 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
7975 /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
7976 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
7977 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
7978 {
7979 rr_search -> nx_mdns_rr_poof_count ++;
7980
7981 /* After seeing two or more of these queries, and seeing no multicast response containing the expected anser within ten seconds, the record should be flushed from the cache. */
7982 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
7983 (rr_search -> nx_mdns_rr_poof_count >= NX_MDNS_POOF_MIN_COUNT))
7984 {
7985 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_POOF_DELETE;
7986 rr_search -> nx_mdns_rr_timer_count = NX_MDNS_POOF_TIMER_COUNT;
7987
7988 /* Set the mDNS timer. */
7989 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
7990 }
7991 }
7992 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
7993 }
7994 }
7995 }
7996 #endif /* NX_MDNS_DISABLE_CLIENT */
7997
7998 #ifndef NX_MDNS_DISABLE_SERVER
7999
8000 /* Step2, mDNS Server process the normal query. */
8001 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8002 {
8003
8004 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8005 /* Set the match count. */
8006 match_count = 0;
8007 nsec_rr = NX_NULL;
8008 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8009
8010 /* Get head. */
8011 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8012 head = (ULONG*)(*head);
8013
8014 /* Find the same record. */
8015 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
8016 {
8017
8018 /* Check the interface index. */
8019 if (p -> nx_mdns_rr_interface_index != interface_index)
8020 continue;
8021
8022 /* Check whether the resource record is valid. */
8023 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
8024 continue;
8025
8026 /* Check whether the same record it is. RFC6762, Section6, Page13. */
8027 /* The rules: rrname must match the question name.
8028 rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
8029 rrclass must match the question qclass unless the qclass is "ANY". */
8030 if (p -> nx_mdns_rr_name != temp_resource_record.nx_mdns_rr_name)
8031 continue;
8032
8033 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8034
8035 /* Check the NSEC type. */
8036 if (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
8037 nsec_rr = p;
8038 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8039
8040 if ((p -> nx_mdns_rr_type != temp_resource_record.nx_mdns_rr_type) &&
8041 (temp_resource_record.nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
8042 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
8043 continue;
8044
8045 /* Check the RR class, Ignore the top bit. */
8046 if ((p -> nx_mdns_rr_class != (temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
8047 ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)!= NX_MDNS_RR_CLASS_ALL))
8048 continue;
8049
8050 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8051
8052 /* Update the match count. */
8053 match_count ++;
8054 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8055
8056 /* Check the state. */
8057 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8058 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
8059 {
8060
8061 /* Check the send flag, Flag is set indicate this resource record shoud be sent. */
8062 if (p -> nx_mdns_rr_send_flag)
8063 {
8064
8065 /* Set the flag to send this Resource records via multicast.
8066 Store the old flag into the top bits.
8067 Store the new flag into the low bits.
8068 Format: 0001 0001 */
8069 p -> nx_mdns_rr_send_flag = ((NX_MDNS_RR_SEND_MULTICAST << 4) | NX_MDNS_RR_SEND_MULTICAST);
8070 }
8071 else
8072 {
8073
8074 /* Set the flag to send this Resource records via multicast.*/
8075 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8076 }
8077
8078 /* In the case where the query has the TC (truncated) bit set, indicating that subsequent Known-Answer packets will follow,
8079 Responders SHOULD delay their responses by a random amount of time selected with uniform random distribution in the range 400-500ms. RFC6762, Section6, Page 15. */
8080 if (mdns_flags & NX_MDNS_TC_FLAG)
8081 {
8082 p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_TC_DELAY_RANGE));
8083 }
8084 else
8085 {
8086
8087 /* A mDNS responder is only required to delay its transmission as necessary to ensure an interval of at least 250ms
8088 since the last time the record was multicast on that interface. RFC6762, Section6, Page16 */
8089 if (authority_count)
8090 {
8091 if (p -> nx_mdns_rr_response_interval > (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT))
8092 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT));
8093 else
8094 p -> nx_mdns_rr_response_interval = 0;
8095 }
8096
8097 /* Check the response interval. */
8098 if (p -> nx_mdns_rr_response_interval <= NX_MDNS_TIMER_COUNT_RANGE)
8099 {
8100
8101 /* Set the timer count according to the resource record set.RFC6762, Section6, Page14. */
8102 if ((p ->nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) == NX_MDNS_RR_FLAG_UNIQUE)
8103 {
8104 p -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8105 }
8106 else
8107 {
8108 /* Set the timer count, delay 20-120ms. */
8109 p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8110 }
8111 }
8112 else
8113 {
8114 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_response_interval;
8115 }
8116 }
8117
8118 /* Set the mDNS timer. */
8119 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
8120 }
8121 }
8122
8123 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8124 /* Send this NSEC response as additional answer. */
8125 if ((match_count == 0) && (nsec_rr))
8126 {
8127 nsec_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_TRUE;
8128 nsec_rr -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8129 _nx_mdns_timer_set(mdns_ptr, nsec_rr, nsec_rr -> nx_mdns_rr_timer_count);
8130 }
8131 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8132 }
8133 #endif /* NX_MDNS_DISABLE_SERVER */
8134
8135 /* Update the data_ptr. */
8136 data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
8137 }
8138 }
8139
8140 /* Process all the Known-Answer records. */
8141 for (index = 0; index < answer_count; index++)
8142 {
8143
8144 /* Check for data_ptr. */
8145 if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
8146 break;
8147
8148 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
8149 {
8150
8151 #ifndef NX_MDNS_DISABLE_SERVER
8152 /* Step1, Cooperating Multicast DNS Responders, RFC6762, Section6.6, Page21. */
8153 /* Does the same rname and rdata name of resource record exist in the local buffer. */
8154 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8155 {
8156
8157 /* Find the same rname, rrtype, rrclass of resource record in local buffer. */
8158 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8159 {
8160
8161 /* Probing state, conflict Resolution. */
8162 if ((rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) &&
8163 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING))
8164 {
8165 _nx_mdns_conflict_process(mdns_ptr, rr_search);
8166
8167 /* Update the data_ptr. */
8168 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8169
8170 continue;
8171 }
8172 }
8173
8174 /* Find the same rname, rrtype, rrclass and identical rdata of resource record in local buffer. */
8175 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8176 {
8177
8178 /* If the TTL in this record(B) is less than half the true TTL in local record(A), A MUST announce local record via multicast. RFC6762, Section6.6,Page21. */
8179 if ((temp_resource_record.nx_mdns_rr_ttl << 1) < rr_search -> nx_mdns_rr_ttl)
8180 {
8181
8182 /* Set the flag. */
8183 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8184
8185 /* Set the timer count, delay 20-120ms. */
8186 rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8187
8188 /* Set the mDNS timer. */
8189 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
8190 }
8191
8192 /* Duplicate Answer Suppression, RFC6762, Section7.4,Page24.
8193 The TTL in that record is not less than the TTL this host would have given. Host should not send this response again. */
8194 if (temp_resource_record.nx_mdns_rr_ttl >= rr_search -> nx_mdns_rr_ttl)
8195 {
8196
8197 if (rr_search -> nx_mdns_rr_send_flag)
8198 {
8199
8200 /* Clear the flag. */
8201 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8202 }
8203 }
8204
8205 /* Check the resource records set. */
8206 if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8207 {
8208
8209 /* Update the data_ptr. */
8210 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8211
8212 continue;
8213 }
8214 }
8215 }
8216
8217 /* Did the same name of resource record have existed in local buffer. */
8218 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8219 {
8220
8221 /* Find the same name, rrtype, rrclass and different rdata of resource record in local buffer. */
8222 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8223 {
8224
8225 /* Check the resource records set. RFC6762, Section6.6, Page21. */
8226 if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8227 {
8228 _nx_mdns_conflict_process(mdns_ptr, rr_search);
8229
8230 /* Update the data_ptr. */
8231 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8232
8233 continue;
8234 }
8235 }
8236 }
8237 #endif /* NX_MDNS_DISABLE_SERVER */
8238
8239 #ifndef NX_MDNS_DISABLE_CLIENT
8240 /* Step2. Add the response resource records in remote buffer. */
8241 _nx_mdns_packet_rr_process(mdns_ptr, packet_ptr, data_ptr, interface_index);
8242 #endif /* NX_MDNS_DISABLE_CLIENT */
8243 }
8244 else
8245 {
8246 #ifndef NX_MDNS_DISABLE_CLIENT
8247 /* Clear the record. */
8248
8249 /* Step1, mDNS Client process the Known-Answer about Duplicate Question Suppression. */
8250 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8251 {
8252
8253 /* Find the same resource record in remote buffer. */
8254 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8255 {
8256
8257 /* Duplicate Question Suppression. */
8258 if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
8259 {
8260
8261 /* Yes, the query includes the Known-Answer Section, clear the duplicate flag. */
8262 rr_search -> nx_mdns_rr_word = (USHORT)(rr_search -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
8263 }
8264
8265 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
8266 /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
8267 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8268 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
8269 {
8270 rr_search -> nx_mdns_rr_poof_count --;
8271
8272 /* Check the count. */
8273 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE) &&
8274 (rr_search -> nx_mdns_rr_poof_count < NX_MDNS_POOF_MIN_COUNT))
8275 {
8276 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
8277 rr_search -> nx_mdns_rr_timer_count = 0;
8278 }
8279 }
8280 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
8281 }
8282 }
8283 #endif /* NX_MDNS_DISABLE_CLIENT */
8284
8285 #ifndef NX_MDNS_DISABLE_SERVER
8286
8287 /* Step2. mDNS Server process the Known-Answer of normal query. */
8288 if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8289 {
8290
8291 /* Find the same resource record. */
8292 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8293 {
8294
8295 /* mDNS responder Must Not answer a mDNS query if the answer included the Answer Section with an RR TTL at least half the correct value. RFC6762, Section7.1, Page23. */
8296 if ((!(rr_search -> nx_mdns_rr_send_flag & NX_MDNS_RR_SEND_FLAG_MASK)) &&
8297 ((temp_resource_record.nx_mdns_rr_ttl << 1) >= rr_search -> nx_mdns_rr_ttl))
8298 {
8299
8300 /* Top four bit is zero and this resource reocrd is Known answer.
8301 Clear the send flag. */
8302 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8303 }
8304 }
8305 }
8306 #endif /* NX_MDNS_DISABLE_SERVER */
8307 }
8308
8309 /* Update the data_ptr. */
8310 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8311 }
8312
8313 return(NX_MDNS_SUCCESS);
8314 }
8315
8316
8317 #ifndef NX_MDNS_DISABLE_SERVER
8318 /**************************************************************************/
8319 /* */
8320 /* FUNCTION RELEASE */
8321 /* */
8322 /* _nx_mdns_probing_send PORTABLE C */
8323 /* 6.1 */
8324 /* AUTHOR */
8325 /* */
8326 /* Yuxin Zhou, Microsoft Corporation */
8327 /* */
8328 /* DESCRIPTION */
8329 /* */
8330 /* This function sends mDNS probing message. */
8331 /* */
8332 /* INPUT */
8333 /* */
8334 /* mdns_ptr Pointer to mDNS instance */
8335 /* */
8336 /* OUTPUT */
8337 /* */
8338 /* none */
8339 /* */
8340 /* CALLS */
8341 /* */
8342 /* */
8343 /* CALLED BY */
8344 /* */
8345 /* */
8346 /* RELEASE HISTORY */
8347 /* */
8348 /* DATE NAME DESCRIPTION */
8349 /* */
8350 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8351 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8352 /* resulting in version 6.1 */
8353 /* */
8354 /**************************************************************************/
_nx_mdns_probing_send(NX_MDNS * mdns_ptr,UINT interface_index)8355 static VOID _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8356 {
8357
8358 UINT status;
8359 NX_PACKET *packet_ptr;
8360 ULONG *head;
8361 NX_MDNS_RR *p;
8362 USHORT question_count = 0;
8363 USHORT answer_count = 0;
8364 USHORT authority_count = 0;
8365 USHORT additional_count = 0;
8366 UCHAR resend_flag = NX_FALSE;
8367 USHORT total_size;
8368 USHORT rr_size;
8369 UINT name_size;
8370 NX_MDNS_RR *p1;
8371 UINT rr_name_length;
8372
8373
8374 /* Create the mdns packet and add the mDNS header. */
8375 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8376
8377 /* Check for errors. */
8378 if (status != NX_SUCCESS)
8379 {
8380 return;
8381 }
8382
8383 /* Set the total size. */
8384 total_size = (USHORT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
8385
8386 /* Set the head pointer. */
8387 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8388
8389 /* Add the answer resource record. */
8390 for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8391 {
8392
8393 /* Check the interface index. */
8394 if (p -> nx_mdns_rr_interface_index != interface_index)
8395 continue;
8396
8397 /* Check the send flag. */
8398 if (p -> nx_mdns_rr_send_flag == 0)
8399 continue;
8400
8401 /* Check the state. */
8402 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8403 continue;
8404
8405 /* Add the resource record into packet. */
8406
8407 /* Calculate the question and answer size before sending the probing message, make sure the question and authority in one packet. */
8408
8409 /* Check string length. */
8410 if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
8411 {
8412 continue;
8413 }
8414
8415 /* Calculate the name size. The name should plus the '.' and '\0'. */
8416 name_size = rr_name_length + 2;
8417
8418 /* Calculate the resource record size for question. QNAME, QTYPE, QCLASS. */
8419 rr_size = (USHORT)(name_size + 4);
8420
8421 /* Calcuate the resource record size for authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
8422 rr_size = (USHORT)(rr_size + (name_size + 10 + p -> nx_mdns_rr_rdata_length));
8423
8424 /* Check if need add other authority answers for this same question. */
8425 for(p1 = (NX_MDNS_RR*)(head + 1); (ULONG)p1 < *head; p1++)
8426 {
8427
8428 /* Check the interface index. */
8429 if (p1 -> nx_mdns_rr_interface_index != interface_index)
8430 continue;
8431
8432 /* Check the state. */
8433 if (p1 -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8434 continue;
8435
8436 /* Check the name and flag. */
8437 if ((p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name) &&
8438 (p1 -> nx_mdns_rr_send_flag) &&
8439 (p1 != p))
8440 {
8441
8442 /* Calculate the resource record size for other authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
8443 rr_size = (USHORT)(rr_size + (name_size + 10 + p1 -> nx_mdns_rr_rdata_length));
8444
8445 /* Check the packet size. */
8446 if (rr_size <= total_size)
8447 {
8448
8449 /* Set the authority answer flag. */
8450 p1 -> nx_mdns_rr_word = p1 -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8451
8452 /* Clear the send flag. */
8453 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8454 }
8455 else
8456 {
8457 resend_flag = NX_TRUE;
8458 break;
8459 }
8460 }
8461 }
8462
8463 /* Check the packet size. */
8464 if (rr_size > total_size)
8465 {
8466 resend_flag = NX_TRUE;
8467 continue;
8468 }
8469 else
8470 total_size = (USHORT)(total_size - rr_size);
8471
8472 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_PROBING);
8473
8474 if (status)
8475 {
8476 resend_flag = NX_TRUE;
8477 }
8478 else
8479 {
8480
8481 /* Set the authority answer flag. */
8482 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8483
8484 /* Update the question count. */
8485 question_count ++;
8486
8487 /* Clear the flag. */
8488 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8489 }
8490 }
8491
8492 /* Add the authority answer resource record. */
8493 for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8494 {
8495
8496 /* Check the interface index. */
8497 if (p -> nx_mdns_rr_interface_index != interface_index)
8498 continue;
8499
8500 /* Check whether set the resource record send flag. */
8501 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING) &&
8502 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_AUTHORIY_ANSWER))
8503 {
8504
8505 /* Add the resource record into packet. */
8506 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_PROBING);
8507 if (status)
8508 resend_flag = NX_TRUE;
8509 else
8510 {
8511
8512 /* Update the retransmit count. */
8513 p -> nx_mdns_rr_retransmit_count --;
8514
8515 /* Update the authority count. */
8516 authority_count ++;
8517
8518 /* Clear the additional flag. */
8519 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_AUTHORIY_ANSWER));
8520 }
8521 }
8522
8523 /* Clear the answer flag. */
8524 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8525 }
8526
8527 if (!question_count &&
8528 !answer_count &&
8529 !authority_count &&
8530 !additional_count)
8531 {
8532
8533 /* Release the packet. */
8534 nx_packet_release(packet_ptr);
8535 return;
8536 }
8537
8538 /* Update the question count in header. */
8539 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8540
8541 /* Update the answer count in header. */
8542 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8543 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8544 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8545
8546 /* Send the mDNS packet. */
8547 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8548
8549 /* Resend the packet. */
8550 if (resend_flag)
8551 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_PROBING_SEND_EVENT, TX_OR);
8552 }
8553
8554
8555 /**************************************************************************/
8556 /* */
8557 /* FUNCTION RELEASE */
8558 /* */
8559 /* _nx_mdns_announcing_send PORTABLE C */
8560 /* 6.1 */
8561 /* AUTHOR */
8562 /* */
8563 /* Yuxin Zhou, Microsoft Corporation */
8564 /* */
8565 /* DESCRIPTION */
8566 /* */
8567 /* This function sends mDNS announcing message. */
8568 /* */
8569 /* INPUT */
8570 /* */
8571 /* mdns_ptr Pointer to mDNS instance */
8572 /* */
8573 /* OUTPUT */
8574 /* */
8575 /* status Completion status */
8576 /* */
8577 /* CALLS */
8578 /* */
8579 /* */
8580 /* CALLED BY */
8581 /* */
8582 /* */
8583 /* RELEASE HISTORY */
8584 /* */
8585 /* DATE NAME DESCRIPTION */
8586 /* */
8587 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8588 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8589 /* resulting in version 6.1 */
8590 /* */
8591 /**************************************************************************/
_nx_mdns_announcing_send(NX_MDNS * mdns_ptr,UINT interface_index)8592 static VOID _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8593 {
8594
8595 UINT status;
8596 NX_PACKET *packet_ptr;
8597 NX_PACKET *new_packet_ptr;
8598 ULONG *head;
8599 NX_MDNS_RR *p;
8600 USHORT question_count = 0;
8601 USHORT answer_count = 0;
8602 USHORT authority_count = 0;
8603 USHORT additional_count = 0;
8604 UINT i;
8605 UCHAR resend_flag = NX_FALSE;
8606
8607
8608 /* Create the mdns packet and add the mDNS header. */
8609 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8610
8611 /* Check for errors. */
8612 if (status != NX_SUCCESS)
8613 {
8614 return;
8615 }
8616
8617 /* Set the head pointer. */
8618 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8619
8620 /* Add the answer resource record. */
8621 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8622 {
8623
8624 /* Check the interface index. */
8625 if (p -> nx_mdns_rr_interface_index != interface_index)
8626 continue;
8627
8628 if(p -> nx_mdns_rr_send_flag == 0)
8629 continue;
8630
8631 /* Check valid state. */
8632 if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) ||
8633 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8634 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID))))
8635 continue;
8636
8637 /* Add the resource record into packet. */
8638 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8639
8640 if (status)
8641 {
8642 resend_flag = NX_TRUE;
8643 }
8644 else
8645 {
8646
8647 /* Update the retransmit count. */
8648 p -> nx_mdns_rr_retransmit_count --;
8649
8650 /* Update the count. */
8651 answer_count++;
8652
8653 /* Clear the flag. */
8654 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8655 }
8656 }
8657
8658 if (!question_count &&
8659 !answer_count &&
8660 !authority_count &&
8661 !additional_count)
8662 {
8663
8664 /* Release the packet. */
8665 nx_packet_release(packet_ptr);
8666 return;
8667 }
8668
8669 /* Update the question count in header. */
8670 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8671
8672 /* Update the answer count in header. */
8673 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8674 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8675 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8676
8677 /* If the interval time is 0, repeat advertise. */
8678 if (!mdns_ptr -> nx_mdns_announcing_retrans_interval)
8679 {
8680 for (i = 1; i < mdns_ptr -> nx_mdns_announcing_count; i ++)
8681 {
8682
8683 /* Allocate new packet. */
8684 status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
8685
8686 /* Check for errors. */
8687 if (status)
8688 {
8689 break;
8690 }
8691
8692 /* Send the mDNS packet. */
8693 _nx_mdns_packet_send(mdns_ptr, new_packet_ptr, interface_index);
8694 }
8695 }
8696
8697 /* Send the mDNS packet. */
8698 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8699
8700 /* Resend the packet. */
8701 if (resend_flag)
8702 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_ANNOUNCING_SEND_EVENT, TX_OR);
8703
8704 return;
8705 }
8706
8707
8708 /**************************************************************************/
8709 /* */
8710 /* FUNCTION RELEASE */
8711 /* */
8712 /* _nx_mdns_response_send PORTABLE C */
8713 /* 6.1 */
8714 /* AUTHOR */
8715 /* */
8716 /* Yuxin Zhou, Microsoft Corporation */
8717 /* */
8718 /* DESCRIPTION */
8719 /* */
8720 /* This function sends mDNS response. */
8721 /* */
8722 /* INPUT */
8723 /* */
8724 /* mdns_ptr Pointer to mDNS instance */
8725 /* */
8726 /* OUTPUT */
8727 /* */
8728 /* none */
8729 /* */
8730 /* CALLS */
8731 /* */
8732 /* */
8733 /* CALLED BY */
8734 /* */
8735 /* */
8736 /* RELEASE HISTORY */
8737 /* */
8738 /* DATE NAME DESCRIPTION */
8739 /* */
8740 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8741 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8742 /* resulting in version 6.1 */
8743 /* */
8744 /**************************************************************************/
_nx_mdns_response_send(NX_MDNS * mdns_ptr,UINT interface_index)8745 static VOID _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index)
8746 {
8747
8748 UINT status;
8749 NX_PACKET *packet_ptr;
8750 ULONG *head;
8751 NX_MDNS_RR *p;
8752 USHORT question_count = 0;
8753 USHORT answer_count = 0;
8754 USHORT authority_count = 0;
8755 USHORT additional_count = 0;
8756 UCHAR resend_flag = NX_FALSE;
8757
8758
8759 /* Create the mdns packet and add the mDNS header. */
8760 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8761
8762 /* Check for errors. */
8763 if (status != NX_SUCCESS)
8764 {
8765 return;
8766 }
8767
8768 /* Set the head pointer. */
8769 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8770
8771 /* Add the answer resource record. */
8772 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8773 {
8774
8775 /* Check the interface index. */
8776 if (p -> nx_mdns_rr_interface_index != interface_index)
8777 continue;
8778
8779 if(p -> nx_mdns_rr_send_flag == 0)
8780 continue;
8781
8782 /* Check valid state. */
8783 if ((p -> nx_mdns_rr_timer_count != 0) ||
8784 !((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8785 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)))
8786 continue;
8787
8788 /* Add the resource record into packet. */
8789 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8790
8791 if (status)
8792 {
8793 resend_flag = NX_TRUE;
8794 }
8795 else
8796 {
8797
8798 /* Set the answer flag to skip the resource record which has been added in answer section when find the additional records. */
8799 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ANSWER;
8800
8801 /* When including a DNS-SD Service Instance Enumeration or Selective Instance Enumeration PTR record in a response packet,
8802 the server/responder SHOULD include the folowing additional records, SRV,TXT, A and AAAA.RFC3763, Section12.1, Page30. */
8803 _nx_mdns_additional_resource_record_find(mdns_ptr, p);
8804
8805 /* Update the count. */
8806 answer_count++;
8807
8808 /* Clear the flag. */
8809 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8810 }
8811 }
8812
8813 /* Add the additional answer resource record. */
8814 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8815 {
8816
8817 /* Check the interface index. */
8818 if (p -> nx_mdns_rr_interface_index != interface_index)
8819 continue;
8820
8821 /* Check whether set the resource record send flag. */
8822 if ((p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ADDITIONAL) &&
8823 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8824 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)))
8825 {
8826
8827 /* Add the resource record into packet. */
8828 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8829 if (status)
8830 {
8831 resend_flag = NX_TRUE;
8832 }
8833 else
8834 {
8835
8836 /* Update the additional count. */
8837 additional_count++;
8838
8839 /* Clear the additional flag. */
8840 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ADDITIONAL));
8841 }
8842 }
8843
8844 /* Clear the answer flag. */
8845 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8846 }
8847
8848 if (!question_count &&
8849 !answer_count &&
8850 !authority_count &&
8851 !additional_count)
8852 {
8853
8854 /* Release the packet. */
8855 nx_packet_release(packet_ptr);
8856 return;
8857 }
8858
8859 /* Update the question count in header. */
8860 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8861
8862 /* Update the answer count in header. */
8863 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8864 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8865 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8866
8867 /* Send the mDNS packet. */
8868 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8869
8870 /* Resend the packet. */
8871 if (resend_flag)
8872 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_RESPONSE_SEND_EVENT, TX_OR);
8873 }
8874 #endif /* NX_MDNS_DISABLE_SERVER */
8875
8876
8877 #ifndef NX_MDNS_DISABLE_CLIENT
8878 /**************************************************************************/
8879 /* */
8880 /* FUNCTION RELEASE */
8881 /* */
8882 /* _nx_mdns_query_send PORTABLE C */
8883 /* 6.1 */
8884 /* AUTHOR */
8885 /* */
8886 /* Yuxin Zhou, Microsoft Corporation */
8887 /* */
8888 /* DESCRIPTION */
8889 /* */
8890 /* This function sends mDNS query message. */
8891 /* */
8892 /* INPUT */
8893 /* */
8894 /* mdns_ptr Pointer to mDNS instance */
8895 /* */
8896 /* OUTPUT */
8897 /* */
8898 /* none */
8899 /* */
8900 /* CALLS */
8901 /* */
8902 /* */
8903 /* CALLED BY */
8904 /* */
8905 /* */
8906 /* RELEASE HISTORY */
8907 /* */
8908 /* DATE NAME DESCRIPTION */
8909 /* */
8910 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8911 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8912 /* resulting in version 6.1 */
8913 /* */
8914 /**************************************************************************/
_nx_mdns_query_send(NX_MDNS * mdns_ptr,UINT interface_index)8915 static VOID _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index)
8916 {
8917
8918 UINT status;
8919 NX_PACKET *packet_ptr;
8920 ULONG *head;
8921 NX_MDNS_RR *p;
8922 USHORT question_count = 0;
8923 USHORT answer_count = 0;
8924 USHORT authority_count = 0;
8925 USHORT additional_count = 0;
8926 UCHAR resend_flag = NX_FALSE;
8927 USHORT tc_bit;
8928 UCHAR more_known_answer = NX_FALSE;
8929 UINT i;
8930
8931
8932 /* Create the mdns packet and add the mDNS header. */
8933 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8934
8935 /* Check for errors. */
8936 if (status != NX_SUCCESS)
8937 {
8938 return;
8939 }
8940
8941 /* Set the head pointer. */
8942 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8943
8944 /* Add the query resource record. */
8945 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8946 {
8947
8948 /* Check the interface index. */
8949 if (p -> nx_mdns_rr_interface_index != interface_index)
8950 continue;
8951
8952 if(p -> nx_mdns_rr_send_flag == 0)
8953 continue;
8954
8955 /* Check valid state. */
8956 if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY) ||
8957 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING))))
8958 continue;
8959
8960 /* Add the resource record into packet. */
8961 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_QUERY);
8962
8963 if (status)
8964 {
8965 resend_flag = NX_TRUE;
8966 }
8967 else
8968 {
8969
8970 /* Update the retransmit count for UPDATING state. */
8971 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
8972 p -> nx_mdns_rr_retransmit_count --;
8973
8974 /* Update the count. */
8975 question_count++;
8976
8977 /* Find the known answer resource records. */
8978 _nx_mdns_known_answer_find(mdns_ptr, p);
8979
8980 /* Clear the flag. */
8981 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8982 }
8983 }
8984
8985 /* Add the known answer resource record. */
8986 for (i = 0; i < 2; i++)
8987 {
8988 if (i == 0)
8989 {
8990 #ifndef NX_MDNS_DISABLE_SERVER
8991 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8992 #else
8993 continue;
8994 #endif /* NX_MDNS_DISABLE_SERVER */
8995 }
8996 else
8997 {
8998 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8999 }
9000
9001 /* Add the peer resource code as known answer for query. */
9002 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
9003 {
9004
9005 /* Check the interface index. */
9006 if (p -> nx_mdns_rr_interface_index != interface_index)
9007 continue;
9008
9009 /* Check whether set the resource record send flag. */
9010 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
9011 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_KNOWN_ANSWER))
9012 {
9013
9014 /* Add the resource record into packet. */
9015 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_QUERY);
9016 if (status)
9017 {
9018 more_known_answer = NX_TRUE;
9019 resend_flag = NX_TRUE;
9020 }
9021 else
9022 {
9023 /* Update the count. */
9024 answer_count ++;
9025
9026 /* Clear the additional flag. */
9027 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_KNOWN_ANSWER));
9028 }
9029 }
9030
9031 /* Clear the answer flag. */
9032 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
9033 }
9034 }
9035
9036 if (!question_count &&
9037 !answer_count &&
9038 !authority_count &&
9039 !additional_count)
9040 {
9041
9042 /* Release the packet. */
9043 nx_packet_release(packet_ptr);
9044 return;
9045 }
9046
9047 /* Set the TC bit. */
9048 if (more_known_answer)
9049 {
9050 tc_bit = NX_MDNS_TC_FLAG;
9051 *(USHORT *)(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) |= NX_CHANGE_USHORT_ENDIAN(tc_bit);
9052 }
9053
9054 /* Update the question count in header. */
9055 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
9056
9057 /* Update the answer count in header. */
9058 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
9059 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
9060 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
9061
9062 /* Send the mDNS packet. */
9063 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
9064
9065 /* Resend the packet. */
9066 if (resend_flag)
9067 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_QUERY_SEND_EVENT, TX_OR);
9068 }
9069 #endif /* NX_MDNS_DISABLE_CLIENT */
9070
9071
9072 /**************************************************************************/
9073 /* */
9074 /* FUNCTION RELEASE */
9075 /* */
9076 /* _nx_mdns_packet_create PORTABLE C */
9077 /* 6.1 */
9078 /* AUTHOR */
9079 /* */
9080 /* Yuxin Zhou, Microsoft Corporation */
9081 /* */
9082 /* DESCRIPTION */
9083 /* */
9084 /* This function creates the mDNS packet and add the mDNS header data. */
9085 /* */
9086 /* INPUT */
9087 /* */
9088 /* mdns_ptr Pointer to mDNS instance */
9089 /* packet_ptr Pointer to mDNS packet */
9090 /* is_query Query flag */
9091 /* */
9092 /* OUTPUT */
9093 /* */
9094 /* status Completion status */
9095 /* */
9096 /* CALLS */
9097 /* */
9098 /* nx_packet_allocate Allocate the mDNS packet */
9099 /* nx_packet_release Release the mDNS packet */
9100 /* _nx_mdns_short_to_network_convert Add the data into the packet */
9101 /* */
9102 /* CALLED BY */
9103 /* */
9104 /* _nx_mdns_announcing_send Send announcing message */
9105 /* _nx_mdns_probing_send Send probing message */
9106 /* _nx_mdns_query_send Send query message */
9107 /* _nx_mdns_response_send Send response message */
9108 /* */
9109 /* RELEASE HISTORY */
9110 /* */
9111 /* DATE NAME DESCRIPTION */
9112 /* */
9113 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9114 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9115 /* resulting in version 6.1 */
9116 /* */
9117 /**************************************************************************/
_nx_mdns_packet_create(NX_MDNS * mdns_ptr,NX_PACKET ** packet_ptr,UCHAR is_query)9118 static UINT _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR is_query)
9119 {
9120
9121 UINT status;
9122 USHORT flags;
9123
9124
9125 /* Allocate the mDNS packet. */
9126 #ifdef NX_MDNS_ENABLE_IPV6
9127 status = nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv6_UDP_PACKET, NX_NO_WAIT);
9128 #else
9129 status = nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
9130 #endif /* NX_MDNS_ENABLE_IPV6 */
9131
9132 /* Check for errors. */
9133 if (status)
9134 {
9135
9136 /* Return error. */
9137 return(status);
9138 }
9139
9140 /* Check if there is enough room to fill with mDNS header. */
9141 if ((UINT)((*packet_ptr) -> nx_packet_data_end - (*packet_ptr) -> nx_packet_append_ptr) < NX_MDNS_QDSECT_OFFSET)
9142 {
9143
9144 /* Release the packet. */
9145 nx_packet_release(*packet_ptr);
9146 return(NX_MDNS_PACKET_ERROR);
9147 }
9148
9149 /* Add the mDNS header. */
9150
9151 /* Set the transaction ID. */
9152 *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_ID_OFFSET) = 0;
9153
9154 /* Set the flags and Command. */
9155 if (is_query == NX_TRUE)
9156 {
9157 flags = NX_MDNS_QUERY_FLAG;
9158 }
9159 else
9160 {
9161 flags = (NX_MDNS_RESPONSE_FLAG | NX_MDNS_AA_FLAG);
9162 }
9163
9164 /* Adjust for endianness. */
9165 NX_CHANGE_USHORT_ENDIAN(flags);
9166
9167 /* Set the flags and Command. */
9168 *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) = flags;
9169
9170 /* Initialize counts to 0. */
9171 *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET) = 0;
9172 *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET) = 0;
9173
9174 /* Set the pointer. */
9175 (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
9176 (*packet_ptr) -> nx_packet_length = NX_MDNS_QDSECT_OFFSET;
9177
9178 return(NX_MDNS_SUCCESS);
9179 }
9180
9181
9182 /**************************************************************************/
9183 /* */
9184 /* FUNCTION RELEASE */
9185 /* */
9186 /* _nx_mdns_packet_send PORTABLE C */
9187 /* 6.1 */
9188 /* AUTHOR */
9189 /* */
9190 /* Yuxin Zhou, Microsoft Corporation */
9191 /* */
9192 /* DESCRIPTION */
9193 /* */
9194 /* This function sends the mDNS packet. */
9195 /* */
9196 /* INPUT */
9197 /* */
9198 /* mdns_ptr Pointer to mDNS instance */
9199 /* packet_ptr Pointer to mDNS packet */
9200 /* */
9201 /* OUTPUT */
9202 /* */
9203 /* status Completion status */
9204 /* */
9205 /* CALLS */
9206 /* */
9207 /* nx_packet_copy Copy the mDNS packet */
9208 /* nx_packet_release Release the mDNS packet */
9209 /* nx_udp_socket_send Send the udp packet */
9210 /* nxd_udp_socket_send Send the udp packet */
9211 /* */
9212 /* CALLED BY */
9213 /* */
9214 /* _nx_mdns_announcing_send Send announcing message */
9215 /* _nx_mdns_probing_send Send probing message */
9216 /* _nx_mdns_query_send Send query message */
9217 /* _nx_mdns_response_send Send response message */
9218 /* */
9219 /* RELEASE HISTORY */
9220 /* */
9221 /* DATE NAME DESCRIPTION */
9222 /* */
9223 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9224 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9225 /* resulting in version 6.1 */
9226 /* */
9227 /**************************************************************************/
_nx_mdns_packet_send(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)9228 static VOID _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
9229 {
9230
9231 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
9232 UINT status;
9233 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
9234 #ifdef NX_MDNS_ENABLE_IPV6
9235 UINT ipv6_packet = NX_FALSE;
9236 NX_PACKET *new_packet_ptr;
9237 UINT address_index = mdns_ptr -> nx_mdns_ipv6_address_index[interface_index];
9238 #endif /* NX_MDNS_ENABLE_IPV6 */
9239
9240
9241 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
9242 NX_PARAMETER_NOT_USED(mdns_ptr);
9243 NX_PARAMETER_NOT_USED(interface_index);
9244 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6 */
9245
9246 #ifdef NX_MDNS_ENABLE_IPV6
9247 if (address_index != 0xFFFFFFFF)
9248 {
9249
9250 /* Allocate new IPv6 packet. */
9251 status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
9252
9253 /* Check for errors. */
9254 if (!status)
9255 {
9256 ipv6_packet = NX_TRUE;
9257 }
9258 }
9259 #endif /* NX_MDNS_ENABLE_IPV6 */
9260
9261 #ifndef NX_DISABLE_IPV4
9262 /* Send the IPv4 mDNS message. */
9263 status = nx_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, packet_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, interface_index);
9264
9265 /* If an error is detected, the packet was not sent and we have to release the packet. */
9266 if (status != NX_SUCCESS)
9267 {
9268
9269 /* Release the packet. */
9270 nx_packet_release(packet_ptr);
9271 }
9272 #else
9273
9274 /* Release the packet. */
9275 nx_packet_release(packet_ptr);
9276 #endif /* NX_DISABLE_IPV4 */
9277
9278 #ifdef NX_MDNS_ENABLE_IPV6
9279
9280 /* Check if send IPv6 packet. */
9281 if (ipv6_packet == NX_TRUE)
9282 {
9283
9284 /* Send the IPv6 mDNS message. */
9285 status = nxd_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, new_packet_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, address_index);
9286
9287 /* If an error is detected, the packet was not sent and we have to release the packet. */
9288 if (status != NX_SUCCESS)
9289 {
9290
9291 /* Release the packet. */
9292 nx_packet_release(new_packet_ptr);
9293 }
9294 }
9295 #endif /* NX_MDNS_ENABLE_IPV6 */
9296 }
9297
9298
9299 /**************************************************************************/
9300 /* */
9301 /* FUNCTION RELEASE */
9302 /* */
9303 /* _nx_mdns_packet_rr_add PORTABLE C */
9304 /* 6.1 */
9305 /* AUTHOR */
9306 /* */
9307 /* Yuxin Zhou, Microsoft Corporation */
9308 /* */
9309 /* DESCRIPTION */
9310 /* */
9311 /* This function adds the mDNS resource record into the packet. */
9312 /* */
9313 /* INPUT */
9314 /* */
9315 /* mdns_ptr Pointer to mDNS instance */
9316 /* packet_ptr Pointer to mDNS packet */
9317 /* rr Pointer to mDNS record */
9318 /* op RR adding Operation */
9319 /* packet_type Packet type */
9320 /* */
9321 /* OUTPUT */
9322 /* */
9323 /* status Completion status */
9324 /* */
9325 /* CALLS */
9326 /* */
9327 /* _nx_mdns_name_string_encode Encode the name string */
9328 /* _nx_mdns_short_to_network_convert Convert and add the data */
9329 /* _nx_mdns_txt_string_encode Encode the txt string */
9330 /* */
9331 /* CALLED BY */
9332 /* */
9333 /* _nx_mdns_announcing_send Send announcing message */
9334 /* _nx_mdns_probing_send Send probing message */
9335 /* _nx_mdns_query_send Send query message */
9336 /* _nx_mdns_response_send Send response message */
9337 /* */
9338 /* RELEASE HISTORY */
9339 /* */
9340 /* DATE NAME DESCRIPTION */
9341 /* */
9342 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9343 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9344 /* verified memcpy use cases, */
9345 /* resulting in version 6.1 */
9346 /* */
9347 /**************************************************************************/
_nx_mdns_packet_rr_add(NX_PACKET * packet_ptr,NX_MDNS_RR * rr,UINT op,UINT packet_type)9348 static UINT _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type)
9349 {
9350
9351 USHORT size = 0;
9352 USHORT index = 0;
9353 USHORT rr_size = 0;
9354 USHORT rdata_length_index = 0;
9355 UCHAR *data_ptr = packet_ptr -> nx_packet_append_ptr;
9356 UINT rr_name_length;
9357
9358
9359 /* Check string length. */
9360 if (_nx_utility_string_length_check((CHAR *)rr -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9361 {
9362 return (NX_MDNS_DATA_SIZE_ERROR);
9363 }
9364
9365 /* Check whether set the resource record send flag. */
9366 if(op == NX_MDNS_PACKET_ADD_RR_QUESTION)
9367 {
9368
9369 /* The name size is should add the '.' and '\0', Calcuate the resource record size. QNAME, QTYPE, QCLASS. */
9370 rr_size = (USHORT)(rr_name_length + 2 + 4);
9371
9372 if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9373 {
9374 return(NX_MDNS_PACKET_ERROR);
9375 }
9376
9377 /* Encode and add the name. */
9378 size = (USHORT)_nx_mdns_name_string_encode(data_ptr, rr -> nx_mdns_rr_name);
9379
9380 /* Updat the index. */
9381 index = (USHORT)(index + size);
9382
9383 /* Add the type. */
9384 if(packet_type == NX_MDNS_PACKET_PROBING)
9385 {
9386 _nx_mdns_short_to_network_convert(data_ptr + index, NX_MDNS_RR_TYPE_ALL);
9387 }
9388 else
9389 {
9390 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9391 }
9392 index = (USHORT)(index + 2);
9393
9394 /* Add the class. */
9395 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9396 index = (USHORT)(index + 2);
9397 }
9398
9399 /* Check whether set the resource record send flag. */
9400 else
9401 {
9402
9403 /* Calcuate the resource record size. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
9404 rr_size = (USHORT)(rr_name_length + 2 + 10 + rr -> nx_mdns_rr_rdata_length);
9405
9406 if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9407 {
9408 return(NX_MDNS_PACKET_ERROR);
9409 }
9410
9411 /* Encode and add the name. */
9412 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_name);
9413
9414 /* Updat the index. */
9415 index = (USHORT)(index + size);
9416
9417 /* Add the type and class. */
9418 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9419 index = (USHORT)(index + 2);
9420
9421 /* Add the class. */
9422 if ((!(rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)) &&
9423 (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE))
9424 {
9425 _nx_mdns_short_to_network_convert(data_ptr + index, ((rr -> nx_mdns_rr_class) | NX_MDNS_RR_CLASS_TOP_BIT));
9426 }
9427 else
9428 {
9429
9430 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9431 }
9432 index = (USHORT)(index + 2);
9433
9434 /* Add the ttl. */
9435 /* Check the resource record owner. */
9436 if (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)
9437 {
9438 /* Add the remaining ttl of peer resource reocrd. */
9439 _nx_mdns_long_to_network_convert(data_ptr + index, (rr -> nx_mdns_rr_remaining_ticks / NX_IP_PERIODIC_RATE));
9440 }
9441 else
9442 {
9443 if (rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE)
9444 {
9445 _nx_mdns_long_to_network_convert(data_ptr + index, 0);
9446 }
9447 else
9448 {
9449 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_ttl);
9450 }
9451 }
9452 index = (USHORT)(index + 4);
9453
9454 /* Compare the RDATA. */
9455 switch (rr -> nx_mdns_rr_type)
9456 {
9457
9458 case NX_MDNS_RR_TYPE_A:
9459 {
9460
9461 /* Add the rdata length. */
9462 _nx_mdns_short_to_network_convert(data_ptr + index, 4);
9463 index = (USHORT)(index + 2);
9464
9465 /* Add the rdata. */
9466 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address);
9467 index = (USHORT)(index + 4);
9468
9469 break;
9470 }
9471 case NX_MDNS_RR_TYPE_AAAA:
9472 {
9473
9474 /* Add the rdata length. */
9475 _nx_mdns_short_to_network_convert(data_ptr + index, 16);
9476 index = (USHORT)(index + 2);
9477
9478 /* Add the rdata. */
9479 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0]);
9480 index = (USHORT)(index + 4);
9481 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1]);
9482 index = (USHORT)(index + 4);
9483 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2]);
9484 index = (USHORT)(index + 4);
9485 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3]);
9486 index = (USHORT)(index + 4);
9487
9488 break;
9489 }
9490 case NX_MDNS_RR_TYPE_PTR:
9491 {
9492
9493 /* Record the rdata length index then skip the rdata length. */
9494 rdata_length_index = index;
9495 index = (USHORT)(index + 2);
9496
9497 /* Encode and add the name. */
9498 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name);
9499 index = (USHORT)(index + size);
9500
9501 /* Add the rdata length. */
9502 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9503
9504 break;
9505 }
9506 case NX_MDNS_RR_TYPE_SRV:
9507 {
9508
9509 /* Record the rdata length index then skip the rdata length. */
9510 rdata_length_index = index;
9511 index = (USHORT)(index + 2);
9512
9513 /* Add the prority. */
9514 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority);
9515 index = (USHORT)(index + 2);
9516
9517 /* Add the weights. */
9518 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights);
9519 index = (USHORT)(index + 2);
9520
9521 /* Add the port. */
9522 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port);
9523 index = (USHORT)(index + 2);
9524
9525 /* Encode and add the name. */
9526 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target);
9527 index = (USHORT)(index + size);
9528
9529 /* Add the rdata length. */
9530 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 6));
9531
9532 break;
9533 }
9534 case NX_MDNS_RR_TYPE_TXT:
9535 {
9536
9537 /* Record the rdata length index then skip the rdata length. */
9538 rdata_length_index = index;
9539 index = (USHORT)(index + 2);
9540
9541 if (rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
9542 {
9543
9544 /* Encode and add the text. */
9545 size = (USHORT)_nx_mdns_txt_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data);
9546 }
9547 else
9548 {
9549
9550 /* Encode the null. */
9551 *(data_ptr + index) = 0;
9552 size = 1;
9553 }
9554 index = (USHORT)(index + size);
9555
9556 /* Add the rdata length. */
9557 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9558
9559 break;
9560 }
9561
9562 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
9563 case NX_MDNS_RR_TYPE_CNAME:
9564 {
9565
9566 /* Record the rdata length index then skip the rdata length. */
9567 rdata_length_index = index;
9568 index = (USHORT)(index + 2);
9569
9570 /* Encode and add the name. */
9571 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_cname.nx_mdns_rr_cname_name);
9572 index = (USHORT)(index + size);
9573
9574 /* Add the rdata length. */
9575 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9576
9577 break;
9578 }
9579 case NX_MDNS_RR_TYPE_NS:
9580 {
9581
9582 /* Record the rdata length index then skip the rdata length. */
9583 rdata_length_index = index;
9584 index = (USHORT)(index + 2);
9585
9586 /* Encode and add the name. */
9587 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ns.nx_mdns_rr_ns_name);
9588 index = (USHORT)(index + size);
9589
9590 /* Add the rdata length. */
9591 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9592
9593 break;
9594 }
9595 case NX_MDNS_RR_TYPE_MX:
9596 {
9597
9598 /* Record the rdata length index then skip the rdata length. */
9599 rdata_length_index = index;
9600 index = (USHORT)(index + 2);
9601
9602 /* Add the preference. */
9603 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference);
9604 index = (USHORT)(index + 2);
9605
9606 /* Encode and add the name. */
9607 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name);
9608 index = (USHORT)(index + size);
9609
9610 /* Add the rdata length. */
9611 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2));
9612
9613 break;
9614 }
9615 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
9616
9617 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
9618 case NX_MDNS_RR_TYPE_NSEC:
9619 {
9620
9621 /* Record the rdata length index then skip the rdata length. */
9622 rdata_length_index = index;
9623 index = (USHORT)(index + 2);
9624
9625 /* Encode and add the next domain name. */
9626 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain);
9627 index = (USHORT)(index + size);
9628
9629 /* Add the window block. */
9630 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block;
9631 index++;
9632
9633 /* Add the bitmap length. */
9634 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length;
9635 index++;
9636
9637 /* Add the type bit maps. */
9638 memcpy(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length); /* Use case of memcpy is verified. */
9639 index = (USHORT)(index + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length);
9640
9641 /* Add the rdata length. */
9642 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2 + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length));
9643
9644 break;
9645 }
9646 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
9647 }
9648 }
9649
9650 /* Update the append pointer and packet length. */
9651 packet_ptr -> nx_packet_append_ptr += index;
9652 packet_ptr -> nx_packet_length += index;
9653
9654 return(NX_MDNS_SUCCESS);
9655 }
9656
9657
9658 /**************************************************************************/
9659 /* */
9660 /* FUNCTION RELEASE */
9661 /* */
9662 /* _nx_mdns_packet_rr_set PORTABLE C */
9663 /* 6.1.11 */
9664 /* AUTHOR */
9665 /* */
9666 /* Yuxin Zhou, Microsoft Corporation */
9667 /* */
9668 /* DESCRIPTION */
9669 /* */
9670 /* This function sets the resource record info from packet. */
9671 /* */
9672 /* INPUT */
9673 /* */
9674 /* mdns_ptr Pointer to mDNS instance. */
9675 /* packet_ptr Pointer to the packet. */
9676 /* data_ptr Pointer to the data. */
9677 /* rr_ptr Pointer to the record */
9678 /* op Operation: */
9679 /* set question or set answer. */
9680 /* */
9681 /* OUTPUT */
9682 /* */
9683 /* status Completion status */
9684 /* */
9685 /* CALLS */
9686 /* */
9687 /* _nx_mdns_name_string_decode Decode the name string */
9688 /* _nx_mdns_cache_add_string Add the name string */
9689 /* _nx_mdns_cache_add_resource_record Add the resource record */
9690 /* */
9691 /* CALLED BY */
9692 /* */
9693 /* _nx_mdns_packet_process Process mDNS packet */
9694 /* */
9695 /* RELEASE HISTORY */
9696 /* */
9697 /* DATE NAME DESCRIPTION */
9698 /* */
9699 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9700 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9701 /* resulting in version 6.1 */
9702 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
9703 /* buffer length verification, */
9704 /* resulting in version 6.1.3 */
9705 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
9706 /* packet length verification, */
9707 /* resulting in version 6.1.4 */
9708 /* 04-25-2022 Yuxin Zhou Modified comment(s), improved */
9709 /* fixed the issue of timer, */
9710 /* resulting in version 6.1.11 */
9711 /* */
9712 /**************************************************************************/
_nx_mdns_packet_rr_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op,UINT interface_index)9713 static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index)
9714 {
9715
9716 UCHAR *cache_ptr;
9717 UINT cache_size;
9718 UINT cache_type;
9719 USHORT record_class;
9720 UINT status;
9721 UINT temp_string_length;
9722
9723
9724 /* Initialize. */
9725 memset(rr_ptr, 0, sizeof(NX_MDNS_RR));
9726
9727 /* Get cache type and size. */
9728 if ((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) ||
9729 (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER))
9730 {
9731 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
9732 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
9733 cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
9734 }
9735 else
9736 {
9737 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
9738 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
9739 cache_type = NX_MDNS_CACHE_TYPE_PEER;
9740 }
9741
9742 /* Check cache pointer and cache size. */
9743 if ((cache_ptr == NX_NULL) || (cache_size == 0))
9744 {
9745 return(NX_MDNS_ERROR);
9746 }
9747
9748 /* Set the interface. */
9749 rr_ptr -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
9750
9751 /* Process the name string. */
9752 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9753 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9754 packet_ptr -> nx_packet_length,
9755 temp_string_buffer, NX_MDNS_NAME_MAX))
9756 {
9757
9758 /* Check string length. */
9759 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9760 {
9761 return(NX_MDNS_DATA_SIZE_ERROR);
9762 }
9763
9764 /* Add the string . */
9765 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
9766 (VOID **)(&rr_ptr -> nx_mdns_rr_name), NX_TRUE, NX_TRUE) != NX_MDNS_SUCCESS)
9767 {
9768 return(NX_MDNS_ERROR);
9769 }
9770 }
9771 else
9772 {
9773 return(NX_MDNS_ERROR);
9774 }
9775
9776 /* Plus 4 for 2 bytes type and 2 bytes class. */
9777 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9778 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9779 {
9780 return(NX_MDNS_ERROR);
9781 }
9782
9783 /* Set the resource record type. */
9784 rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9785
9786 /* Get the resource record class.*/
9787 record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9788
9789 /* Remote RR, set the RR owner flag.*/
9790 if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
9791 rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9792
9793 /* Unique RR, Set the RR set flag. */
9794 if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9795 {
9796 rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9797 }
9798
9799 /* Check the operation and update the record class. */
9800 if((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) || (op == NX_MDNS_RR_OP_PEER_SET_QUESTION))
9801 {
9802 rr_ptr -> nx_mdns_rr_class = record_class;
9803 return(NX_MDNS_SUCCESS);
9804 }
9805 else
9806 {
9807 rr_ptr -> nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9808 }
9809
9810 /* Set the rdata information for answer record. */
9811 status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, rr_ptr, op);
9812
9813 /* Return success. */
9814 return (status);
9815 }
9816
9817
9818 #ifndef NX_MDNS_DISABLE_CLIENT
9819 /**************************************************************************/
9820 /* */
9821 /* FUNCTION RELEASE */
9822 /* */
9823 /* _nx_mdns_packet_rr_process PORTABLE C */
9824 /* 6.1.11 */
9825 /* AUTHOR */
9826 /* */
9827 /* Yuxin Zhou, Microsoft Corporation */
9828 /* */
9829 /* DESCRIPTION */
9830 /* */
9831 /* This function processes the resource record of packet, and add the */
9832 /* record into peer cache. */
9833 /* */
9834 /* INPUT */
9835 /* */
9836 /* mdns_ptr Pointer to mDNS instance. */
9837 /* packet_ptr Pointer to the packet. */
9838 /* data_ptr Pointer to the data. */
9839 /* insert_ptr Pointer to the insert record */
9840 /* op Operation: add answer, set */
9841 /* question or set answer. */
9842 /* cache_ptr The record buffer. */
9843 /* */
9844 /* OUTPUT */
9845 /* */
9846 /* status Completion status */
9847 /* */
9848 /* CALLS */
9849 /* */
9850 /* _nx_mdns_name_string_decode Decode the name string */
9851 /* _nx_mdns_cache_add_string Add the name string */
9852 /* _nx_mdns_cache_add_resource_record Add the resource record */
9853 /* */
9854 /* CALLED BY */
9855 /* */
9856 /* _nx_mdns_packet_process Process mDNS packet */
9857 /* */
9858 /* RELEASE HISTORY */
9859 /* */
9860 /* DATE NAME DESCRIPTION */
9861 /* */
9862 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9863 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9864 /* verified memcpy use cases, */
9865 /* resulting in version 6.1 */
9866 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
9867 /* buffer length verification, */
9868 /* resulting in version 6.1.3 */
9869 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
9870 /* packet length verification, */
9871 /* resulting in version 6.1.4 */
9872 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
9873 /* corrected the random value, */
9874 /* fixed the issue of timer, */
9875 /* resulting in version 6.1.11 */
9876 /* */
9877 /**************************************************************************/
_nx_mdns_packet_rr_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,UINT interface_index)9878 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index)
9879 {
9880
9881 UINT status;
9882 USHORT record_class;
9883 UCHAR is_present;
9884 NX_MDNS_RR rr_ptr;
9885 NX_MDNS_RR *insert_ptr;
9886 NX_MDNS_RR *p;
9887 ULONG *head;
9888 UCHAR *service_name,*service_type,*service_domain;
9889 UINT temp_string_length;
9890 UINT rr_name_length;
9891
9892
9893 /* Check the peer cache. */
9894 if ((mdns_ptr -> nx_mdns_peer_service_cache == NX_NULL) ||
9895 (mdns_ptr -> nx_mdns_peer_service_cache_size == 0))
9896 {
9897 return(NX_MDNS_ERROR);
9898 }
9899
9900 /* Initialize. */
9901 memset(&rr_ptr, 0, sizeof(NX_MDNS_RR));
9902
9903 /* Process the name string. */
9904 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9905 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9906 packet_ptr -> nx_packet_length,
9907 temp_string_buffer, NX_MDNS_NAME_MAX))
9908 {
9909
9910 /* Check string length. */
9911 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9912 {
9913 return(NX_MDNS_DATA_SIZE_ERROR);
9914 }
9915
9916 /* Add the string . */
9917 if(_nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_string_buffer, temp_string_length,
9918 (VOID **)(&rr_ptr.nx_mdns_rr_name), NX_FALSE, NX_TRUE))
9919 {
9920 return(NX_MDNS_ERROR);
9921 }
9922 }
9923 else
9924 {
9925 return(NX_MDNS_ERROR);
9926 }
9927
9928 /* Plus 4 for 2 bytes type and 2 bytes class. */
9929 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9930 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9931 {
9932 return(NX_MDNS_ERROR);
9933 }
9934
9935 /* Set the resource record type. */
9936 rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9937
9938 /* Get the resource record class.*/
9939 record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9940
9941 /* Set the resource record class. */
9942 rr_ptr.nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9943
9944 /* Remote RR, set the RR owner flag.*/
9945 rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9946
9947 /* Unique RR, Set the RR set flag. */
9948 if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9949 {
9950 rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9951 }
9952
9953 /* Set the interface index. */
9954 rr_ptr.nx_mdns_rr_interface_index = (UCHAR)interface_index;
9955
9956 /* Set the rdata information for answer record. */
9957 status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, &rr_ptr, NX_MDNS_RR_OP_PEER_ADD_ANSWER);
9958
9959 /* Check status. */
9960 if(status)
9961 {
9962
9963 /* Delete the name strings. */
9964 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, rr_ptr.nx_mdns_rr_name, 0);
9965 return (NX_MDNS_ERROR);
9966 }
9967
9968 /* Check if need to ignore this source reocrd. */
9969 if ((mdns_ptr -> nx_mdns_service_ignore_mask) &&
9970 ((rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
9971 (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
9972 (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)))
9973 {
9974
9975 /* Get the service. */
9976 if (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
9977 {
9978
9979 /* Check string length. */
9980 if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9981 {
9982 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
9983 return(NX_MDNS_DATA_SIZE_ERROR);
9984 }
9985 memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9986 }
9987 else
9988 {
9989
9990 /* Check string length. */
9991 if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9992 {
9993 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
9994 return(NX_MDNS_DATA_SIZE_ERROR);
9995 }
9996 memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9997 }
9998
9999 /* Resolve the service type. */
10000 if (_nx_mdns_service_name_resolve(temp_string_buffer, &service_name, &service_type, &service_domain))
10001 {
10002 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10003 return (status);
10004 }
10005
10006 /* Check if this service type should be ignored. */
10007 if (_nx_mdns_service_mask_match(mdns_ptr, service_type, mdns_ptr -> nx_mdns_service_ignore_mask) == NX_MDNS_SUCCESS)
10008 {
10009 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10010 return (NX_MDNS_ERROR);
10011 }
10012 }
10013
10014 /* Add the resource record into remote buffer. */
10015 if (_nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr, &insert_ptr, &is_present))
10016 {
10017
10018 /* Delete the name strings. */
10019 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10020 return (NX_MDNS_ERROR);
10021 }
10022
10023 /* Check the ttl. */
10024 if (insert_ptr -> nx_mdns_rr_ttl)
10025 {
10026
10027 /* Step1. Process answer record. */
10028 /* Update the state. */
10029 insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
10030
10031 /* Update the timer count. The querier should not include records in the Known-Answer list whose remaining TTL is less than half of their original TTL. */
10032 insert_ptr -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
10033
10034 /* Record the remaining ticks of resource record. */
10035 if (insert_ptr -> nx_mdns_rr_ttl >= NX_MDNS_RR_MAX_TTL)
10036 {
10037 /* If the ttl of resource resource record is outside the range, set as 0xFFFFFFFF. */
10038 insert_ptr -> nx_mdns_rr_remaining_ticks = 0xFFFFFFFF;
10039 }
10040 else
10041 {
10042 /* Convert units(seconds to ticks). */
10043 insert_ptr -> nx_mdns_rr_remaining_ticks = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE;
10044 }
10045
10046 /* Step2. Process query record. */
10047 /* Set the pointer. */
10048 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
10049 head = (ULONG*)(*head);
10050
10051 /* Check the remote resource record state. */
10052 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10053 {
10054
10055 /* Check the state. */
10056 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
10057 continue;
10058
10059 /* Check the interface index. */
10060 if (p -> nx_mdns_rr_interface_index != insert_ptr -> nx_mdns_rr_interface_index)
10061 continue;
10062
10063 /* Check the name. */
10064 if (p -> nx_mdns_rr_name != insert_ptr -> nx_mdns_rr_name)
10065 continue;
10066
10067 /* Check the type. */
10068 if ((p -> nx_mdns_rr_type != insert_ptr -> nx_mdns_rr_type) &&
10069 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL))
10070 continue;
10071
10072 /* Check the class. */
10073 if (p -> nx_mdns_rr_class != insert_ptr -> nx_mdns_rr_class)
10074 continue;
10075
10076 /* Check the query type. */
10077 if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_CONTINUOUS_QUERY))
10078 {
10079
10080 /* Determine if we need to wake a thread suspended. */
10081 if (mdns_ptr -> nx_mdns_rr_receive_suspension_list)
10082 {
10083
10084 /* Resume suspended thread. */
10085 _nx_mdns_query_thread_resume(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), mdns_ptr, insert_ptr);
10086 }
10087
10088 /* Get the answer, we need not send the question again. Delete the resource record. */
10089 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
10090
10091 }
10092 else
10093 {
10094
10095 /* There is no need for the querier to continue issuing a stream of queries when a mDNS response
10096 is received containing a unique answer. mDNS querier should send the next query at 80%-82% of the
10097 record's TTL. RFC6762, Section5.2,Page11. */
10098 if ((insert_ptr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) && (insert_ptr -> nx_mdns_rr_ttl))
10099 {
10100
10101 /* Set the timer count. */
10102 p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (((ULONG)NX_RAND()) % 3)) / 100;
10103
10104 /* Set the mDNS timer. */
10105 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10106 }
10107
10108 /* Set the updating flag to update the resource record at 80% of the record's TTL. */
10109 insert_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UPDATING;
10110 }
10111 }
10112 }
10113 else
10114 {
10115
10116 /* Update the state to delete this record from peer cache. . */
10117 insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_DELETE;
10118
10119 /* Delete the resource record one second later. */
10120 insert_ptr -> nx_mdns_rr_timer_count = NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT;
10121 }
10122
10123 /* Set the mDNS timer for insert RR. */
10124 _nx_mdns_timer_set(mdns_ptr, insert_ptr, insert_ptr -> nx_mdns_rr_timer_count);
10125
10126 /* Service name registered success, invoke the notify function. */
10127 if (mdns_ptr -> nx_mdns_service_change_notify)
10128 {
10129
10130 /* Process the service notify function. */
10131 _nx_mdns_service_change_notify_process(mdns_ptr, insert_ptr, is_present);
10132 }
10133
10134 /* Return success. */
10135 return (NX_MDNS_SUCCESS);
10136 }
10137 #endif /* NX_MDNS_DISABLE_CLIENT */
10138
10139
10140 /**************************************************************************/
10141 /* */
10142 /* FUNCTION RELEASE */
10143 /* */
10144 /* _nx_mdns_packet_rr_data_set PORTABLE C */
10145 /* 6.1.4 */
10146 /* AUTHOR */
10147 /* */
10148 /* Yuxin Zhou, Microsoft Corporation */
10149 /* */
10150 /* DESCRIPTION */
10151 /* */
10152 /* This function processes the packet, and sets the data of */
10153 /* resource record. */
10154 /* */
10155 /* INPUT */
10156 /* */
10157 /* mdns_ptr Pointer to mDNS instance. */
10158 /* packet_ptr Pointer to the packet. */
10159 /* data_ptr Pointer to the data. */
10160 /* rr_ptr Pointer to the record */
10161 /* op Operation: */
10162 /* set answer in local cache. */
10163 /* or add answer in peer cache.*/
10164 /* cache_ptr The record buffer. */
10165 /* */
10166 /* OUTPUT */
10167 /* */
10168 /* status Completion status */
10169 /* */
10170 /* CALLS */
10171 /* */
10172 /* _nx_mdns_name_string_decode Decode the name string */
10173 /* _nx_mdns_cache_add_string Add the name string */
10174 /* _nx_mdns_cache_add_resource_record Add the resource record */
10175 /* */
10176 /* CALLED BY */
10177 /* */
10178 /* _nx_mdns_packet_process Process mDNS packet */
10179 /* */
10180 /* RELEASE HISTORY */
10181 /* */
10182 /* DATE NAME DESCRIPTION */
10183 /* */
10184 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10185 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10186 /* resulting in version 6.1 */
10187 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
10188 /* buffer length verification, */
10189 /* resulting in version 6.1.3 */
10190 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
10191 /* packet length verification, */
10192 /* resulting in version 6.1.4 */
10193 /* */
10194 /**************************************************************************/
_nx_mdns_packet_rr_data_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op)10195 static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op)
10196 {
10197
10198 UCHAR *string_search = NX_NULL;
10199 UINT cache_type;
10200 UCHAR find_string;
10201 UCHAR continue_process = NX_FALSE;
10202 UINT status = NX_MDNS_UNSUPPORTED_TYPE;
10203 UINT temp_string_length;
10204
10205
10206 /* Get cache type and size. */
10207 if (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER)
10208 {
10209 cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
10210 find_string = NX_TRUE;
10211 }
10212 else
10213 {
10214 cache_type = NX_MDNS_CACHE_TYPE_PEER;
10215 find_string = NX_FALSE;
10216 }
10217
10218 /* Plus 10 for 2 bytes type, 2 bytes class, 4 bytes ttl and 2 bytes rdata length. */
10219 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
10220 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 10) > packet_ptr -> nx_packet_append_ptr))
10221 {
10222 return(NX_MDNS_ERROR);
10223 }
10224
10225 /* Set the resource record time to live.*/
10226 rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + temp_string_length + 4);
10227
10228 /* Set the resource record rdata length. */
10229 rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 8);;
10230
10231 /* Update the pointer to point at the resource data. */
10232 data_ptr = data_ptr + temp_string_length + 10;
10233
10234 /* Check the type. */
10235 switch (rr_ptr -> nx_mdns_rr_type)
10236 {
10237 case NX_MDNS_RR_TYPE_A:
10238 {
10239
10240 /* 4 bytes IP address. */
10241 if (data_ptr + 4 > packet_ptr -> nx_packet_append_ptr)
10242 {
10243 return(NX_MDNS_ERROR);
10244 }
10245
10246 /* Get the rdata. */
10247 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = NX_MDNS_GET_ULONG_DATA(data_ptr);
10248 rr_ptr -> nx_mdns_rr_rdata_length = 4;
10249
10250 /* Update the status. */
10251 status = NX_MDNS_SUCCESS;
10252 break;
10253 }
10254 case NX_MDNS_RR_TYPE_AAAA:
10255 {
10256
10257 /* 16 bytes IPv6 address. */
10258 if (data_ptr + 16 > packet_ptr -> nx_packet_append_ptr)
10259 {
10260 return(NX_MDNS_ERROR);
10261 }
10262
10263 /* Get the rdata. */
10264 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = NX_MDNS_GET_ULONG_DATA(data_ptr);
10265 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = NX_MDNS_GET_ULONG_DATA(data_ptr + 4);
10266 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = NX_MDNS_GET_ULONG_DATA(data_ptr + 8);
10267 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = NX_MDNS_GET_ULONG_DATA(data_ptr + 12);
10268 rr_ptr -> nx_mdns_rr_rdata_length = 16;
10269
10270 /* Update the status. */
10271 status = NX_MDNS_SUCCESS;
10272 break;
10273 }
10274 case NX_MDNS_RR_TYPE_TXT:
10275 {
10276
10277 /* Process the txt string. An empty TXT record contaning zero strings is not allowed. RFC6763, Page12. */
10278 if (rr_ptr -> nx_mdns_rr_rdata_length == 1)
10279 {
10280
10281 /* Update the status. */
10282 status = NX_MDNS_SUCCESS;
10283 }
10284 else if (rr_ptr -> nx_mdns_rr_rdata_length > 1)
10285 {
10286
10287 if (data_ptr + rr_ptr -> nx_mdns_rr_rdata_length > packet_ptr -> nx_packet_append_ptr)
10288 {
10289 return(NX_MDNS_ERROR);
10290 }
10291
10292 /* Add the txt string. */
10293 if (_nx_mdns_txt_string_decode(data_ptr, rr_ptr -> nx_mdns_rr_rdata_length, temp_string_buffer, NX_MDNS_NAME_MAX) == NX_MDNS_SUCCESS)
10294 {
10295
10296 /* Check string length. */
10297 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10298 {
10299 return(NX_MDNS_DATA_SIZE_ERROR);
10300 }
10301
10302 /* Find the same string . */
10303 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10304 (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10305 {
10306
10307 /* Update the name pointer. */
10308 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = string_search;
10309
10310 /* Calculate the text string.inlcude the one byte label. */
10311 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(temp_string_length + 1);
10312
10313 /* Update the status. */
10314 status = NX_MDNS_SUCCESS;
10315 }
10316 }
10317 }
10318
10319 break;
10320 }
10321 case NX_MDNS_RR_TYPE_SRV:
10322 {
10323
10324 /* Plus 6 bytes for 2 bytes priority, 2 bytes weights and 2 bytes port. */
10325 if (data_ptr + 6 > packet_ptr -> nx_packet_append_ptr)
10326 {
10327 return(NX_MDNS_ERROR);
10328 }
10329
10330 /* Get the priority. */
10331 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = NX_MDNS_GET_USHORT_DATA(data_ptr);
10332 data_ptr += 2;
10333
10334 /* Get the weights. */
10335 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = NX_MDNS_GET_USHORT_DATA(data_ptr);
10336 data_ptr += 2;
10337
10338 /* Get the port. */
10339 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = NX_MDNS_GET_USHORT_DATA(data_ptr);
10340 data_ptr += 2;
10341
10342 /* Update the rdata length. */
10343 rr_ptr -> nx_mdns_rr_rdata_length = 6;
10344
10345 /* Continue to process target name. */
10346 continue_process = NX_TRUE;
10347 break;
10348 }
10349 case NX_MDNS_RR_TYPE_PTR:
10350 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10351 case NX_MDNS_RR_TYPE_CNAME:
10352 case NX_MDNS_RR_TYPE_NS:
10353 #endif
10354 {
10355
10356 /* Update the rdata length. */
10357 rr_ptr -> nx_mdns_rr_rdata_length = 0;
10358
10359 /* Continue to process the domain name. */
10360 continue_process = NX_TRUE;
10361 break;
10362 }
10363 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10364 case NX_MDNS_RR_TYPE_MX:
10365 {
10366
10367 /* Plus 2 bytes for preference. */
10368 if (data_ptr + 2 > packet_ptr -> nx_packet_append_ptr)
10369 {
10370 return(NX_MDNS_ERROR);
10371 }
10372
10373 /* Set the preference. */
10374 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference = NX_MDNS_GET_USHORT_DATA(data_ptr);
10375 data_ptr += 2;
10376
10377 /* Update the rdata length. */
10378 rr_ptr -> nx_mdns_rr_rdata_length = 2;
10379
10380 /* Continue to process the domain name. */
10381 continue_process = NX_TRUE;
10382 break;
10383 }
10384 #endif
10385 }
10386
10387 /* Check if need to continue process rdata. */
10388 if(continue_process == NX_TRUE)
10389 {
10390
10391 /* Process the target/domain name string. */
10392 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
10393 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
10394 packet_ptr -> nx_packet_length,
10395 temp_string_buffer, NX_MDNS_NAME_MAX))
10396 {
10397
10398 /* Check string length. */
10399 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10400 {
10401 return(NX_MDNS_DATA_SIZE_ERROR);
10402 }
10403
10404 /* Add the string. */
10405 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10406 (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10407 {
10408
10409 /* Update the name pointer for SRV, PTR, etc. */
10410 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target = string_search;
10411
10412 /* Calculate the text string. Inlcude the one byte label '.' and null '\0'. */
10413 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(rr_ptr -> nx_mdns_rr_rdata_length + (temp_string_length + 2));
10414
10415 /* Update the status. */
10416 status = NX_MDNS_SUCCESS;
10417 }
10418 }
10419 }
10420
10421 /* Return success. */
10422 return (status);
10423 }
10424
10425
10426 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
10427 /**************************************************************************/
10428 /* */
10429 /* FUNCTION RELEASE */
10430 /* */
10431 /* _nx_mdns_packet_address_check PORTABLE C */
10432 /* 6.1.4 */
10433 /* AUTHOR */
10434 /* */
10435 /* Yuxin Zhou, Microsoft Corporation */
10436 /* */
10437 /* DESCRIPTION */
10438 /* */
10439 /* This function checks the IP address and port of received packet. */
10440 /* */
10441 /* INPUT */
10442 /* */
10443 /* packet_ptr Pointer to mDNS packet */
10444 /* */
10445 /* OUTPUT */
10446 /* */
10447 /* status Completion status */
10448 /* */
10449 /* CALLS */
10450 /* */
10451 /* none */
10452 /* */
10453 /* CALLED BY */
10454 /* */
10455 /* _nx_mdns_packet_process Process mDNS packet */
10456 /* */
10457 /* RELEASE HISTORY */
10458 /* */
10459 /* DATE NAME DESCRIPTION */
10460 /* */
10461 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10462 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10463 /* resulting in version 6.1 */
10464 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
10465 /* packet length verification, */
10466 /* resulting in version 6.1.4 */
10467 /* */
10468 /**************************************************************************/
_nx_mdns_packet_address_check(NX_PACKET * packet_ptr)10469 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr)
10470 {
10471
10472 USHORT mdns_flags;
10473 UINT src_port;
10474 ULONG *udp_header;
10475
10476 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
10477 NXD_ADDRESS src_address;
10478 NXD_ADDRESS des_address;
10479 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
10480
10481 #ifndef NX_DISABLE_IPV4
10482 NX_IPV4_HEADER *ipv4_header;
10483 #endif /* NX_DISABLE_IPV4 */
10484
10485 #ifdef NX_MDNS_ENABLE_IPV6
10486 NX_IPV6_HEADER *ipv6_header;
10487 #endif /* NX_MDNS_ENABLE_IPV6 */
10488
10489
10490 /* 2 bytes ID and 2 bytes flags. */
10491 if (packet_ptr -> nx_packet_length < 4)
10492 {
10493 return(NX_MDNS_ERROR);
10494 }
10495
10496 /* Extract the message type which should be the first byte. */
10497 mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
10498
10499 #ifndef NX_DISABLE_IPV4
10500 /* Get the ip address. */
10501 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10502 {
10503
10504 /* Set the IPv4 header. */
10505 ipv4_header = (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
10506
10507 /* Set the source address. */
10508 src_address.nxd_ip_version = NX_IP_VERSION_V4;
10509 src_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_source_ip;
10510
10511 /* Set the destination address. */
10512 des_address.nxd_ip_version = NX_IP_VERSION_V4;
10513 des_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_destination_ip;
10514 }
10515 else
10516 #endif /* NX_DISABLE_IPV4 */
10517
10518 #ifdef NX_MDNS_ENABLE_IPV6
10519 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10520 {
10521
10522 /* Set the IPv6 header. */
10523 ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
10524
10525 /* Set the source address. */
10526 src_address.nxd_ip_version = NX_IP_VERSION_V6;
10527 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_address.nxd_ip_address.v6);
10528
10529 /* Set the destination address. */
10530 des_address.nxd_ip_version = NX_IP_VERSION_V6;
10531 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, des_address.nxd_ip_address.v6);
10532 }
10533 else
10534 #endif /* NX_MDNS_ENABLE_IPV6 */
10535 {
10536
10537 /* Invalid IP version . */
10538 return(NX_MDNS_ERROR);
10539 }
10540
10541 /* Pickup the pointer to the head of the UDP packet. */
10542 udp_header = (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 8);
10543
10544 /* Get the source port and destination port. */
10545 src_port = (UINT) ((*udp_header) >> NX_SHIFT_BY_16);
10546
10547 /* Check the source UDP port. RFC6762, Section6, Page15. */
10548 if (src_port != NX_MDNS_UDP_PORT)
10549 {
10550 return(NX_MDNS_UDP_PORT_ERROR);
10551 }
10552
10553 /* Check the QR bit. */
10554 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
10555 {
10556
10557 /* Check the response code. */
10558 if (mdns_flags & NX_MDNS_ERROR_MASK)
10559 {
10560
10561 /* Release the source packet. */
10562 return(NX_MDNS_AUTH_ERROR);
10563 }
10564
10565 /* In response messages for Multicast domains, the AA bit Must be set to one, RFC6762, Page48. */
10566 if ((mdns_flags & NX_MDNS_AA_FLAG) != NX_MDNS_AA_FLAG)
10567 {
10568 return (NX_MDNS_ERROR);
10569 }
10570
10571 #ifndef NX_DISABLE_IPV4
10572 /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10573 if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10574 {
10575
10576 /* Local link check, Multicast Address or (I & M) == (P & M). */
10577 if ((des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS) &&
10578 (packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address & packet_ptr ->nx_packet_ip_interface -> nx_interface_ip_network_mask) !=
10579 (src_address.nxd_ip_address.v4 & packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_network_mask))
10580 {
10581 return (NX_MDNS_NOT_LOCAL_LINK);
10582 }
10583 }
10584 else
10585 #endif /* NX_DISABLE_IPV4 */
10586
10587 #ifdef NX_MDNS_ENABLE_IPV6
10588 if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10589 {
10590
10591 /* Destination address is not FF02::FB address or source address not on link, RFC6762, Section 11, Page39. */
10592 /* Not check the source address. */
10593 if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10594 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10595 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10596 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10597 {
10598 return (NX_MDNS_DEST_ADDRESS_ERROR);
10599 }
10600 }
10601 else
10602 #endif /* NX_MDNS_ENABLE_IPV6 */
10603 {
10604
10605 /* Invalid IP version. */
10606 return(NX_MDNS_ERROR);
10607 }
10608 }
10609 else
10610 {
10611
10612 #ifndef NX_DISABLE_IPV4
10613 /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10614 if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10615 {
10616 if (des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS)
10617 {
10618 return (NX_MDNS_DEST_ADDRESS_ERROR);
10619 }
10620 }
10621 else
10622 #endif /* NX_DISABLE_IPV4 */
10623
10624 #ifdef NX_MDNS_ENABLE_IPV6
10625 if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10626 {
10627 if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10628 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10629 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10630 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10631 {
10632 return (NX_MDNS_DEST_ADDRESS_ERROR);
10633 }
10634 }
10635 else
10636 #endif /* NX_MDNS_ENABLE_IPV6 */
10637 {
10638
10639 /* Invalid IP version . */
10640 return(NX_MDNS_ERROR);
10641 }
10642 }
10643
10644 return(NX_MDNS_SUCCESS);
10645 }
10646 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
10647
10648
10649 #ifndef NX_MDNS_DISABLE_SERVER
10650 /**************************************************************************/
10651 /* */
10652 /* FUNCTION RELEASE */
10653 /* */
10654 /* _nx_mdns_address_change_process PORTABLE C */
10655 /* 6.1 */
10656 /* AUTHOR */
10657 /* */
10658 /* Yuxin Zhou, Microsoft Corporation */
10659 /* */
10660 /* DESCRIPTION */
10661 /* */
10662 /* This function process the address change event. */
10663 /* */
10664 /* INPUT */
10665 /* */
10666 /* mdns_ptr Pointer to mDNS instance */
10667 /* */
10668 /* OUTPUT */
10669 /* */
10670 /* status Completion status */
10671 /* */
10672 /* CALLS */
10673 /* */
10674 /* nx_packet_copy Copy the mDNS packet */
10675 /* nx_packet_release Release the mDNS packet */
10676 /* nx_udp_socket_send Send the udp packet */
10677 /* nxd_udp_socket_send Send the udp packet */
10678 /* */
10679 /* CALLED BY */
10680 /* */
10681 /* _nx_mdns_thread_entry Processing thread for mDNS */
10682 /* */
10683 /* RELEASE HISTORY */
10684 /* */
10685 /* DATE NAME DESCRIPTION */
10686 /* */
10687 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10688 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10689 /* resulting in version 6.1 */
10690 /* */
10691 /**************************************************************************/
_nx_mdns_address_change_process(NX_MDNS * mdns_ptr)10692 static VOID _nx_mdns_address_change_process(NX_MDNS *mdns_ptr)
10693 {
10694
10695 ULONG *head;
10696 NX_MDNS_RR *p;
10697 UINT i;
10698
10699
10700 /* Register the host name. */
10701 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
10702 {
10703
10704 /* Check if the interface is enabled. */
10705 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
10706 continue;
10707
10708 /* Get the local buffer head. */
10709 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10710
10711 if (head)
10712 {
10713
10714 /* Set the pointer. */
10715 head = (ULONG*)(*head);
10716
10717 /* Check the resource record. */
10718 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10719 {
10720
10721 /* Check whether the resource record is valid. */
10722 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
10723 continue;
10724
10725 /* Check the interface index. */
10726 if (p -> nx_mdns_rr_interface_index != i)
10727 continue;
10728
10729 /* If any of a host's IP addresses change, it MUST re-announce those address records. RFC6762, Section8.4, Page31. */
10730 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10731 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10732 {
10733
10734 /* Send the "goodbye " announcement with RR TTL zero. RFC6762, Section8.4, Page31. */
10735 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
10736
10737 /* Clear the retransmit count. */
10738 p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
10739
10740 /* Set the timer count. 250ms. */
10741 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
10742
10743 /* Set the delete flag. */
10744 p -> nx_mdns_rr_word = (p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
10745
10746 /* Set the mDNS timer. */
10747 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10748 }
10749
10750 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
10751 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
10752 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
10753 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
10754 }
10755 }
10756
10757 /* Second register the host name, the host does not need to repeat the Probing step, Only Announcing the A/AAAA. */
10758 _nx_mdns_host_name_register(mdns_ptr, NX_FALSE, i);
10759 }
10760 }
10761
10762
10763 /**************************************************************************/
10764 /* */
10765 /* FUNCTION RELEASE */
10766 /* */
10767 /* _nx_mdns_conflict_process PORTABLE C */
10768 /* 6.1 */
10769 /* AUTHOR */
10770 /* */
10771 /* Yuxin Zhou, Microsoft Corporation */
10772 /* */
10773 /* DESCRIPTION */
10774 /* */
10775 /* This function process the mDNS conflict. RFC6762, Section9, Page31 */
10776 /* */
10777 /* INPUT */
10778 /* */
10779 /* mdns_ptr Pointer to mDNS instance */
10780 /* record_rr The resource record */
10781 /* */
10782 /* OUTPUT */
10783 /* */
10784 /* status Completion status */
10785 /* */
10786 /* CALLS */
10787 /* */
10788 /* _nx_mdns_cache_add_string Add the string */
10789 /* _nx_mdns_cache_delete_string Delete the string */
10790 /* _nx_mdns_srv_name_resolve Reslove the service name */
10791 /* nx_mdns_rr_change_notify Resource record notify */
10792 /* */
10793 /* CALLED BY */
10794 /* */
10795 /* _nx_mdns_packet_process Process mDNS packet */
10796 /* */
10797 /* RELEASE HISTORY */
10798 /* */
10799 /* DATE NAME DESCRIPTION */
10800 /* */
10801 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10802 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
10803 /* buffer length verification, */
10804 /* verified memcpy use cases, */
10805 /* resulting in version 6.1 */
10806 /* */
10807 /**************************************************************************/
_nx_mdns_conflict_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)10808 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
10809 {
10810
10811 UINT status;
10812 UCHAR *old_name;
10813 UCHAR *name;
10814 UCHAR *type = NX_NULL;
10815 UCHAR *domain = NX_NULL;
10816 UINT i;
10817 ULONG *head;
10818 NX_MDNS_RR *p;
10819 UCHAR is_host_type;
10820 UINT temp_string_length;
10821 UINT rr_name_length;
10822
10823
10824 /* Initialize the value. */
10825 i = 0;
10826 memset(&temp_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10827 memset(&target_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10828
10829 /* Get rr type. */
10830 if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10831 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT))
10832 {
10833 is_host_type = NX_FALSE;
10834
10835 /* Check string length. */
10836 if (_nx_utility_string_length_check((CHAR *)(record_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
10837 {
10838 return(NX_MDNS_DATA_SIZE_ERROR);
10839 }
10840
10841 /* Store the service name. */
10842 memcpy((CHAR *)&target_string_buffer[0], (const char*)(record_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
10843
10844 /* Get Name, Type, Domain. */
10845 _nx_mdns_service_name_resolve(&target_string_buffer[0], &name, &type, &domain);
10846 }
10847 else if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10848 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10849 {
10850 is_host_type = NX_TRUE;
10851 name = mdns_ptr -> nx_mdns_host_name;
10852 }
10853 else
10854 {
10855
10856 /* This is an unsupported or unknown type. */
10857 return(NX_MDNS_UNSUPPORTED_TYPE);
10858 }
10859
10860 /* Check the conflict count. */
10861 if (record_rr -> nx_mdns_rr_conflict_count >= NX_MDNS_CONFLICT_COUNT)
10862 {
10863
10864 /* Yes, Receive the confilictiong mDNS, Probing failure. */
10865 if ((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10866 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A))
10867 {
10868
10869 /* Service name has been registered , invoke the notify function. */
10870 if (mdns_ptr -> nx_mdns_probing_notify)
10871 {
10872 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, name, NX_MDNS_LOCAL_SERVICE_REGISTERED_FAILURE);
10873 }
10874 }
10875
10876 /* Return. */
10877 return (NX_MDNS_ERROR);
10878 }
10879
10880 /* Record the old name. */
10881 old_name = record_rr -> nx_mdns_rr_name;
10882
10883 /* Set the new name and probing it. */
10884 while ((*name) != '\0')
10885 {
10886 temp_string_buffer[i++] = *name++;
10887 }
10888
10889 /* The first conflict, only add the " (2)". */
10890 if (record_rr -> nx_mdns_rr_conflict_count == 0)
10891 {
10892 temp_string_buffer[i++] = ' ';
10893 temp_string_buffer[i++] = '(';
10894 temp_string_buffer[i++] = '2';
10895 temp_string_buffer[i++] = ')';
10896 }
10897
10898 /* Modify the count, eg: " (2)" change to " (3)". */
10899 else
10900 {
10901 temp_string_buffer[i-2] = (UCHAR)(temp_string_buffer[i-2] + 1);
10902 }
10903
10904
10905 if(is_host_type == NX_TRUE)
10906 {
10907
10908 /* Check string length. */
10909 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_HOST_NAME_MAX))
10910 {
10911 return(NX_MDNS_DATA_SIZE_ERROR);
10912 }
10913
10914 /* Construct the target host. */
10915 memcpy((CHAR *)(mdns_ptr -> nx_mdns_host_name), (CHAR *)(temp_string_buffer), temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h. */
10916
10917 temp_string_buffer[i++] = '.';
10918
10919 /* Check string length. */
10920 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &temp_string_length, NX_MDNS_DOMAIN_NAME_MAX))
10921 {
10922 return(NX_MDNS_DATA_SIZE_ERROR);
10923 }
10924
10925 /* Add the domain. */
10926 memcpy((CHAR *)(&temp_string_buffer[i]), (CHAR *)mdns_ptr -> nx_mdns_domain_name, temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_DOMAIN_NAME_MAX is limited in nxd_mdns.h. */
10927 }
10928 else
10929 {
10930 temp_string_buffer[i++] = '.';
10931
10932 /* Set the Type. */
10933 while ((*type) != '\0')
10934 {
10935 temp_string_buffer[i++] = *type++;
10936 }
10937
10938 temp_string_buffer[i++] = '.';
10939
10940 /* Set the Domain. */
10941 while ((*domain) != '\0')
10942 {
10943 temp_string_buffer[i++] = *domain++;
10944 }
10945 }
10946
10947 /* Check string length. */
10948 if (_nx_utility_string_length_check((CHAR *)&temp_string_buffer[0], &temp_string_length, NX_MDNS_NAME_MAX))
10949 {
10950 return(NX_MDNS_DATA_SIZE_ERROR);
10951 }
10952
10953 /* Add the new resource records. */
10954 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL,
10955 &temp_string_buffer[0], temp_string_length,
10956 (VOID **)(&record_rr -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
10957
10958 if (status )
10959 {
10960
10961 /* No, return error status. */
10962 return(status);
10963 }
10964
10965 /* Update the state. */
10966 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
10967 record_rr -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
10968 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
10969 record_rr -> nx_mdns_rr_conflict_count ++;
10970
10971 /* Set the mDNS timer. */
10972 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
10973
10974 /* Update the PTR/SRV data name. */
10975 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10976 head = (ULONG*)(*head);
10977
10978 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10979 {
10980 if ((((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) && (is_host_type == NX_FALSE)) ||
10981 ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) && (is_host_type == NX_TRUE))) &&
10982 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == old_name))
10983 {
10984
10985 /* Add the new resource records. */
10986 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_string_buffer[0], temp_string_length,
10987 (VOID **)(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)), NX_FALSE, NX_TRUE);
10988
10989 /* Delete the rdata name. */
10990 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10991 }
10992 }
10993
10994 /* Delete the old name. */
10995 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10996
10997 return(NX_MDNS_SUCCESS);
10998 }
10999 #endif /* NX_MDNS_DISABLE_SERVER */
11000
11001
11002 #ifndef NX_MDNS_DISABLE_CLIENT
11003 /**************************************************************************/
11004 /* */
11005 /* FUNCTION RELEASE */
11006 /* */
11007 /* _nx_mdns_service_change_notify_process PORTABLE C */
11008 /* 6.1 */
11009 /* AUTHOR */
11010 /* */
11011 /* Yuxin Zhou, Microsoft Corporation */
11012 /* */
11013 /* DESCRIPTION */
11014 /* */
11015 /* This function processes the mDNS service change operation, when the */
11016 /* service information change, notify the application. */
11017 /* */
11018 /* INPUT */
11019 /* */
11020 /* mdns_ptr Pointer to mDNS instance */
11021 /* record_rr The resource record */
11022 /* is_present The service type */
11023 /* */
11024 /* OUTPUT */
11025 /* */
11026 /* status Completion status */
11027 /* */
11028 /* CALLS */
11029 /* */
11030 /* tx_mutex_get Get the mDNS mutex */
11031 /* tx_mutex_put Put the mDNS mutex */
11032 /* */
11033 /* CALLED BY */
11034 /* */
11035 /* Application Code */
11036 /* */
11037 /* RELEASE HISTORY */
11038 /* */
11039 /* DATE NAME DESCRIPTION */
11040 /* */
11041 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11042 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11043 /* verified memcpy use cases, */
11044 /* resulting in version 6.1 */
11045 /* */
11046 /**************************************************************************/
_nx_mdns_service_change_notify_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * new_rr,UCHAR is_present)11047 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present)
11048 {
11049
11050 UINT notify_status = 0;
11051 ULONG *head;
11052 NX_MDNS_RR *p;
11053 NX_MDNS_SERVICE temp_service;
11054 UINT rr_name_length;
11055
11056
11057 /* Initialize the struct. */
11058 memset(&temp_service, 0, sizeof(NX_MDNS_SERVICE));
11059
11060 /* Compare the RDATA. */
11061 switch (new_rr -> nx_mdns_rr_type)
11062 {
11063 case NX_MDNS_RR_TYPE_A:
11064 case NX_MDNS_RR_TYPE_AAAA:
11065 {
11066
11067 /* Get the remote buffer head. */
11068 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11069 head = (ULONG*)(*head);
11070
11071 /* Check the resource record. */
11072 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
11073 {
11074
11075 /* Check whether the resource record is valid. */
11076 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11077 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11078 continue;
11079
11080 /* Check the interface. */
11081 if (p -> nx_mdns_rr_interface_index != new_rr -> nx_mdns_rr_interface_index)
11082 continue;
11083
11084 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
11085 {
11086 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == new_rr -> nx_mdns_rr_name)
11087 {
11088
11089 /* Check string length. */
11090 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11091 {
11092 break;
11093 }
11094
11095 /* Store the Service name. */
11096 memcpy((CHAR *)(&temp_string_buffer[0]), (CHAR *)(p -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11097
11098 /* Check if the address is updated. */
11099 if (((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0)) ||
11100 (((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))))
11101 {
11102 notify_status = NX_MDNS_PEER_SERVICE_UPDATED;
11103 }
11104 break;
11105 }
11106 }
11107 }
11108
11109 break;
11110 }
11111 case NX_MDNS_RR_TYPE_SRV:
11112 {
11113
11114 /* Check string length. */
11115 if (_nx_utility_string_length_check((CHAR *)(new_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11116 {
11117 break;
11118 }
11119
11120 /* Store the Service name. */
11121 memcpy((CHAR *)&temp_string_buffer[0], (CHAR *)(new_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11122
11123 /* Check if the service is new. */
11124 if ((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0))
11125 {
11126 notify_status = NX_MDNS_PEER_SERVICE_RECEIVED;
11127 }
11128 else if ((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))
11129 {
11130 notify_status = NX_MDNS_PEER_SERVICE_DELETED;
11131 }
11132 break;
11133 }
11134 default:
11135 {
11136
11137 /* This is an unsupported or unknown type. */
11138 return;
11139 }
11140 }
11141
11142 /* Check if need to call then notify function. */
11143 if (notify_status == 0)
11144 return;
11145
11146 /* Store the service name. */
11147 memcpy((CHAR *)(&temp_service.buffer[0]), (CHAR *)(&temp_string_buffer[0]), rr_name_length); /* Use case of memcpy is verified. */
11148
11149 /* Reslove the service name. */
11150 if (_nx_mdns_service_name_resolve(&temp_service.buffer[0], &(temp_service.service_name), &(temp_service.service_type), &(temp_service.service_domain)))
11151 return;
11152
11153 /* Compare the service change type. */
11154 if (_nx_mdns_service_mask_match(mdns_ptr, temp_service.service_type, mdns_ptr -> nx_mdns_service_notify_mask))
11155 return;
11156
11157 /* Get the additional information. */
11158 _nx_mdns_service_addition_info_get(mdns_ptr, &temp_string_buffer[0], &temp_service, new_rr -> nx_mdns_rr_interface_index);
11159
11160 /* Call the notify function. */
11161 (mdns_ptr -> nx_mdns_service_change_notify)(mdns_ptr, &temp_service, notify_status);
11162 }
11163
11164
11165 /**************************************************************************/
11166 /* */
11167 /* FUNCTION RELEASE */
11168 /* */
11169 /* _nx_mdns_service_addition_info_get PORTABLE C */
11170 /* 6.1 */
11171 /* AUTHOR */
11172 /* */
11173 /* Yuxin Zhou, Microsoft Corporation */
11174 /* */
11175 /* DESCRIPTION */
11176 /* */
11177 /* This function adds the mDNS resource record into remote buffer, */
11178 /* mDNS thread send the query message using continuous type. */
11179 /* */
11180 /* INPUT */
11181 /* */
11182 /* mdns_ptr Pointer to mDNS instance */
11183 /* name The service instance */
11184 /* type The service type */
11185 /* domain The domain name */
11186 /* */
11187 /* OUTPUT */
11188 /* */
11189 /* status Completion status */
11190 /* */
11191 /* CALLS */
11192 /* */
11193 /* tx_mutex_get Get the mDNS mutex */
11194 /* tx_mutex_put Put the mDNS mutex */
11195 /* _nx_mdns_query_check Check the query RR */
11196 /* _nx_mdns_cache_add_string Add the string into buffer */
11197 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11198 /* _nx_mdns_cache_add_resource_record Add the resource record */
11199 /* into buffer */
11200 /* */
11201 /* CALLED BY */
11202 /* */
11203 /* Application Code */
11204 /* */
11205 /* RELEASE HISTORY */
11206 /* */
11207 /* DATE NAME DESCRIPTION */
11208 /* */
11209 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11210 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11211 /* verified memcpy use cases, */
11212 /* resulting in version 6.1 */
11213 /* */
11214 /**************************************************************************/
_nx_mdns_service_addition_info_get(NX_MDNS * mdns_ptr,UCHAR * srv_name,NX_MDNS_SERVICE * service,UINT interface_index)11215 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index)
11216 {
11217
11218 UINT index = 0;
11219 ULONG current_time;
11220 ULONG *head, *tail;
11221 UCHAR i;
11222 NX_MDNS_RR *p;
11223 NX_MDNS_RR *p1;
11224 UINT srv_name_length;
11225 UINT temp_length;
11226
11227
11228 /* Check string length. */
11229 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
11230 {
11231 return(NX_MDNS_ERROR);
11232 }
11233
11234 /* Get the current time. */
11235 current_time = tx_time_get();
11236
11237 for(i = 0; i < 2; i++)
11238 {
11239
11240 /* Set the pointer. */
11241 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
11242 {
11243 #ifndef NX_MDNS_DISABLE_SERVER
11244 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
11245 #else
11246 continue;
11247 #endif /* NX_MDNS_DISABLE_SERVER */
11248 }
11249 else
11250 {
11251 #ifndef NX_MDNS_DISABLE_CLIENT
11252 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11253 #else
11254 continue;
11255 #endif /* NX_MDNS_DISABLE_CLIENT */
11256 }
11257
11258 if(head == NX_NULL)
11259 continue;
11260
11261 /* Set the pointer. */
11262 tail = (ULONG*)(*head);
11263
11264 /* Check the resource record. */
11265 for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
11266 {
11267
11268 /* Check whether the resource record is valid. */
11269 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11270 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11271 continue;
11272
11273 /* Check the interface index. */
11274 if (p -> nx_mdns_rr_interface_index != interface_index)
11275 continue;
11276
11277 /* Check the type and name. */
11278 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
11279 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11280 {
11281
11282 /* Update the elasped timer. */
11283 p -> nx_mdns_rr_elapsed_time = current_time;
11284
11285 /* Set the service priority, weight, port and target. */
11286 service -> service_priority = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority;
11287 service -> service_weight = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights;
11288 service -> service_port = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port;
11289
11290 /* Check string length. */
11291 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target), &temp_length, NX_MDNS_HOST_NAME_MAX))
11292 {
11293 return(NX_MDNS_ERROR);
11294 }
11295
11296 /* Store the target host. */
11297 memcpy((CHAR *)(service -> service_host), /* Use case of memcpy is verified. */
11298 (CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
11299 temp_length + 1);
11300
11301 /* All address records (type "A" and "AAAA") named in the SRV rdata */
11302 for (p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
11303 {
11304
11305 /* Update the elasped timer. */
11306 p1 -> nx_mdns_rr_elapsed_time = current_time;
11307
11308 /* Check the interface index. */
11309 if (p1 -> nx_mdns_rr_interface_index != interface_index)
11310 continue;
11311
11312 /* Find the "A" records. */
11313 if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) &&
11314 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11315 {
11316
11317 /* Set the IPv4 address. */
11318 service -> service_ipv4 = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
11319 }
11320
11321 /* Find the "AAAA" records. */
11322 if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA) &&
11323 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11324 {
11325 if (index < NX_MDNS_IPV6_ADDRESS_COUNT)
11326 {
11327
11328 /* Set the IPv6 address. */
11329 service -> service_ipv6[index][0] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0];
11330 service -> service_ipv6[index][1] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1];
11331 service -> service_ipv6[index][2] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2];
11332 service -> service_ipv6[index][3] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3];
11333 index ++;
11334 }
11335 }
11336 }
11337 }
11338
11339 /* Check the type and name. */
11340 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) &&
11341 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11342 {
11343
11344 /* Update the elasped timer. */
11345 p -> nx_mdns_rr_elapsed_time = current_time;
11346
11347 /* Set the text valid flag. */
11348 service -> service_text_valid = 1;
11349
11350 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
11351 {
11352
11353 /* Check string length. */
11354 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), &temp_length, NX_MDNS_NAME_MAX))
11355 {
11356 continue;
11357 }
11358
11359 /* Store the txt. */
11360 memcpy((CHAR *)(service -> service_text), (const char*)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), temp_length + 1); /* Use case of memcpy is verified. */
11361 }
11362 }
11363 }
11364 }
11365
11366 /* Set the interface index. */
11367 service -> interface_index = (UCHAR)interface_index;
11368
11369 /* Return a error status. */
11370 return(NX_MDNS_SUCCESS);
11371 }
11372 #endif /* NX_MDNS_DISABLE_CLIENT */
11373
11374
11375 /**************************************************************************/
11376 /* */
11377 /* FUNCTION RELEASE */
11378 /* */
11379 /* _nx_mdns_cache_initialize PORTABLE C */
11380 /* 6.1 */
11381 /* AUTHOR */
11382 /* */
11383 /* Yuxin Zhou, Microsoft Corporation */
11384 /* */
11385 /* DESCRIPTION */
11386 /* */
11387 /* This function initializes the mDNS remote buffer and local buffer. */
11388 /* */
11389 /* INPUT */
11390 /* */
11391 /* mdns_ptr Pointer to mDNS instance */
11392 /* local_cache_ptr Pointer to local cache */
11393 /* local_cache_size The size of local cache */
11394 /* peer_cache_ptr Pointer to peer cache */
11395 /* peer_cache_size The size of peer cache */
11396 /* */
11397 /* OUTPUT */
11398 /* */
11399 /* status Completion status */
11400 /* */
11401 /* CALLS */
11402 /* */
11403 /* tx_mutex_get Get the mDNS mutex */
11404 /* tx_mutex_put Put the mDNS mutex */
11405 /* */
11406 /* CALLED BY */
11407 /* */
11408 /* _nx_mdns_create Initialize the mDNS structure */
11409 /* _nx_mdns_disable Disable the mDNS function */
11410 /* _nx_mdns_peer_cache_clear Clear the peer cache */
11411 /* */
11412 /* RELEASE HISTORY */
11413 /* */
11414 /* DATE NAME DESCRIPTION */
11415 /* */
11416 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11417 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11418 /* resulting in version 6.1 */
11419 /* */
11420 /**************************************************************************/
_nx_mdns_cache_initialize(NX_MDNS * mdns_ptr,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size)11421 UINT _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size,
11422 VOID *peer_cache_ptr, UINT peer_cache_size)
11423 {
11424
11425 ULONG *head;
11426 ULONG *tail;
11427
11428
11429 #ifndef NX_MDNS_DISABLE_SERVER
11430 /* Check the cache. */
11431 if (local_cache_ptr)
11432 {
11433
11434 /* Zero out the cache. */
11435 memset(local_cache_ptr, 0, local_cache_size);
11436
11437 /* Set the head. */
11438 head = (ULONG*)local_cache_ptr;
11439 *head = (ULONG)((ULONG*)local_cache_ptr + 1);
11440
11441 /* Set the tail. */
11442 tail = (ULONG*)local_cache_ptr + (local_cache_size >> 2) - 1;
11443 *tail = (ULONG)tail;
11444
11445 /* Record the info. */
11446 mdns_ptr -> nx_mdns_local_service_cache = (UCHAR*)local_cache_ptr;
11447 mdns_ptr -> nx_mdns_local_service_cache_size = local_cache_size;
11448
11449 /* Clear the count. */
11450 mdns_ptr -> nx_mdns_local_rr_count = 0;
11451 mdns_ptr -> nx_mdns_local_string_count = 0;
11452 mdns_ptr -> nx_mdns_local_string_bytes = 0;
11453 }
11454 #else
11455 NX_PARAMETER_NOT_USED(local_cache_ptr);
11456 NX_PARAMETER_NOT_USED(local_cache_size);
11457 #endif /* NX_MDNS_DISABLE_SERVER */
11458
11459 #ifndef NX_MDNS_DISABLE_CLIENT
11460 /* Check the cache. */
11461 if (peer_cache_ptr)
11462 {
11463
11464 /* Zero out the cache. */
11465 memset(peer_cache_ptr, 0, peer_cache_size);
11466
11467 /* Set the head. */
11468 head = (ULONG*)peer_cache_ptr;
11469 *head = (ULONG)((ULONG*)peer_cache_ptr + 1);
11470
11471 /* Set the tail. */
11472 tail = (ULONG*)peer_cache_ptr + (peer_cache_size >> 2) - 1;
11473 *tail = (ULONG)tail;
11474
11475 /* Record the info. */
11476 mdns_ptr -> nx_mdns_peer_service_cache = (UCHAR*)peer_cache_ptr;
11477 mdns_ptr -> nx_mdns_peer_service_cache_size = peer_cache_size;
11478
11479 /* Clear the count. */
11480 mdns_ptr -> nx_mdns_peer_rr_count = 0;
11481 mdns_ptr -> nx_mdns_peer_string_count = 0;
11482 mdns_ptr -> nx_mdns_peer_string_bytes = 0;
11483 }
11484 #else
11485 NX_PARAMETER_NOT_USED(peer_cache_ptr);
11486 NX_PARAMETER_NOT_USED(peer_cache_size);
11487 #endif /* NX_MDNS_DISABLE_CLIENT */
11488
11489 return(NX_SUCCESS);
11490 }
11491
11492
11493 /**************************************************************************/
11494 /* */
11495 /* FUNCTION RELEASE */
11496 /* */
11497 /* _nx_mdns_cache_add_resource_record PORTABLE C */
11498 /* 6.1 */
11499 /* AUTHOR */
11500 /* */
11501 /* Yuxin Zhou, Microsoft Corporation */
11502 /* */
11503 /* DESCRIPTION */
11504 /* */
11505 /* This function adds the mDNS resource record into record buffer. */
11506 /* */
11507 /* INPUT */
11508 /* */
11509 /* mdns_ptr Pointer to mDNS instance */
11510 /* cache_type Cache type: local or peer */
11511 /* record_ptr Pointer to resource record */
11512 /* insert_rr Pointer to insert resource */
11513 /* record */
11514 /* */
11515 /* OUTPUT */
11516 /* */
11517 /* status Completion status */
11518 /* */
11519 /* CALLS */
11520 /* */
11521 /* _nx_mdns_cache_find_resource_record Find the resource record */
11522 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11523 /* */
11524 /* CALLED BY */
11525 /* */
11526 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
11527 /* _nx_mdns_rr_ptr_add Add PTR resource record */
11528 /* _nx_mdns_rr_srv_add Add SRV resource record */
11529 /* _nx_mdns_rr_txt_add Add TXT resource record */
11530 /* _nx_mdns_query Send query */
11531 /* _nx_mdns_cache_delete_rr_string Delete the rr string */
11532 /* _nx_mdns_packet_rr_process Process resource record */
11533 /* */
11534 /* RELEASE HISTORY */
11535 /* */
11536 /* DATE NAME DESCRIPTION */
11537 /* */
11538 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11539 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11540 /* verified memcpy use cases, */
11541 /* resulting in version 6.1 */
11542 /* */
11543 /**************************************************************************/
_nx_mdns_cache_add_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,NX_MDNS_RR ** insert_ptr,UCHAR * is_present)11544 UINT _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present)
11545 {
11546
11547 UCHAR *cache_ptr;
11548 UINT cache_size;
11549 ULONG *tail;
11550 ULONG *head;
11551 NX_MDNS_RR *p;
11552 NX_MDNS_RR *rr;
11553 UINT rr_name_length;
11554
11555 #ifndef NX_MDNS_DISABLE_CLIENT
11556 ULONG elapsed_time;
11557 ULONG current_time;
11558 ULONG min_elapsed_time;
11559 #endif /* NX_MDNS_DISABLE_CLIENT */
11560
11561
11562 #ifndef NX_MDNS_DISABLE_CLIENT
11563 /* Initialize the parameters. */
11564 min_elapsed_time = 0;
11565 current_time = tx_time_get();
11566 #endif /* NX_MDNS_DISABLE_CLIENT */
11567
11568 /* Initialize. */
11569 if (is_present)
11570 *is_present = NX_FALSE;
11571
11572 /* Check the RR with same rname, rtype, rclass and rdata. */
11573 if (_nx_mdns_cache_find_resource_record(mdns_ptr, cache_type, record_ptr, NX_MDNS_RR_MATCH_ALL, &rr) == NX_MDNS_SUCCESS)
11574 {
11575
11576 /* Check string length. */
11577 if (_nx_utility_string_length_check((CHAR *)(rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11578 {
11579 return(NX_MDNS_DATA_SIZE_ERROR);
11580 }
11581
11582 /* Copy other informations of record_ptr into insert_rr resource record. */
11583 memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11584
11585 /* Special process for _services._dns-sd._udp.local which pointer to same service type. */
11586 if ((rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
11587 (!_nx_mdns_name_match(rr -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
11588 {
11589 rr -> nx_mdns_rr_count ++;
11590 }
11591
11592 /* Delete the resource record same strings. */
11593 _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, rr);
11594
11595 /* Set the insert ptr. */
11596 if(insert_ptr != NX_NULL)
11597 *insert_ptr = rr;
11598
11599 /* Set the flag. */
11600 if (is_present)
11601 *is_present = NX_TRUE;
11602
11603 return(NX_MDNS_SUCCESS);
11604 }
11605
11606 /* Check the cache type. */
11607 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11608 {
11609 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11610 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
11611 }
11612 else
11613 {
11614 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11615 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
11616 }
11617
11618 /* Check cache pointer and cache size. */
11619 if ((cache_ptr == NX_NULL) || (cache_size == 0))
11620 {
11621 return(NX_MDNS_ERROR);
11622 }
11623
11624 /* Get head and tail. */
11625 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
11626 tail = (ULONG*)(*tail);
11627 head = (ULONG*)cache_ptr;
11628 head = (ULONG*)(*head);
11629
11630 /* Set the pointer. */
11631 rr = NX_NULL;
11632
11633 /* Find an empty entry before head. */
11634 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11635 {
11636 if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11637 {
11638 rr = p;
11639 break;
11640 }
11641 }
11642
11643 if (!rr)
11644 {
11645
11646 /* Check whether the cache is full. */
11647 if((head + (sizeof(NX_MDNS_RR) >> 2)) > tail)
11648 {
11649 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11650 {
11651 return(NX_MDNS_CACHE_ERROR);
11652 }
11653 else
11654 {
11655
11656 #ifndef NX_MDNS_DISABLE_CLIENT
11657 /* Find an aging resource reocrd and repalce it. */
11658 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11659 {
11660
11661 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11662 continue;
11663
11664 /* Calculate the elapsed time. */
11665 elapsed_time = current_time - p -> nx_mdns_rr_elapsed_time;
11666
11667 /* Check the elapsed time to find the aging resource record. */
11668 if (elapsed_time >= min_elapsed_time)
11669 {
11670 rr = p;
11671 min_elapsed_time = elapsed_time;
11672 }
11673 }
11674
11675 if (rr)
11676 {
11677
11678 /* Delete this record. */
11679 _nx_mdns_cache_delete_resource_record(mdns_ptr, cache_type, rr);
11680
11681 /* Update the head. */
11682 head = (ULONG*)cache_ptr;
11683 head = (ULONG*)(*head);
11684 }
11685 else
11686 {
11687 return(NX_MDNS_CACHE_ERROR);
11688 }
11689 #endif /* NX_MDNS_DISABLE_CLIENT */
11690 }
11691 }
11692 else
11693 {
11694 rr = (NX_MDNS_RR*)head;
11695 }
11696 }
11697
11698 /* Just copy it to cache_ptr. */
11699 memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11700
11701 /* Check the type. */
11702 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11703 {
11704
11705 /* Increase the count. */
11706 mdns_ptr -> nx_mdns_local_rr_count ++;
11707 }
11708 else
11709 {
11710
11711 /* Increase the count. */
11712 mdns_ptr -> nx_mdns_peer_rr_count ++;
11713 }
11714
11715 #ifndef NX_MDNS_DISABLE_CLIENT
11716 /* Update the peer resource record elapsed time. */
11717 if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
11718 {
11719
11720 /* Get the current time to set the elapsed time. */
11721 rr -> nx_mdns_rr_elapsed_time = current_time;
11722 }
11723 #endif /* NX_MDNS_DISABLE_CLIENT */
11724
11725 /* Set the insert ptr. */
11726 if(insert_ptr != NX_NULL)
11727 *insert_ptr = rr;
11728
11729 if((ULONG*)rr >= head)
11730 {
11731
11732 /* Update HEAD when new record is added. */
11733 head = (ULONG*)cache_ptr;
11734 *head = (ULONG)(rr + 1);
11735 }
11736
11737 return(NX_MDNS_SUCCESS);
11738 }
11739
11740
11741 /**************************************************************************/
11742 /* */
11743 /* FUNCTION RELEASE */
11744 /* */
11745 /* _nx_mdns_cache_delete_resource_record PORTABLE C */
11746 /* 6.1 */
11747 /* AUTHOR */
11748 /* */
11749 /* Yuxin Zhou, Microsoft Corporation */
11750 /* */
11751 /* DESCRIPTION */
11752 /* */
11753 /* This function deletes the mDNS resource record from record buffer. */
11754 /* */
11755 /* INPUT */
11756 /* */
11757 /* mdns_ptr Pointer to mDNS instance. */
11758 /* cache_type Cache type: local or peer */
11759 /* record_ptr Pointer to resource record. */
11760 /* */
11761 /* OUTPUT */
11762 /* */
11763 /* status Completion status */
11764 /* */
11765 /* CALLS */
11766 /* */
11767 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11768 /* */
11769 /* CALLED BY */
11770 /* */
11771 /* _nx_mdns_rr_delete Delete the resource record */
11772 /* _nx_mdns_query Send the one-shot query */
11773 /* _nx_mdns_timer_event_process Process the timer event */
11774 /* _nx_mdns_packet_process Process mDNS packet */
11775 /* _nx_mdns_cache_delete_rr_string Delete the rr string */
11776 /* */
11777 /* RELEASE HISTORY */
11778 /* */
11779 /* DATE NAME DESCRIPTION */
11780 /* */
11781 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11782 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11783 /* resulting in version 6.1 */
11784 /* */
11785 /**************************************************************************/
_nx_mdns_cache_delete_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr)11786 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr)
11787 {
11788
11789 UCHAR *cache_ptr;
11790 ULONG *head;
11791
11792
11793 /* Delete the resource record strings. */
11794 _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, record_ptr);
11795
11796 /* Zero out the record. */
11797 memset(record_ptr, 0, sizeof(NX_MDNS_RR));
11798
11799 /* Check the type. */
11800 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11801 {
11802
11803 /* Decrease the count. */
11804 mdns_ptr -> nx_mdns_local_rr_count --;
11805
11806 /* Set the cache. */
11807 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11808 }
11809 else
11810 {
11811
11812 /* Decrease the count. */
11813 mdns_ptr -> nx_mdns_peer_rr_count --;
11814
11815 /* Set the cache. */
11816 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11817 }
11818
11819 if (cache_ptr == NX_NULL)
11820 {
11821 return(NX_MDNS_CACHE_ERROR);
11822 }
11823
11824 /* Get head. */
11825 head = (ULONG*)cache_ptr;
11826 head = (ULONG*)(*head);
11827
11828 /* Move HEAD if the last RR is deleted. */
11829 if(record_ptr == ((NX_MDNS_RR*)head - 1))
11830 {
11831 while(record_ptr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11832 {
11833 record_ptr--;
11834 if(record_ptr < (NX_MDNS_RR*)cache_ptr)
11835 break;
11836 }
11837 *((ULONG*)cache_ptr) = (ULONG)(record_ptr + 1);
11838 }
11839
11840 return(NX_MDNS_SUCCESS);
11841 }
11842
11843
11844 /**************************************************************************/
11845 /* */
11846 /* FUNCTION RELEASE */
11847 /* */
11848 /* _nx_mdns_cache_find_resource_record PORTABLE C */
11849 /* 6.1 */
11850 /* AUTHOR */
11851 /* */
11852 /* Yuxin Zhou, Microsoft Corporation */
11853 /* */
11854 /* DESCRIPTION */
11855 /* */
11856 /* This function finds the mDNS resource record in record buffer. */
11857 /* */
11858 /* INPUT */
11859 /* */
11860 /* mdns_ptr Pointer to mDNS instance. */
11861 /* cache_type Cache type: local or peer */
11862 /* record_ptr Resource record. */
11863 /* match_type Match type. */
11864 /* search_rr The search resource record. */
11865 /* */
11866 /* OUTPUT */
11867 /* */
11868 /* status Completion status */
11869 /* */
11870 /* CALLS */
11871 /* */
11872 /* None */
11873 /* */
11874 /* CALLED BY */
11875 /* */
11876 /* _nx_mdns_packet_process Process mDNS packet */
11877 /* _nx_mdns_cache_add_resource_record Add the resource record */
11878 /* */
11879 /* RELEASE HISTORY */
11880 /* */
11881 /* DATE NAME DESCRIPTION */
11882 /* */
11883 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11884 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11885 /* resulting in version 6.1 */
11886 /* */
11887 /**************************************************************************/
_nx_mdns_cache_find_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,UINT match_type,NX_MDNS_RR ** search_rr)11888 UINT _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_rr)
11889 {
11890
11891 UCHAR *cache_ptr;
11892 ULONG *head;
11893 NX_MDNS_RR *p;
11894 UINT same_rdata;
11895
11896
11897 /* Check the cache type. */
11898 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11899 {
11900 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11901 }
11902 else
11903 {
11904 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11905 }
11906
11907 /* Get head. */
11908 head = (ULONG*)cache_ptr;
11909 head = (ULONG*)(*head);
11910
11911 /* Find the same record. */
11912 for(p = (NX_MDNS_RR*)((UCHAR*)cache_ptr + sizeof(ULONG)); (ULONG*)p < head; p++)
11913 {
11914
11915 /* Check the interface index. */
11916 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
11917 continue;
11918
11919 /* Check whether the resource record is valid. */
11920 if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11921 continue;
11922
11923 /* Check whether the same record it is. RFC6762, Section6, Page13. */
11924 /* The rules: rrname must match the question name.
11925 rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
11926 rrclass must match the question qclass unless the qclass is "ANY". */
11927 if (p -> nx_mdns_rr_name != record_ptr -> nx_mdns_rr_name)
11928 continue;
11929
11930 /* In the probing state, we need not match the type. */
11931 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
11932 {
11933 if ((p -> nx_mdns_rr_type != record_ptr -> nx_mdns_rr_type) &&
11934 (record_ptr -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
11935 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
11936 continue;
11937 }
11938
11939 /* Check the RR class, Ignore the top bit. */
11940 if ((p -> nx_mdns_rr_class != (record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
11941 ((record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK) != NX_MDNS_RR_CLASS_ALL))
11942 continue;
11943
11944 /* Check if just match the basic info. */
11945 if (match_type == NX_MDNS_RR_MATCH_EXCEPT_RDATA)
11946 {
11947
11948 /* Find the same record. */
11949 *search_rr = p;
11950 return(NX_MDNS_SUCCESS);
11951 }
11952 else
11953 {
11954
11955 /* Yes, match all information of resource record. */
11956
11957 /* Check the state. */
11958 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11959 continue;
11960
11961 /* Reset the value. */
11962 same_rdata = NX_FALSE;
11963
11964 /* Compare the RDATA. */
11965 switch (p -> nx_mdns_rr_type)
11966 {
11967 case NX_MDNS_RR_TYPE_A:
11968 {
11969 if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address)
11970 {
11971 same_rdata = NX_TRUE;
11972 }
11973 break;
11974 }
11975 case NX_MDNS_RR_TYPE_SRV:
11976 {
11977 if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority) &&
11978 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights) &&
11979 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port) &&
11980 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11981 {
11982 same_rdata = NX_TRUE;
11983 }
11984 break;
11985 }
11986 case NX_MDNS_RR_TYPE_AAAA:
11987 {
11988 if(!memcmp(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, 16))
11989 {
11990 same_rdata = NX_TRUE;
11991 }
11992 break;
11993 }
11994 case NX_MDNS_RR_TYPE_PTR:
11995 case NX_MDNS_RR_TYPE_TXT:
11996
11997 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
11998 case NX_MDNS_RR_TYPE_CNAME:
11999 case NX_MDNS_RR_TYPE_NS:
12000 #endif
12001 {
12002
12003 /* Check the rdata. */
12004 if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
12005 {
12006 same_rdata = NX_TRUE;
12007 }
12008 break;
12009 }
12010 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12011 case NX_MDNS_RR_TYPE_MX:
12012 {
12013 if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name) &&
12014 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference))
12015 {
12016 same_rdata = NX_TRUE;
12017 }
12018 break;
12019 }
12020 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
12021
12022 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12023 case NX_MDNS_RR_TYPE_NSEC:
12024 {
12025 if ((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain == record_ptr ->nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain) &&
12026 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block) &&
12027 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length) &&
12028 (!memcmp(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12029 &(record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12030 record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length)))
12031 {
12032 same_rdata = NX_TRUE;
12033 }
12034 break;
12035 }
12036 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12037 default:
12038 {
12039
12040 /* This is an unsupported or unknown type. */
12041 return(NX_MDNS_UNSUPPORTED_TYPE);
12042 }
12043 }
12044
12045 /* Check the same RR. */
12046 if (same_rdata == NX_TRUE)
12047 {
12048
12049 /* Find the same record. */
12050 *search_rr = p;
12051 return(NX_MDNS_SUCCESS);
12052 }
12053 }
12054 }
12055
12056 return(NX_MDNS_ERROR);
12057 }
12058
12059
12060 /**************************************************************************/
12061 /* */
12062 /* FUNCTION RELEASE */
12063 /* */
12064 /* _nx_mdns_cache_add_string PORTABLE C */
12065 /* 6.1 */
12066 /* AUTHOR */
12067 /* */
12068 /* Yuxin Zhou, Microsoft Corporation */
12069 /* */
12070 /* DESCRIPTION */
12071 /* */
12072 /* This function adds or finds the mDNS string in the record buffer. */
12073 /* */
12074 /* INPUT */
12075 /* */
12076 /* mdns_ptr Pointer to mDNS instance */
12077 /* cache_type Cache type: local or peer */
12078 /* memory_ptr Pointer to the string */
12079 /* memory_size The size of string. */
12080 /* insert_rr Pointer to insert string. */
12081 /* find_string If set, just find the existed */
12082 /* string, otherwise, insert */
12083 /* this string if it does not */
12084 /* exist. */
12085 /* add_name If set, use name match */
12086 /* to check the string, */
12087 /* otherwise, use memcmp. */
12088 /* */
12089 /* OUTPUT */
12090 /* */
12091 /* status Completion status */
12092 /* */
12093 /* CALLS */
12094 /* */
12095 /* none */
12096 /* */
12097 /* CALLED BY */
12098 /* */
12099 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
12100 /* _nx_mdns_rr_ptr_add Add PTR resource record */
12101 /* _nx_mdns_rr_srv_add Add SRV resource record */
12102 /* _nx_mdns_rr_txt_add Add TXT resource record */
12103 /* _nx_mdns_query Send query */
12104 /* _nx_mdns_conflict_process Process the conflict */
12105 /* _nx_mdns_packet_rr_process Process resource record */
12106 /* */
12107 /* RELEASE HISTORY */
12108 /* */
12109 /* DATE NAME DESCRIPTION */
12110 /* */
12111 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12112 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
12113 /* verified memcpy use cases, */
12114 /* resulting in version 6.1 */
12115 /* */
12116 /**************************************************************************/
_nx_mdns_cache_add_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * memory_ptr,UINT memory_size,VOID ** insert_ptr,UCHAR find_string,UCHAR add_name)12117 UINT _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *memory_ptr, UINT memory_size, VOID **insert_ptr, UCHAR find_string, UCHAR add_name)
12118 {
12119
12120 UCHAR *cache_ptr;
12121 UINT cache_size;
12122 ULONG *tail;
12123 ULONG *head;
12124 UINT memory_len;
12125 UINT used_cache_size;
12126 USHORT len, cnt;
12127 USHORT min_len = 0xFFFF;
12128 UCHAR *p, *available, *start;
12129
12130
12131 /* Check the cache type. */
12132 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12133 {
12134 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12135 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12136 }
12137 else
12138 {
12139 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12140 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12141 }
12142
12143 /* Check cache pointer and cache size. */
12144 if ((cache_ptr == NX_NULL) || (cache_size == 0))
12145 {
12146 return(NX_MDNS_ERROR);
12147 }
12148
12149 /* Get head and tail. */
12150 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12151 p = (UCHAR*)tail;
12152 tail = (ULONG*)(*tail);
12153 head = (ULONG*)cache_ptr;
12154 head = (ULONG*)(*head);
12155
12156 /* Calculate the amount of memory needed to store this string, including CNT and LEN fields. */
12157
12158 /* Make the length 4 bytes align. */
12159 memory_len = memory_size;
12160
12161 /* Add the length of CNT and LEN fields. */
12162 memory_len = ((memory_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12163
12164 available = (UCHAR*)tail;
12165 while(p > (UCHAR*)tail)
12166 {
12167
12168 /* Get len and cnt. */
12169 len = *((USHORT*)(p - 2));
12170 cnt = *((USHORT*)(p - 4));
12171 start = p - len;
12172
12173 if((len == memory_len) &&
12174 (((add_name == NX_TRUE) &&
12175 (!_nx_mdns_name_match(start, memory_ptr, memory_size))) ||
12176 ((add_name == NX_FALSE) &&
12177 (!memcmp(start, memory_ptr, memory_size)))))
12178 {
12179
12180 /* The same string exists in the string table. */
12181 if(insert_ptr)
12182 *insert_ptr = start;
12183
12184 if(find_string == NX_FALSE)
12185 {
12186
12187 /* Increase the use count CNT. */
12188 cnt++;
12189 *((USHORT*)(p - 4)) = cnt;
12190 }
12191
12192 return(NX_MDNS_SUCCESS);
12193 }
12194
12195 /* This slot is not being used. The size of the slot is a smaller
12196 fit for this string. */
12197 if((cnt == 0) && (len >= memory_len) && (len < min_len))
12198 {
12199
12200 /* This place is better to insert. */
12201 available = p;
12202 min_len = len;
12203 }
12204
12205 /* Move to the next string. */
12206 p = start;
12207 }
12208
12209 if(find_string == NX_TRUE)
12210 return(NX_MDNS_ERROR);
12211
12212 /* If we reach this point, the string needs to be added to the string table. */
12213 if(available == (UCHAR*)tail)
12214 {
12215
12216 /* Make sure the service cache still has room to add this string
12217 (without overwriting the RR area.) */
12218 if(((UCHAR*)tail - memory_len) < (UCHAR*)head )
12219 {
12220
12221 /* This service cache does not have room for the string table to grow. */
12222 /* Invoke user-installed cache full notify function .*/
12223 if(mdns_ptr -> nx_mdns_cache_full_notify)
12224 {
12225
12226 /* Calculate the fragment size, RR size, string size, Head and Tail. */
12227 if(cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12228 {
12229 used_cache_size = mdns_ptr -> nx_mdns_local_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_local_string_bytes + 2 * sizeof(ULONG);
12230 }
12231 else
12232 {
12233 used_cache_size = mdns_ptr -> nx_mdns_peer_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_peer_string_bytes + 2 * sizeof(ULONG);
12234 }
12235
12236 /* Check the cache. */
12237 if ((used_cache_size + memory_len) <= cache_size)
12238 {
12239 (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FRAGMENTED, cache_type);
12240 }
12241 else
12242 {
12243 (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FULL, cache_type);
12244 }
12245 }
12246
12247 /* The buffer is full. */
12248 return(NX_MDNS_CACHE_ERROR);
12249 }
12250
12251 /* Update TAIL. */
12252 *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)(available - memory_len);
12253
12254 }
12255 else if(memory_len < min_len)
12256 {
12257
12258 /* Set the LEN for remaining space. */
12259 *((USHORT*)(available - 2 - memory_len)) = (USHORT)(min_len - memory_len);
12260 }
12261
12262 /* Set LEN and CNT. */
12263 *((USHORT*)(available - 2)) = (USHORT)memory_len;
12264 *((USHORT*)(available - 4)) = 1;
12265
12266 /* Clear last 4 bytes. */
12267 *((ULONG*)(available - 8)) = 0;
12268
12269 /* Insert string to cache. */
12270 memcpy(available - memory_len, memory_ptr, memory_size); /* Use case of memcpy is verified. */
12271
12272 /* Set end character 0. */
12273 *(available - memory_len + memory_size) = 0;
12274
12275
12276 /* Check the type. */
12277 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12278 {
12279
12280 /* Increase the count and bytes. */
12281 mdns_ptr -> nx_mdns_local_string_count ++;
12282 mdns_ptr -> nx_mdns_local_string_bytes += memory_len;
12283 }
12284 else
12285 {
12286
12287 /* Increase the count and bytes. */
12288 mdns_ptr -> nx_mdns_peer_string_count ++;
12289 mdns_ptr -> nx_mdns_peer_string_bytes += memory_len;
12290 }
12291
12292 if(insert_ptr)
12293 *insert_ptr = available - memory_len;
12294
12295 return(NX_MDNS_SUCCESS);
12296 }
12297
12298
12299 /**************************************************************************/
12300 /* */
12301 /* FUNCTION RELEASE */
12302 /* */
12303 /* _nx_mdns_cache_delete_string PORTABLE C */
12304 /* 6.1 */
12305 /* AUTHOR */
12306 /* */
12307 /* Yuxin Zhou, Microsoft Corporation */
12308 /* */
12309 /* DESCRIPTION */
12310 /* */
12311 /* This function deletes the mDNS string from the record buffer. */
12312 /* */
12313 /* INPUT */
12314 /* */
12315 /* mdns_ptr Pointer to mDNS instance */
12316 /* cache_type Cache type: local or peer */
12317 /* string_ptr Pointer to the string */
12318 /* string_len The length of string */
12319 /* */
12320 /* OUTPUT */
12321 /* */
12322 /* status Completion status */
12323 /* */
12324 /* CALLS */
12325 /* */
12326 /* None */
12327 /* */
12328 /* CALLED BY */
12329 /* */
12330 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
12331 /* _nx_mdns_rr_ptr_add Add PTR resource record */
12332 /* _nx_mdns_rr_srv_add Add SRV resource record */
12333 /* _nx_mdns_rr_txt_add Add TXT resource record */
12334 /* _nx_mdns_query Send query */
12335 /* _nx_mdns_conflict_process Process the conflict */
12336 /* _nx_mdns_cache_add_resource_record Add the resource record */
12337 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
12338 /* _nx_mdns_packet_rr_process Process resource record */
12339 /* */
12340 /* RELEASE HISTORY */
12341 /* */
12342 /* DATE NAME DESCRIPTION */
12343 /* */
12344 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12345 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12346 /* resulting in version 6.1 */
12347 /* */
12348 /**************************************************************************/
_nx_mdns_cache_delete_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * string_ptr,UINT string_len)12349 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len)
12350 {
12351
12352 UCHAR *cache_ptr;
12353 UINT cache_size;
12354 ULONG *tail;
12355 ULONG *end;
12356 USHORT cnt;
12357
12358
12359 /* Check the cache type. */
12360 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12361 {
12362 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12363 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12364 }
12365 else
12366 {
12367 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12368 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12369 }
12370
12371 /* Check cache pointer and cache size. */
12372 if ((cache_ptr == NX_NULL) || (cache_size == 0))
12373 {
12374 return(NX_MDNS_ERROR);
12375 }
12376
12377 /* Validate input parameter. */
12378 if(string_ptr == NX_NULL)
12379 return(NX_MDNS_PARAM_ERROR);
12380
12381 /* Check if input the string length. */
12382 if (string_len == 0)
12383 {
12384
12385 /* Check string length. */
12386 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12387 {
12388 return(NX_MDNS_DATA_SIZE_ERROR);
12389 }
12390 }
12391
12392 /* Add the length of CNT and LEN fields. */
12393 /* Also make the total length 4 bytes align. */
12394 string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12395
12396 end = (ULONG*)((UCHAR*)string_ptr + string_len);
12397
12398 /* Get tail. */
12399
12400 /* Validate the string table. */
12401 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12402 if(end > tail)
12403 {
12404
12405 /* The end of string exceeds cache_ptr. */
12406 return(NX_MDNS_CACHE_ERROR);
12407 }
12408 tail = (ULONG*)(*tail);
12409 if((UCHAR*)string_ptr < (UCHAR*)tail)
12410 {
12411
12412 /* The end of string exceeds cache_ptr. */
12413 return(NX_MDNS_CACHE_ERROR);
12414 }
12415
12416 /* Decrease the usage counter value. */
12417 cnt = *((USHORT*)((UCHAR*)end - 4));
12418 cnt--;
12419 *((USHORT*)((UCHAR*)end - 4)) = cnt;
12420
12421 /* Clear the memory if cnt is zero. */
12422 if(cnt == 0)
12423 {
12424 memset(string_ptr, 0, string_len - 2);
12425
12426 /* Check the type. */
12427 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12428 {
12429
12430 /* Increase the count and bytes. */
12431 mdns_ptr -> nx_mdns_local_string_count --;
12432 mdns_ptr -> nx_mdns_local_string_bytes -= string_len;
12433 }
12434 else
12435 {
12436
12437 /* Increase the count and bytes. */
12438 mdns_ptr -> nx_mdns_peer_string_count --;
12439 mdns_ptr -> nx_mdns_peer_string_bytes -= string_len;
12440 }
12441
12442 /* Update the tail pointer if the string at the tail is deleted. */
12443 if(string_ptr == tail)
12444 {
12445 tail = end;
12446
12447 while((end < ((ULONG*)cache_ptr + (cache_size >> 2) - 1)))
12448 {
12449
12450 /* Set the string pt and string length. */
12451 string_ptr = end;
12452
12453 /* Check string length. */
12454 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12455 {
12456 return(NX_MDNS_DATA_SIZE_ERROR);
12457 }
12458
12459 /* Check the string length. */
12460 if(string_len == 0)
12461 {
12462
12463 /* This slot is cleared. */
12464 while(*((ULONG*)string_ptr) == 0)
12465 string_ptr = (UCHAR*)string_ptr + 4;
12466
12467 end = (ULONG*)string_ptr + 1;
12468 cnt = *((USHORT*)string_ptr);
12469 }
12470 else
12471 {
12472
12473 /* Make the length 4 bytes align and add the length of CNT and LEN fields. */
12474 string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12475
12476 end = (ULONG*)((UCHAR*)string_ptr + string_len);
12477 cnt = *((USHORT*)((UCHAR*)end - 4));
12478 }
12479
12480 /* Check whether this slot is never referenced. */
12481 if(cnt == 0)
12482 tail = end;
12483 else
12484 break;
12485 }
12486 *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)tail;
12487 }
12488 }
12489
12490 return(NX_MDNS_SUCCESS);
12491 }
12492
12493
12494 /**************************************************************************/
12495 /* */
12496 /* FUNCTION RELEASE */
12497 /* */
12498 /* _nx_mdns_cache_delete_rr_string PORTABLE C */
12499 /* 6.1 */
12500 /* AUTHOR */
12501 /* */
12502 /* Yuxin Zhou, Microsoft Corporation */
12503 /* */
12504 /* DESCRIPTION */
12505 /* */
12506 /* This function deletes the mDNS string from the record buffer. */
12507 /* */
12508 /* INPUT */
12509 /* */
12510 /* mdns_ptr Pointer to mDNS instance */
12511 /* cache_type Cache type: local or peer */
12512 /* string_ptr Pointer to the string */
12513 /* */
12514 /* OUTPUT */
12515 /* */
12516 /* None */
12517 /* */
12518 /* CALLS */
12519 /* */
12520 /* _nx_mdns_cache_delete_string Delete the string from cache */
12521 /* */
12522 /* CALLED BY */
12523 /* */
12524 /* _nx_mdns_cache_add_resource_record Add the resource record */
12525 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
12526 /* */
12527 /* RELEASE HISTORY */
12528 /* */
12529 /* DATE NAME DESCRIPTION */
12530 /* */
12531 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12532 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12533 /* resulting in version 6.1 */
12534 /* */
12535 /**************************************************************************/
_nx_mdns_cache_delete_rr_string(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_rr)12536 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr)
12537 {
12538
12539 /* Delete the name strings. */
12540 _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_name, 0);
12541
12542 /* Check if need to release the rdata string. */
12543 if (record_rr -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
12544 {
12545
12546 if (((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
12547 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12548 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
12549 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12550 ||
12551 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
12552 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12553 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12554 ||
12555 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_CNAME) ||
12556 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NS) ||
12557 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_MX)
12558 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
12559 ) &&
12560 (record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
12561 {
12562
12563 /* Delete the same strings. */
12564 _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
12565 }
12566 }
12567 }
12568
12569
12570 #ifndef NX_MDNS_DISABLE_SERVER
12571 /**************************************************************************/
12572 /* */
12573 /* FUNCTION RELEASE */
12574 /* */
12575 /* _nx_mdns_additional_resource_record_find PORTABLE C */
12576 /* 6.1 */
12577 /* AUTHOR */
12578 /* */
12579 /* Yuxin Zhou, Microsoft Corporation */
12580 /* */
12581 /* DESCRIPTION */
12582 /* */
12583 /* This function find the mDNS additional resource record. */
12584 /* */
12585 /* INPUT */
12586 /* */
12587 /* mdns_ptr Pointer to mDNS instance */
12588 /* record_ptr Pointer to record instance */
12589 /* */
12590 /* OUTPUT */
12591 /* */
12592 /* status Completion status */
12593 /* */
12594 /* CALLS */
12595 /* */
12596 /* None */
12597 /* */
12598 /* CALLED BY */
12599 /* */
12600 /* _nx_mdns_response_send Send response message */
12601 /* */
12602 /* RELEASE HISTORY */
12603 /* */
12604 /* DATE NAME DESCRIPTION */
12605 /* */
12606 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12607 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12608 /* resulting in version 6.1 */
12609 /* */
12610 /**************************************************************************/
_nx_mdns_additional_resource_record_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12611 UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12612 {
12613
12614 ULONG *head;
12615 NX_MDNS_RR *p;
12616
12617 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12618 head = (ULONG*)(*head);
12619
12620 /* Find the additional resource records according to the type. */
12621 switch (record_ptr -> nx_mdns_rr_type )
12622 {
12623
12624 case NX_MDNS_RR_TYPE_A:
12625 case NX_MDNS_RR_TYPE_AAAA:
12626 {
12627
12628 /* Recommends AAAA records in the additional section when responding
12629 to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51. */
12630 _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_interface_index);
12631
12632 break;
12633 }
12634
12635 case NX_MDNS_RR_TYPE_PTR:
12636 {
12637
12638 /* Find the additional resource record. */
12639 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12640 {
12641
12642 /* Check the interface. */
12643 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12644 continue;
12645
12646 /* The SRV record(s) named in the PTR rdata.
12647 The TXT record(s) named in the PTR rdata.
12648 All address records (type "A" and "AAAA") named in the SRV rdata. RFC6763, Section12.1, Page30.*/
12649
12650 /* The SRV records named in the PTR rdata */
12651 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
12652 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12653 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12654 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12655 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12656 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12657 {
12658
12659 /* Set the flag to add this resource records into additional records. */
12660 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12661
12662 /* All address records (type "A" and "AAAA") named in the SRV rdata */
12663 _nx_mdns_additional_a_aaaa_find(mdns_ptr, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12664 }
12665
12666 /* The TXT records named in the PTR rdata */
12667 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12668 (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)) &&
12669 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12670 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12671 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12672 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12673 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12674 {
12675
12676 /* Set the flag to add this resource records into additional records. */
12677 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12678 }
12679 }
12680
12681 break;
12682 }
12683
12684 case NX_MDNS_RR_TYPE_SRV:
12685 case NX_MDNS_RR_TYPE_TXT:
12686 {
12687
12688 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12689 /* Find the additional resource record. */
12690 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12691 {
12692
12693 /* Check the interface. */
12694 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12695 continue;
12696
12697 /* The NSEC records named same as SRV/TXT name. */
12698 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
12699 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_name) &&
12700 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12701 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12702 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12703 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12704 {
12705
12706 /* Set the flag to add this resource records into additional records. */
12707 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12708 }
12709 }
12710 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12711
12712 /* All address records (type "A" and "AAAA") named in the SRV rdata */
12713 if (record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
12714 _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12715 break;
12716 }
12717 }
12718
12719 return(NX_MDNS_SUCCESS);
12720 }
12721
12722
12723 /**************************************************************************/
12724 /* */
12725 /* FUNCTION RELEASE */
12726 /* */
12727 /* _nx_mdns_additional_a_aaaa_find PORTABLE C */
12728 /* 6.1 */
12729 /* AUTHOR */
12730 /* */
12731 /* Yuxin Zhou, Microsoft Corporation */
12732 /* */
12733 /* DESCRIPTION */
12734 /* */
12735 /* This function find the mDNS additional A/AAAA resource record. */
12736 /* */
12737 /* INPUT */
12738 /* */
12739 /* mdns_ptr Pointer to mDNS instance */
12740 /* record_ptr Pointer to record instance */
12741 /* */
12742 /* OUTPUT */
12743 /* */
12744 /* status Completion status */
12745 /* */
12746 /* CALLS */
12747 /* */
12748 /* None */
12749 /* */
12750 /* CALLED BY */
12751 /* */
12752 /* _nx_mdns_additional_resource_record_find */
12753 /* Find additional record */
12754 /* */
12755 /* RELEASE HISTORY */
12756 /* */
12757 /* DATE NAME DESCRIPTION */
12758 /* */
12759 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12760 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12761 /* resulting in version 6.1 */
12762 /* */
12763 /**************************************************************************/
_nx_mdns_additional_a_aaaa_find(NX_MDNS * mdns_ptr,UCHAR * name,UINT interface_index)12764 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index)
12765 {
12766
12767 ULONG *head;
12768 NX_MDNS_RR *p;
12769
12770 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12771 head = (ULONG*)(*head);
12772
12773 /* Recommends AAAA records in the additional section when responding
12774 to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51. */
12775 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12776 {
12777
12778 /* Check the interface index. */
12779 if (p -> nx_mdns_rr_interface_index != interface_index)
12780 continue;
12781
12782 /* Find the "A" records. */
12783 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
12784 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA ||
12785 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))) &&
12786 (p -> nx_mdns_rr_name == name) &&
12787 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12788 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12789 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12790 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12791 {
12792
12793 /* Set the flag to add this resource records into additional records. */
12794 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12795 }
12796 }
12797 }
12798 #endif /* NX_MDNS_DISABLE_SERVER */
12799
12800
12801 #ifndef NX_MDNS_DISABLE_CLIENT
12802 /**************************************************************************/
12803 /* */
12804 /* FUNCTION RELEASE */
12805 /* */
12806 /* _nx_mdns_known_answer_find PORTABLE C */
12807 /* 6.1 */
12808 /* AUTHOR */
12809 /* */
12810 /* Yuxin Zhou, Microsoft Corporation */
12811 /* */
12812 /* DESCRIPTION */
12813 /* */
12814 /* This function finds the mDNS known answer. */
12815 /* */
12816 /* INPUT */
12817 /* */
12818 /* mdns_ptr Pointer to mDNS instance */
12819 /* record_ptr Pointer to record instance */
12820 /* */
12821 /* OUTPUT */
12822 /* */
12823 /* status Completion status */
12824 /* */
12825 /* CALLS */
12826 /* */
12827 /* None */
12828 /* */
12829 /* CALLED BY */
12830 /* */
12831 /* _nx_mdns_query_send Send query message */
12832 /* _nx_mdns_packet_process Process mDNS packet */
12833 /* */
12834 /* RELEASE HISTORY */
12835 /* */
12836 /* DATE NAME DESCRIPTION */
12837 /* */
12838 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12839 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12840 /* resulting in version 6.1 */
12841 /* */
12842 /**************************************************************************/
_nx_mdns_known_answer_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12843 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12844 {
12845
12846 UINT status = NX_MDNS_NO_KNOWN_ANSWER;
12847 ULONG *head, *tail;
12848 NX_MDNS_RR *p;
12849 UINT i;
12850 UINT name_length;
12851 #ifndef NX_MDNS_DISABLE_SERVER
12852 UINT cache_count = 2;
12853 #else
12854 UINT cache_count = 1;
12855 #endif
12856
12857 /* Check string length. */
12858 if (_nx_utility_string_length_check((CHAR *)(record_ptr -> nx_mdns_rr_name), &name_length, NX_MDNS_NAME_MAX))
12859 {
12860 return(NX_MDNS_DATA_SIZE_ERROR);
12861 }
12862
12863 /* Loop to find the known answer in cache. */
12864 for (i = 0; i < cache_count; i++)
12865 {
12866
12867 /* Set the pointer. */
12868 if (i == 0)
12869 {
12870 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12871 }
12872 #ifndef NX_MDNS_DISABLE_SERVER
12873 else
12874 {
12875 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12876 }
12877 #endif /* NX_MDNS_DISABLE_SERVER */
12878 tail = (ULONG*)(*head);
12879
12880 /* Whether this mDNS message response to query. */
12881 for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
12882 {
12883
12884 /* Check the state. */
12885 if(p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_VALID)
12886 continue;
12887
12888 /* Check the interface index. */
12889 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12890 continue;
12891
12892 /* Check whether the Known Answer record it is. */
12893 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_name, name_length)) &&
12894 (p -> nx_mdns_rr_class == record_ptr -> nx_mdns_rr_class))
12895 {
12896
12897 if ((record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) ||
12898 (p -> nx_mdns_rr_type == record_ptr -> nx_mdns_rr_type))
12899 {
12900
12901 /* Set the additional flag. */
12902 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_KNOWN_ANSWER;
12903
12904 /* Yes, find the known answer. */
12905 status = NX_MDNS_SUCCESS;
12906 }
12907 }
12908 }
12909 }
12910
12911 return(status);
12912 }
12913 #endif /* NX_MDNS_DISABLE_CLIENT */
12914
12915
12916 #ifndef NX_MDNS_DISABLE_CLIENT
12917 /**************************************************************************/
12918 /* */
12919 /* FUNCTION RELEASE */
12920 /* */
12921 /* _nx_mdns_query_check PORTABLE C */
12922 /* 6.1.11 */
12923 /* AUTHOR */
12924 /* */
12925 /* Yuxin Zhou, Microsoft Corporation */
12926 /* */
12927 /* DESCRIPTION */
12928 /* */
12929 /* This function checks whether mDNS querier already has one Unique */
12930 /* record in the local buffer/remote buffer or one same query in the */
12931 /* remote buffer. */
12932 /* */
12933 /* INPUT */
12934 /* */
12935 /* mdns_ptr Pointer to mDNS instance */
12936 /* name The resource record name */
12937 /* type The resource record type */
12938 /* interface_index The interface index */
12939 /* */
12940 /* OUTPUT */
12941 /* */
12942 /* status Completion status */
12943 /* */
12944 /* CALLS */
12945 /* */
12946 /* None */
12947 /* */
12948 /* CALLED BY */
12949 /* */
12950 /* _nx_mdns_query Send the query */
12951 /* */
12952 /* RELEASE HISTORY */
12953 /* */
12954 /* DATE NAME DESCRIPTION */
12955 /* */
12956 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12957 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12958 /* resulting in version 6.1 */
12959 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
12960 /* corrected the random value, */
12961 /* resulting in version 6.1.11 */
12962 /* */
12963 /**************************************************************************/
_nx_mdns_query_check(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT one_shot,NX_MDNS_RR ** search_rr,UINT interface_index)12964 static UINT _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index)
12965 {
12966
12967 ULONG *head;
12968 NX_MDNS_RR *p;
12969 UCHAR i;
12970 UCHAR same_query = NX_FALSE;
12971 NX_MDNS_RR *rr = NX_NULL;
12972 UCHAR srv_flag = NX_FALSE;
12973 UCHAR txt_flag = NX_FALSE;
12974 UINT name_length;
12975
12976
12977 /* Check string length. */
12978 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
12979 {
12980 return(NX_MDNS_DATA_SIZE_ERROR);
12981 }
12982
12983 for(i = 0; i < 2; i++)
12984 {
12985 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
12986 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12987 else
12988 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12989
12990 if(head)
12991 {
12992 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
12993 {
12994
12995 /* Check whether the resource record is valid. */
12996 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
12997 continue;
12998
12999 /* Check the interface index. */
13000 if (p -> nx_mdns_rr_interface_index != interface_index)
13001 continue;
13002
13003 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, name, name_length))
13004 {
13005 if ((p -> nx_mdns_rr_type == type) && (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
13006 {
13007
13008 /* Set the query. */
13009 same_query = NX_TRUE;
13010
13011 /* Record the RR potiner. */
13012 rr = p;
13013 }
13014
13015 /* Check the rr type. */
13016 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
13017 srv_flag = NX_TRUE;
13018 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT)
13019 txt_flag = NX_TRUE;
13020
13021 if ((p -> nx_mdns_rr_type == type) ||
13022 ((type == NX_MDNS_RR_TYPE_ALL) && (srv_flag == NX_TRUE) && (txt_flag == NX_TRUE)))
13023 {
13024 if (search_rr)
13025 *search_rr = p;
13026
13027 /* Check the query type. */
13028 if (one_shot == NX_TRUE)
13029 return(NX_MDNS_EXIST_SHARED_RR);
13030
13031 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
13032 return(NX_MDNS_EXIST_UNIQUE_RR);
13033 }
13034 }
13035 }
13036 }
13037 }
13038
13039 /* Check the same query. */
13040 if (same_query == NX_TRUE)
13041 {
13042
13043 /* A multicast DNS querier should also delay the first query of the series by
13044 a randomly chosen amount in the range 20-120ms. */
13045 rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
13046 rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
13047
13048 /* Set the mDNS timer. */
13049 _nx_mdns_timer_set(mdns_ptr, rr, rr -> nx_mdns_rr_timer_count);
13050
13051 return (NX_MDNS_EXIST_SAME_QUERY);
13052 }
13053
13054 /* Return a successful status. */
13055 return(NX_SUCCESS);
13056 }
13057
13058
13059 /**************************************************************************/
13060 /* */
13061 /* FUNCTION RELEASE */
13062 /* */
13063 /* _nx_mdns_query_cleanup PORTABLE C */
13064 /* 6.1 */
13065 /* AUTHOR */
13066 /* */
13067 /* Yuxin Zhou, Microsoft Corporation */
13068 /* */
13069 /* DESCRIPTION */
13070 /* */
13071 /* This function processes mDNS One-shot query timeout and thread */
13072 /* terminate actions that require the mDNS data structures to be */
13073 /* cleaned up. */
13074 /* */
13075 /* INPUT */
13076 /* */
13077 /* thread_ptr Pointer to suspended thread's */
13078 /* control block */
13079 /* */
13080 /* OUTPUT */
13081 /* */
13082 /* None */
13083 /* */
13084 /* CALLS */
13085 /* */
13086 /* _tx_thread_system_resume Resume thread service */
13087 /* */
13088 /* CALLED BY */
13089 /* */
13090 /* _tx_thread_timeout Thread timeout processing */
13091 /* _tx_thread_terminate Thread terminate processing */
13092 /* */
13093 /* RELEASE HISTORY */
13094 /* */
13095 /* DATE NAME DESCRIPTION */
13096 /* */
13097 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13098 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13099 /* resulting in version 6.1 */
13100 /* */
13101 /**************************************************************************/
_nx_mdns_query_cleanup(TX_THREAD * thread_ptr NX_CLEANUP_PARAMETER)13102 VOID _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER)
13103 {
13104
13105 TX_INTERRUPT_SAVE_AREA
13106
13107 NX_MDNS *mdns_ptr;
13108
13109
13110 NX_CLEANUP_EXTENSION
13111
13112 /* Setup pointer to UDP socket control block. */
13113 mdns_ptr = (NX_MDNS *) thread_ptr -> tx_thread_suspend_control_block;
13114
13115 /* Disable interrupts to remove the suspended thread from the UDP socket. */
13116 TX_DISABLE
13117
13118 /* Determine if the cleanup is still required. */
13119 if ((thread_ptr -> tx_thread_suspend_cleanup) && (mdns_ptr) &&
13120 (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
13121 {
13122
13123 /* Yes, we still have thread suspension! */
13124
13125 /* Clear the suspension cleanup flag. */
13126 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
13127
13128 /* Remove the suspended thread from the list. */
13129
13130 /* See if this is the only suspended thread on the list. */
13131 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13132 {
13133
13134 /* Yes, the only suspended thread. */
13135
13136 /* Update the head pointer. */
13137 mdns_ptr -> nx_mdns_rr_receive_suspension_list = NX_NULL;
13138 }
13139 else
13140 {
13141
13142 /* At least one more thread is on the same suspension list. */
13143
13144 /* Update the list head pointer. */
13145 mdns_ptr -> nx_mdns_rr_receive_suspension_list = thread_ptr -> tx_thread_suspended_next;
13146
13147 /* Update the links of the adjacent threads. */
13148 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13149 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13150 }
13151
13152 /* Decrement the suspension count. */
13153 mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13154
13155 /* Now we need to determine if this cleanup is from a terminate, timeout,
13156 or from a wait abort. */
13157 if (thread_ptr -> tx_thread_state == TX_TCP_IP)
13158 {
13159
13160 /* Thread still suspended on the UDP socket. Setup return error status and
13161 resume the thread. */
13162
13163 /* Setup return status. */
13164 thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13165
13166 /* Temporarily disable preemption. */
13167 _tx_thread_preempt_disable++;
13168
13169 /* Restore interrupts. */
13170 TX_RESTORE
13171
13172 /* Resume the thread! Check for preemption even though we are executing
13173 from the system timer thread right now which normally executes at the
13174 highest priority. */
13175 _tx_thread_system_resume(thread_ptr);
13176
13177 /* Finished, just return. */
13178 return;
13179 }
13180 }
13181
13182 /* Restore interrupts. */
13183 TX_RESTORE
13184 }
13185
13186
13187 /**************************************************************************/
13188 /* */
13189 /* FUNCTION RELEASE */
13190 /* */
13191 /* _nx_mdns_query_thread_suspend PORTABLE C */
13192 /* 6.1 */
13193 /* AUTHOR */
13194 /* */
13195 /* Yuxin Zhou, Microsoft Corporation */
13196 /* */
13197 /* DESCRIPTION */
13198 /* */
13199 /* This function suspends a thread on a mDNS client query service */
13200 /* */
13201 /* INPUT */
13202 /* */
13203 /* suspension_list_head Pointer to the suspension list*/
13204 /* mutex_ptr Pointer to mutex to release */
13205 /* suspend_cleanup Suspension cleanup routine */
13206 /* wait_option Optional timeout value */
13207 /* */
13208 /* OUTPUT */
13209 /* */
13210 /* None */
13211 /* */
13212 /* CALLS */
13213 /* */
13214 /* tx_mutex_put Release protection */
13215 /* _tx_thread_system_suspend Suspend thread */
13216 /* */
13217 /* CALLED BY */
13218 /* */
13219 /* */
13220 /* RELEASE HISTORY */
13221 /* */
13222 /* DATE NAME DESCRIPTION */
13223 /* */
13224 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13225 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13226 /* resulting in version 6.1 */
13227 /* */
13228 /**************************************************************************/
_nx_mdns_query_thread_suspend(TX_THREAD ** suspension_list_head,VOID (* suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),NX_MDNS * mdns_ptr,NX_MDNS_RR ** rr,ULONG wait_option)13229 VOID _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
13230 NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option)
13231 {
13232
13233 TX_INTERRUPT_SAVE_AREA
13234
13235 TX_THREAD *thread_ptr;
13236
13237
13238 /* Lockout interrupts. */
13239 TX_DISABLE
13240
13241 /* Pickup thread pointer. */
13242 thread_ptr = _tx_thread_current_ptr;
13243
13244 /* Setup suspension list. */
13245 if (*suspension_list_head)
13246 {
13247
13248 /* This list is not NULL, add current thread to the end. */
13249 thread_ptr -> tx_thread_suspended_next = *suspension_list_head;
13250 thread_ptr -> tx_thread_suspended_previous = (*suspension_list_head) -> tx_thread_suspended_previous;
13251 ((*suspension_list_head) -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr;
13252 (*suspension_list_head) -> tx_thread_suspended_previous = thread_ptr;
13253 }
13254 else
13255 {
13256
13257 /* No other threads are suspended. Setup the head pointer and
13258 just setup this threads pointers to itself. */
13259 *suspension_list_head = thread_ptr;
13260 thread_ptr -> tx_thread_suspended_next = thread_ptr;
13261 thread_ptr -> tx_thread_suspended_previous = thread_ptr;
13262 }
13263
13264 /* Setup return status. */
13265 thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13266
13267 /* Setup cleanup routine pointer. */
13268 thread_ptr -> tx_thread_suspend_cleanup = suspend_cleanup;
13269
13270 /* Setup cleanup information, i.e. this pool control block. */
13271 thread_ptr -> tx_thread_suspend_control_block = (void *)mdns_ptr;
13272
13273 /* Save the return RR pointer address as well. */
13274 thread_ptr -> tx_thread_additional_suspend_info = (void *)rr;
13275
13276 /* Increment the suspended thread count. */
13277 mdns_ptr -> nx_mdns_rr_receive_suspended_count++;
13278
13279 /* Set the state to suspended. */
13280 thread_ptr -> tx_thread_state = TX_TCP_IP;
13281
13282 /* Set the suspending flag. */
13283 thread_ptr -> tx_thread_suspending = TX_TRUE;
13284
13285 /* Temporarily disable preemption. */
13286 _tx_thread_preempt_disable++;
13287
13288 /* Save the timeout value. */
13289 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
13290
13291 /* Restore interrupts. */
13292 TX_RESTORE
13293
13294 /* Call actual thread suspension routine. */
13295 _tx_thread_system_suspend(thread_ptr);
13296 }
13297
13298
13299 /**************************************************************************/
13300 /* */
13301 /* FUNCTION RELEASE */
13302 /* */
13303 /* _nx_mdns_query_thread_resume PORTABLE C */
13304 /* 6.1 */
13305 /* AUTHOR */
13306 /* */
13307 /* Yuxin Zhou, Microsoft Corporation */
13308 /* */
13309 /* DESCRIPTION */
13310 /* */
13311 /* This function resumes a thread suspended on a mDNS Client query */
13312 /* service. */
13313 /* */
13314 /* INPUT */
13315 /* */
13316 /* thread_ptr Pointer to suspended thread's */
13317 /* control block */
13318 /* */
13319 /* OUTPUT */
13320 /* */
13321 /* None */
13322 /* */
13323 /* CALLS */
13324 /* */
13325 /* _tx_thread_system_resume Resume thread service */
13326 /* */
13327 /* CALLED BY */
13328 /* */
13329 /* _tx_thread_timeout Thread timeout processing */
13330 /* _tx_thread_terminate Thread terminate processing */
13331 /* */
13332 /* RELEASE HISTORY */
13333 /* */
13334 /* DATE NAME DESCRIPTION */
13335 /* */
13336 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13337 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13338 /* resulting in version 6.1 */
13339 /* */
13340 /**************************************************************************/
_nx_mdns_query_thread_resume(TX_THREAD ** suspension_list_head,NX_MDNS * mdns_ptr,NX_MDNS_RR * rr)13341 VOID _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr)
13342 {
13343
13344 TX_INTERRUPT_SAVE_AREA
13345
13346 TX_THREAD *thread_ptr;
13347
13348
13349 /* Disable interrupts. */
13350 TX_DISABLE
13351
13352 /* Pickup the thread pointer. */
13353 thread_ptr = *suspension_list_head;
13354
13355 /* Determine if there still is a thread suspended. */
13356 if (thread_ptr)
13357 {
13358
13359 /* Remove the suspended thread from the list. */
13360
13361 /* See if this is the only suspended thread on the list. */
13362 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13363 {
13364
13365 /* Yes, the only suspended thread. */
13366
13367 /* Update the head pointer. */
13368 *suspension_list_head = TX_NULL;
13369 }
13370 else
13371 {
13372
13373 /* At least one more thread is on the same expiration list. */
13374
13375 /* Update the list head pointer. */
13376 *suspension_list_head = thread_ptr -> tx_thread_suspended_next;
13377
13378 /* Update the links of the adjacent threads. */
13379 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13380 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13381 }
13382
13383 /* Decrement the suspension count. */
13384 mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13385
13386 /* Prepare for resumption of the first thread. */
13387
13388 /* Clear cleanup routine to avoid timeout. */
13389 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
13390
13391 /* Temporarily disable preemption. */
13392 _tx_thread_preempt_disable++;
13393
13394 /* Return this block pointer to the suspended thread waiting for
13395 a block. */
13396 *((NX_MDNS_RR **) thread_ptr -> tx_thread_additional_suspend_info) = rr;
13397
13398 /* Restore interrupts. */
13399 TX_RESTORE
13400
13401 /* Put return status into the thread control block. */
13402 thread_ptr -> tx_thread_suspend_status = NX_MDNS_SUCCESS;
13403
13404 /* Resume thread. */
13405 _tx_thread_system_resume(thread_ptr);
13406 }
13407 else
13408 {
13409
13410 /* Restore interrupts. */
13411 TX_RESTORE
13412 }
13413 }
13414
13415
13416 /**************************************************************************/
13417 /* */
13418 /* FUNCTION RELEASE */
13419 /* */
13420 /* _nx_mdns_service_mask_match PORTABLE C */
13421 /* 6.1 */
13422 /* AUTHOR */
13423 /* */
13424 /* Yuxin Zhou, Microsoft Corporation */
13425 /* */
13426 /* DESCRIPTION */
13427 /* */
13428 /* This function matchs the mDNS service mask to listen the service */
13429 /* and notify the application, or ignore the service. */
13430 /* */
13431 /* INPUT */
13432 /* */
13433 /* mdns_ptr Pointer to mDNS instance */
13434 /* service_type Pointer to Service type */
13435 /* service_mask The Service mask */
13436 /* */
13437 /* OUTPUT */
13438 /* */
13439 /* status Completion status */
13440 /* */
13441 /* CALLS */
13442 /* */
13443 /* tx_mutex_get Get the mDNS mutex */
13444 /* tx_mutex_put Put the mDNS mutex */
13445 /* */
13446 /* CALLED BY */
13447 /* */
13448 /* Application Code */
13449 /* */
13450 /* RELEASE HISTORY */
13451 /* */
13452 /* DATE NAME DESCRIPTION */
13453 /* */
13454 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13455 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13456 /* resulting in version 6.1 */
13457 /* */
13458 /**************************************************************************/
_nx_mdns_service_mask_match(NX_MDNS * mdns_ptr,UCHAR * service_type,ULONG service_mask)13459 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask)
13460 {
13461
13462 UINT i;
13463 UINT found;
13464 ULONG mask;
13465 UINT type_length;
13466
13467
13468 NX_PARAMETER_NOT_USED(mdns_ptr);
13469
13470 /* Initialize the parameters. */
13471 i = 0;
13472 found = 0;
13473 mask = 0x00000001;
13474
13475 /* Compare the service type. */
13476 while (nx_mdns_service_types[i])
13477 {
13478
13479 /* Check string length. */
13480 if (_nx_utility_string_length_check((CHAR *)nx_mdns_service_types[i], &type_length, NX_MDNS_TYPE_MAX))
13481 {
13482 return(NX_MDNS_DATA_SIZE_ERROR);
13483 }
13484
13485 /* Find the same service type. */
13486 if (!_nx_mdns_name_match(service_type, (UCHAR *)(nx_mdns_service_types[i]), type_length))
13487 {
13488 found = 1;
13489 break;
13490 }
13491 i ++;
13492 }
13493
13494 /* Check the result. */
13495 if (found)
13496 {
13497
13498 /* Check service mask. */
13499 if (service_mask & (mask << i))
13500 {
13501 return(NX_MDNS_SUCCESS);
13502 }
13503 }
13504
13505 /* Return status. */
13506 return(NX_MDNS_SERVICE_TYPE_MISMATCH);
13507 }
13508 #endif /* NX_MDNS_DISABLE_CLIENT */
13509
13510
13511 /**************************************************************************/
13512 /* */
13513 /* FUNCTION RELEASE */
13514 /* */
13515 /* _nx_mdns_name_match PORTABLE C */
13516 /* 6.1 */
13517 /* AUTHOR */
13518 /* */
13519 /* Yuxin Zhou, Microsoft Corporation */
13520 /* */
13521 /* DESCRIPTION */
13522 /* */
13523 /* This function name string match, the lowercase letters "a" to "z" */
13524 /* match their uppercase equivalents "A" to "Z". */
13525 /* */
13526 /* INPUT */
13527 /* */
13528 /* ptr Pointer to destination */
13529 /* name Source name string */
13530 /* */
13531 /* OUTPUT */
13532 /* */
13533 /* status Completion status */
13534 /* */
13535 /* CALLS */
13536 /* */
13537 /* None */
13538 /* */
13539 /* CALLED BY */
13540 /* */
13541 /* _nx_mdns_packet_rr_add Add the RR into packet */
13542 /* */
13543 /* RELEASE HISTORY */
13544 /* */
13545 /* DATE NAME DESCRIPTION */
13546 /* */
13547 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13548 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13549 /* resulting in version 6.1 */
13550 /* */
13551 /**************************************************************************/
_nx_mdns_name_match(UCHAR * src,UCHAR * dst,UINT length)13552 static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length)
13553 {
13554
13555 UINT index = 0;
13556
13557
13558 /* Check the name. */
13559 while (*dst != '\0')
13560 {
13561 if((*src) != (*dst))
13562 {
13563 if((((*src) | 0x20) >= 'a') && (((*src) | 0x20) <= 'z'))
13564 {
13565 /* Match the characters, case in-sensitive. */
13566 if(((*src) | 0x20) != ((*dst) | 0x20))
13567 return(NX_MDNS_NAME_MISMATCH);
13568 }
13569 else
13570 {
13571 return(NX_MDNS_NAME_MISMATCH);
13572 }
13573 }
13574 src ++;
13575 dst ++;
13576 index ++;
13577 }
13578
13579 /* Check the scan length. */
13580 if (index != length)
13581 {
13582 return (NX_MDNS_NAME_MISMATCH);
13583 }
13584
13585 /* Return success. */
13586 return(NX_MDNS_SUCCESS);
13587 }
13588
13589
13590 /**************************************************************************/
13591 /* */
13592 /* FUNCTION RELEASE */
13593 /* */
13594 /* _nx_mdns_txt_string_encode PORTABLE C */
13595 /* 6.1 */
13596 /* AUTHOR */
13597 /* */
13598 /* Yuxin Zhou, Microsoft Corporation */
13599 /* */
13600 /* DESCRIPTION */
13601 /* */
13602 /* This function encodes the txt string and adds the txt string into */
13603 /* packet.the TXT records are formatted in a "key=value" notation */
13604 /* with ";" acting as separator when more then one key is available. */
13605 /* */
13606 /* INPUT */
13607 /* */
13608 /* ptr Pointer to destination */
13609 /* name Source name string */
13610 /* */
13611 /* OUTPUT */
13612 /* */
13613 /* status Completion status */
13614 /* */
13615 /* CALLS */
13616 /* */
13617 /* None */
13618 /* */
13619 /* CALLED BY */
13620 /* */
13621 /* _nx_mdns_packet_rr_add Add the RR into packet */
13622 /* */
13623 /* RELEASE HISTORY */
13624 /* */
13625 /* DATE NAME DESCRIPTION */
13626 /* */
13627 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13628 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13629 /* resulting in version 6.1 */
13630 /* */
13631 /**************************************************************************/
_nx_mdns_txt_string_encode(UCHAR * ptr,UCHAR * txt)13632 static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *txt)
13633 {
13634
13635 UCHAR *length;
13636 UINT count = 1;
13637
13638
13639 /* Point to the first character position in the buffer. This will point
13640 to the length of the following name. */
13641 length = ptr++;
13642
13643 /* Default the length to zero. */
13644 *length = 0;
13645
13646 /* Move through string, copying bytes and updating length.
13647 Whenever a "." is found, start a new string by updating the
13648 pointer to the length and setting the length to zero. */
13649 while (*txt)
13650 {
13651
13652 /* Is a dot been found? */
13653 if (*txt == ';')
13654 {
13655
13656
13657 /* Yes, setup a new length pointer. */
13658 length = ptr++;
13659
13660 /* Default the length to zero. */
13661 *length = 0;
13662 txt++;
13663 }
13664 else
13665 {
13666
13667 /* Copy a character to the destination. */
13668 *ptr++ = *txt++;
13669
13670 /* Adjust the length of the current segment. */
13671 (*length)++;
13672 }
13673
13674 /* Increment the total count here. */
13675 count++;
13676 }
13677
13678 /* Return the count. */
13679 return(count);
13680 }
13681
13682
13683 /**************************************************************************/
13684 /* */
13685 /* FUNCTION RELEASE */
13686 /* */
13687 /* _nx_mdns_txt_string_decode PORTABLE C */
13688 /* 6.1.3 */
13689 /* AUTHOR */
13690 /* */
13691 /* Yuxin Zhou, Microsoft Corporation */
13692 /* */
13693 /* DESCRIPTION */
13694 /* */
13695 /* This function decode the txt string and adds the txt string into */
13696 /* buffer.the TXT records are formatted in a "key=value" notation */
13697 /* with ";" acting as separator when more then one key is available. */
13698 /* */
13699 /* INPUT */
13700 /* */
13701 /* data Pointer to buffer to decode */
13702 /* data_length The length of data */
13703 /* buffer Pointer to decoded data */
13704 /* size Size of data buffer to decode */
13705 /* */
13706 /* OUTPUT */
13707 /* */
13708 /* status Completion status */
13709 /* */
13710 /* CALLS */
13711 /* */
13712 /* None */
13713 /* */
13714 /* CALLED BY */
13715 /* */
13716 /* _nx_mdns_packet_process Process mDNS packet */
13717 /* _nx_mdns_packet_rr_process Process resource record */
13718 /* */
13719 /* RELEASE HISTORY */
13720 /* */
13721 /* DATE NAME DESCRIPTION */
13722 /* */
13723 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13724 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13725 /* resulting in version 6.1 */
13726 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
13727 /* buffer length verification, */
13728 /* resulting in version 6.1.3 */
13729 /* */
13730 /**************************************************************************/
_nx_mdns_txt_string_decode(UCHAR * data,UINT data_length,UCHAR * buffer,UINT size)13731 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size)
13732 {
13733
13734
13735 /* Check the buffer size. */
13736 if (data_length >= size)
13737 {
13738 return (NX_MDNS_CACHE_ERROR);
13739 }
13740
13741 /* decode the data. */
13742 while (data_length)
13743 {
13744
13745 UINT labelSize = *data++;
13746
13747 /* Is this a compression pointer or a count. */
13748 if (labelSize <= NX_MDNS_LABEL_MAX)
13749 {
13750
13751 /* Simple count, check for space and copy the label. */
13752 while ((labelSize > 0) && (data_length > 1))
13753 {
13754
13755 *buffer++ = *data++;
13756 labelSize--;
13757 data_length--;
13758 }
13759
13760 /* Now add the ';' */
13761 *buffer++ = ';';
13762 data_length--;
13763 }
13764 else
13765 {
13766 return(NX_MDNS_EXCEED_MAX_LABEL);
13767 }
13768 }
13769
13770 /* Done copying the data, set the last . to a trailing null */
13771 if (*(buffer - 1) == ';')
13772 {
13773
13774 buffer--;
13775 }
13776
13777 /* Null terminate name. */
13778 *buffer = '\0';
13779
13780 /* Return name size. */
13781 return(NX_MDNS_SUCCESS);
13782 }
13783
13784
13785 /**************************************************************************/
13786 /* */
13787 /* FUNCTION RELEASE */
13788 /* */
13789 /* _nx_mdns_name_size_calculate PORTABLE C */
13790 /* 6.1.4 */
13791 /* AUTHOR */
13792 /* */
13793 /* Yuxin Zhou, Microsoft Corporation */
13794 /* */
13795 /* DESCRIPTION */
13796 /* */
13797 /* This function calculates the size of the name. */
13798 /* */
13799 /* INPUT */
13800 /* */
13801 /* name Pointer to the name */
13802 /* packet_ptr Pointer to received packet */
13803 /* */
13804 /* OUTPUT */
13805 /* */
13806 /* UINT Size of name */
13807 /* */
13808 /* CALLS */
13809 /* */
13810 /* None */
13811 /* */
13812 /* CALLED BY */
13813 /* */
13814 /* */
13815 /* RELEASE HISTORY */
13816 /* */
13817 /* DATE NAME DESCRIPTION */
13818 /* */
13819 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13820 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13821 /* resulting in version 6.1 */
13822 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
13823 /* packet length verification, */
13824 /* resulting in version 6.1.4 */
13825 /* */
13826 /**************************************************************************/
_nx_mdns_name_size_calculate(UCHAR * name,NX_PACKET * packet_ptr)13827 static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr)
13828 {
13829
13830 UINT size = 0;
13831
13832
13833 /* As long as we haven't found a zero length terminating label */
13834 while (*name != '\0')
13835 {
13836
13837 UINT labelSize = *name++;
13838
13839 /* Is this a compression pointer or a count. */
13840 if (labelSize <= NX_MDNS_LABEL_MAX)
13841 {
13842
13843 if (name + labelSize >= packet_ptr -> nx_packet_append_ptr)
13844 {
13845
13846 /* If name buffer is OOB, just fail. */
13847 return(0);
13848 }
13849
13850 /* Simple count, adjust size and skip the label. */
13851 size += labelSize + 1;
13852 name += labelSize;
13853 }
13854 else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
13855 {
13856
13857 /* This is a pointer size is 2 bytes and this is the end of this name */
13858 return(size + 2);
13859 }
13860 else
13861 {
13862
13863 /* Not defined, just fail */
13864 return(0);
13865 }
13866 }
13867
13868 /* Adjust size for the final NULL. */
13869 return(size + 1);
13870 }
13871
13872
13873 /**************************************************************************/
13874 /* */
13875 /* FUNCTION RELEASE */
13876 /* */
13877 /* _nx_mdns_name_string_encode PORTABLE C */
13878 /* 6.1 */
13879 /* AUTHOR */
13880 /* */
13881 /* Yuxin Zhou, Microsoft Corporation */
13882 /* */
13883 /* DESCRIPTION */
13884 /* */
13885 /* This function converts a string containing the name as a list of */
13886 /* labels separated by dots to the encoded list of labels specified */
13887 /* in RFC1035 for DNS servers. This conversion doesn't handle */
13888 /* compression and doesn't check on the lengths of the labels or the */
13889 /* entire name. */
13890 /* */
13891 /* INPUT */
13892 /* */
13893 /* ptr Pointer to destination */
13894 /* name Source name string */
13895 /* */
13896 /* OUTPUT */
13897 /* */
13898 /* count Count of characters encoded */
13899 /* */
13900 /* CALLS */
13901 /* */
13902 /* None */
13903 /* */
13904 /* CALLED BY */
13905 /* */
13906 /* */
13907 /* RELEASE HISTORY */
13908 /* */
13909 /* DATE NAME DESCRIPTION */
13910 /* */
13911 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13912 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13913 /* resulting in version 6.1 */
13914 /* */
13915 /**************************************************************************/
_nx_mdns_name_string_encode(UCHAR * ptr,UCHAR * name)13916 static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name)
13917 {
13918
13919 UCHAR *length;
13920 UINT count = 1;
13921
13922
13923 /* Point to the first character position in the buffer. This will point
13924 to the length of the following name. */
13925 length = ptr++;
13926
13927 /* Default the length to zero. */
13928 *length = 0;
13929
13930 /* Move through string, copying bytes and updating length.
13931 Whenever a "." is found, start a new string by updating the
13932 pointer to the length and setting the length to zero. */
13933 while (*name)
13934 {
13935
13936 /* Is a dot been found? */
13937 if (*name == '.')
13938 {
13939
13940 /* Yes, setup a new length pointer. */
13941 length = ptr++;
13942
13943 /* Default the length to zero. */
13944 *length = 0;
13945 name++;
13946 }
13947 else
13948 {
13949
13950 /* Copy a character to the destination. */
13951 *ptr++ = *name++;
13952
13953 /* Adjust the length of the current segment. */
13954 (*length)++;
13955 }
13956
13957 /* Increment the total count here. */
13958 count++;
13959 }
13960
13961 /* Add the final zero length, like a NULL terminator. */
13962 *ptr = 0;
13963
13964 /* Increment the total count. */
13965 count++;
13966
13967 /* Return the count. */
13968 return(count);
13969 }
13970
13971
13972 /**************************************************************************/
13973 /* */
13974 /* FUNCTION RELEASE */
13975 /* */
13976 /* _nx_mdns_name_string_decode PORTABLE C */
13977 /* 6.1.4 */
13978 /* AUTHOR */
13979 /* */
13980 /* Yuxin Zhou, Microsoft Corporation */
13981 /* */
13982 /* DESCRIPTION */
13983 /* */
13984 /* This function converts from the encoded list of labels as specified */
13985 /* in RFC 1035 to a string containing the name as a list of labels */
13986 /* separated by dots. */
13987 /* */
13988 /* INPUT */
13989 /* */
13990 /* data Pointer to buffer to decode */
13991 /* start Location of start of data */
13992 /* data_length Length of data buffer */
13993 /* buffer Pointer to decoded data */
13994 /* size Size of data buffer to decode */
13995 /* */
13996 /* OUTPUT */
13997 /* */
13998 /* Size of decoded data */
13999 /* */
14000 /* CALLS */
14001 /* */
14002 /* None */
14003 /* */
14004 /* CALLED BY */
14005 /* */
14006 /* */
14007 /* RELEASE HISTORY */
14008 /* */
14009 /* DATE NAME DESCRIPTION */
14010 /* */
14011 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14012 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14013 /* resulting in version 6.1 */
14014 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
14015 /* buffer length verification, */
14016 /* prevented infinite loop in */
14017 /* name compression, */
14018 /* resulting in version 6.1.3 */
14019 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
14020 /* packet length verification, */
14021 /* resulting in version 6.1.4 */
14022 /* */
14023 /**************************************************************************/
_nx_mdns_name_string_decode(UCHAR * data,UINT start,UINT data_length,UCHAR * buffer,UINT size)14024 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size)
14025 {
14026
14027 UCHAR *character = data + start;
14028 UINT length = 0;
14029 UINT offset;
14030 UINT pointer_count = 0;
14031 UINT labelSize;
14032
14033
14034 /* As long as there is space in the buffer and we haven't
14035 found a zero terminating label */
14036 while (1)
14037 {
14038
14039 if (character >= data + data_length)
14040 {
14041 return(0);
14042 }
14043
14044 if ((size <= length) || (*character == '\0'))
14045 {
14046 break;
14047 }
14048
14049 labelSize = *character++;
14050
14051 /* Is this a compression pointer or a count. */
14052 if (labelSize <= NX_MDNS_LABEL_MAX)
14053 {
14054
14055 /* Simple count, check for space and copy the label. */
14056 while ((size > length) && (labelSize > 0))
14057 {
14058 if (character >= data + data_length)
14059 {
14060 return(0);
14061 }
14062
14063 *buffer++ = *character++;
14064 length++;
14065 labelSize--;
14066 }
14067
14068 /* Now add the '.' */
14069 *buffer++ = '.';
14070 length++;
14071 }
14072 else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
14073 {
14074
14075 if (character >= data + data_length)
14076 {
14077 return(0);
14078 }
14079
14080 /* This is a pointer, just adjust the source. */
14081 offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
14082
14083 /* Make sure offset is in the buffer. */
14084 if (offset >= data_length)
14085 {
14086 return(0);
14087 }
14088
14089 /* Pointer must not point back to itself. */
14090 if ((data + offset == character) || (data + offset == character - 1))
14091 {
14092 return(0);
14093 }
14094
14095 /* Prevent infinite loop with compression pointers. */
14096 pointer_count++;
14097 if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS)
14098 {
14099 return(0);
14100 }
14101
14102 character = data + offset;
14103 }
14104 else
14105 {
14106
14107 /* Not defined, just fail */
14108 return(0);
14109 }
14110 }
14111
14112 /* Done copying the data, set the last . to a trailing null */
14113 if ((length > 0) && (*(buffer - 1) == '.'))
14114 {
14115
14116 buffer--;
14117 length --;
14118 }
14119
14120 /* Null terminate name. */
14121 *buffer = '\0';
14122
14123 /* Return name size. */
14124 return(length);
14125 }
14126
14127
14128 /**************************************************************************/
14129 /* */
14130 /* FUNCTION RELEASE */
14131 /* */
14132 /* _nx_mdns_rr_size_get PORTABLE C */
14133 /* 6.1.4 */
14134 /* AUTHOR */
14135 /* */
14136 /* Yuxin Zhou, Microsoft Corporation */
14137 /* */
14138 /* DESCRIPTION */
14139 /* */
14140 /* This function gets the size of resource record. */
14141 /* */
14142 /* INPUT */
14143 /* */
14144 /* resource Pointer to the resource */
14145 /* packet_ptr Pointer to received packet */
14146 /* */
14147 /* OUTPUT */
14148 /* */
14149 /* size of data */
14150 /* */
14151 /* CALLS */
14152 /* */
14153 /* */
14154 /* CALLED BY */
14155 /* */
14156 /* */
14157 /* RELEASE HISTORY */
14158 /* */
14159 /* DATE NAME DESCRIPTION */
14160 /* */
14161 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14162 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14163 /* resulting in version 6.1 */
14164 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
14165 /* packet length verification, */
14166 /* resulting in version 6.1.4 */
14167 /* */
14168 /**************************************************************************/
_nx_mdns_rr_size_get(UCHAR * resource,NX_PACKET * packet_ptr)14169 static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr)
14170 {
14171
14172 UINT name_size;
14173 UINT data_size;
14174
14175 /* Resource size is
14176 name size + data size + 2 bytes for type, 2 for class, 4 for time to live and 2 for data length
14177 i.e. name size + data size + 10 bytes overhead.
14178 */
14179 name_size = _nx_mdns_name_size_calculate(resource, packet_ptr);
14180
14181 if (resource + name_size + 8 + 2 > packet_ptr -> nx_packet_append_ptr)
14182 {
14183 return(0);
14184 }
14185 data_size = NX_MDNS_GET_USHORT_DATA(resource + name_size + 8);
14186
14187 /* Return resource size. */
14188 return(name_size + data_size + 10);
14189 }
14190
14191
14192 /**************************************************************************/
14193 /* */
14194 /* FUNCTION RELEASE */
14195 /* */
14196 /* _nx_mdns_short_to_network_convert PORTABLE C */
14197 /* 6.1 */
14198 /* AUTHOR */
14199 /* */
14200 /* Yuxin Zhou, Microsoft Corporation */
14201 /* */
14202 /* DESCRIPTION */
14203 /* */
14204 /* This function converts an unsigned short to network byte order, */
14205 /* which is big endian. */
14206 /* */
14207 /* INPUT */
14208 /* */
14209 /* ptr Pointer to the destination */
14210 /* value Source value */
14211 /* */
14212 /* OUTPUT */
14213 /* */
14214 /* None */
14215 /* */
14216 /* CALLS */
14217 /* */
14218 /* None */
14219 /* */
14220 /* CALLED BY */
14221 /* */
14222 /* DNS component */
14223 /* */
14224 /* RELEASE HISTORY */
14225 /* */
14226 /* DATE NAME DESCRIPTION */
14227 /* */
14228 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14229 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14230 /* resulting in version 6.1 */
14231 /* */
14232 /**************************************************************************/
_nx_mdns_short_to_network_convert(UCHAR * ptr,USHORT value)14233 static void _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value)
14234 {
14235
14236 *ptr++ = (UCHAR)(value >> 8);
14237 *ptr = (UCHAR)value;
14238 }
14239
14240
14241 /**************************************************************************/
14242 /* */
14243 /* FUNCTION RELEASE */
14244 /* */
14245 /* _nx_mdns_long_to_network_convert PORTABLE C */
14246 /* 6.1 */
14247 /* AUTHOR */
14248 /* */
14249 /* Yuxin Zhou, Microsoft Corporation */
14250 /* */
14251 /* DESCRIPTION */
14252 /* */
14253 /* This function converts an unsigned long to network format, which */
14254 /* big endian. */
14255 /* */
14256 /* INPUT */
14257 /* */
14258 /* ptr Pointer to the destination */
14259 /* value Source value */
14260 /* */
14261 /* OUTPUT */
14262 /* */
14263 /* None */
14264 /* */
14265 /* CALLS */
14266 /* */
14267 /* None */
14268 /* */
14269 /* CALLED BY */
14270 /* */
14271 /* DNS component */
14272 /* */
14273 /* RELEASE HISTORY */
14274 /* */
14275 /* DATE NAME DESCRIPTION */
14276 /* */
14277 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14278 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14279 /* resulting in version 6.1 */
14280 /* */
14281 /**************************************************************************/
_nx_mdns_long_to_network_convert(UCHAR * ptr,ULONG value)14282 static void _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value)
14283 {
14284
14285 *ptr++ = (UCHAR)(value >> 24);
14286 *ptr++ = (UCHAR)(value >> 16);
14287 *ptr++ = (UCHAR)(value >> 8);
14288 *ptr = (UCHAR)value;
14289 }
14290