1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** Multicast Domain Name System (mDNS) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 #define NX_MDNS_SOURCE_CODE
25
26
27 /* Force error checking to be disabled in this module */
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif /* NX_DISABLE_ERROR_CHECKING */
31
32
33 /* Include necessary system files. */
34 #include "nxd_mdns.h"
35 #include "tx_thread.h"
36
37 /* Define the application protocol. */
38 static CHAR *nx_mdns_app_protocol[]= {"_tcp", "_udp", NX_NULL};
39
40 /* Define the service type. */
41 #ifndef NX_MDNS_DISABLE_CLIENT
42 static CHAR *nx_mdns_service_types[] =
43 {
44 "_device-info",
45 "_http",
46 "_https",
47 "_guid",
48 "_h323",
49 "_ntp",
50 "_objective",
51 "_rdp",
52 "_remote",
53 "_rtsp",
54 "_sip",
55 "_smb",
56 "_soap",
57 "_ssh",
58 "_telnet",
59 "_tftp",
60 "_xmpp-client",
61 NX_NULL
62 };
63 #endif /* NX_MDNS_DISABLE_CLIENT */
64
65
66 /* Define the mDNS internal Function. */
67 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
68 static VOID _nx_mdns_timer_entry(ULONG mdns_value);
69 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr, ULONG timer_count);
70 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr);
71 static VOID _nx_mdns_thread_entry(ULONG mdns_value);
72 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
73 static UINT _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR type);
74 static VOID _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
75 static UINT _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type);
76 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);
77 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);
78 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
79 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr);
80 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
81 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);
82 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain);
83 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
84 static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr);
85 static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length);
86 static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr);
87 static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name);
88 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size);
89 static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name);
90 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size);
91 static VOID _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value);
92 static VOID _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value);
93
94 #ifndef NX_MDNS_DISABLE_SERVER
95 static VOID _nx_mdns_address_change_process(NX_MDNS *mdns_ptr);
96 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index);
97 static UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index);
98 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
99 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index);
100 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
101 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);
102 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);
103 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);
104
105 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
106 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index);
107 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
108
109 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);
110 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
111 static UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
112 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index);
113 static VOID _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index);
114 static VOID _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index);
115 static VOID _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index);
116 #ifndef NX_DISABLE_IPV4
117 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info);
118 #endif /* NX_DISABLE_IPV4 */
119 #ifdef NX_MDNS_ENABLE_IPV6
120 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address);
121 #endif /* NX_MDNS_ENABLE_IPV6 */
122 #endif /* NX_MDNS_DISABLE_SERVER */
123
124 #ifndef NX_MDNS_DISABLE_CLIENT
125 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present);
126 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index);
127 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask);
128 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);
129 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index);
130 static VOID _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index);
131 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);
132 static VOID _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER);
133 static VOID _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
134 NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option);
135 static VOID _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr);
136 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
137 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index);
138 #endif /* NX_MDNS_DISABLE_CLIENT */
139
140 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);
141 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);
142 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr);
143 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);
144 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);
145 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len);
146 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr);
147
148
149 /* Define the mDNS STRUCT. */
150 static struct NX_MDNS_STRUCT *_nx_mdns_created_ptr;
151 static CHAR _nx_mdns_dns_sd[NX_MDNS_DNS_SD_MAX + 1] = "_services._dns-sd._udp.local";
152 static UCHAR temp_string_buffer[NX_MDNS_NAME_MAX + 1];
153 static UCHAR target_string_buffer[NX_MDNS_NAME_MAX + 1];
154
155 #ifdef NX_MDNS_ENABLE_IPV6
156 static NXD_ADDRESS NX_MDNS_IPV6_MULTICAST_ADDRESS;
157 #endif /* NX_MDNS_ENABLE_IPV6 */
158
159 /**************************************************************************/
160 /* */
161 /* FUNCTION RELEASE */
162 /* */
163 /* _nxe_mdns_create PORTABLE C */
164 /* 6.1 */
165 /* AUTHOR */
166 /* */
167 /* Yuxin Zhou, Microsoft Corporation */
168 /* */
169 /* DESCRIPTION */
170 /* */
171 /* This function checks for errors in the mDNS create function call */
172 /* */
173 /* Note: the name string is generated by internal logic and it is */
174 /* always NULL-terminated. */
175 /* */
176 /* INPUT */
177 /* */
178 /* mdns_ptr Pointer to mDNS instance */
179 /* ip_ptr Pointer to IP instance */
180 /* priority The priority of mDNS Thread */
181 /* stack_ptr Stack pointer for mDNS Thread */
182 /* stack_size Stack size for mDNS Thread */
183 /* host_name Pointer to host name */
184 /* local_cache_ptr Pointer to local cache */
185 /* local_cache_size The size of local cache */
186 /* peer_cache_ptr Pointer to peer cache */
187 /* peer_cache_size The size of peer cache */
188 /* probing_notify mDNS probing notify */
189 /* */
190 /* OUTPUT */
191 /* */
192 /* status Completion status */
193 /* */
194 /* CALLS */
195 /* */
196 /* _nx_mdns_create Actual mDNS create function */
197 /* */
198 /* CALLED BY */
199 /* */
200 /* Application Code */
201 /* */
202 /* RELEASE HISTORY */
203 /* */
204 /* DATE NAME DESCRIPTION */
205 /* */
206 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
207 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
208 /* resulting in version 6.1 */
209 /* */
210 /**************************************************************************/
_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))211 UINT _nxe_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
212 UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
213 VOID *local_cache_ptr, UINT local_cache_size,
214 VOID *peer_cache_ptr, UINT peer_cache_size,
215 VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
216 {
217
218 UINT status;
219 UCHAR *ptr;
220
221
222 /* Check for invalid input pointers. */
223 if ((!ip_ptr) || (!mdns_ptr) || (!stack_ptr) || (!packet_pool) || (!host_name))
224 {
225 return(NX_PTR_ERROR);
226 }
227
228 /* Check for invalid non pointer input. */
229 if ((ip_ptr -> nx_ip_id != NX_IP_ID) ||
230 (stack_size < TX_MINIMUM_STACK) ||
231 (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
232 {
233 return(NX_MDNS_PARAM_ERROR);
234 }
235
236 /* Check the host name format, RFC 1033,1034,1035 recomend that host names contain only letters, digits, and hyphens RFC6763, Appendix E, Page44. */
237 ptr = host_name;
238 while (*ptr != '\0')
239 {
240 if (((*ptr >= 'a') && (*ptr <= 'z')) ||
241 ((*ptr >= 'A') && (*ptr <= 'Z')) ||
242 ((*ptr >= '0') && (*ptr <= '9')) ||
243 ((*ptr == '-')))
244 ptr++;
245 else
246 return(NX_MDNS_HOST_NAME_ERROR);
247 }
248
249 /* Check the default domain name size. */
250 if ((sizeof("local") - 1) > NX_MDNS_DOMAIN_NAME_MAX)
251 {
252 return(NX_MDNS_DATA_SIZE_ERROR);
253 }
254
255 #ifndef NX_MDNS_DISABLE_SERVER
256
257 /* Check for invalid input pointers, cache header and tail (8 bytes). */
258 if ((!local_cache_ptr) || (local_cache_size < 8))
259 {
260 return(NX_PTR_ERROR);
261 }
262
263 /* Make sure record_buffer is 4-byte aligned. */
264 if ((((UINT)local_cache_ptr & 0x3) != 0) ||
265 ((local_cache_size & 0x3) != 0))
266 {
267 return(NX_MDNS_CACHE_ERROR);
268 }
269 #endif /* NX_MDNS_DISABLE_SERVER */
270
271 #ifndef NX_MDNS_DISABLE_CLIENT
272
273 /* Check for invalid input pointers, cache header and tail (8 bytes). */
274 if ((!peer_cache_ptr) || (peer_cache_size < 8))
275 {
276 return(NX_PTR_ERROR);
277 }
278
279 /* Make sure peer cache is 4-byte aligned. */
280 if ((((UINT)peer_cache_ptr & 0x3) != 0) ||
281 ((peer_cache_size & 0x3) != 0))
282 {
283 return(NX_MDNS_CACHE_ERROR);
284 }
285 #endif /* NX_MDNS_DISABLE_CLIENT */
286
287 /* Call actual mDNS create service. */
288 status = _nx_mdns_create(mdns_ptr, ip_ptr, packet_pool, priority,
289 stack_ptr, stack_size, host_name,
290 local_cache_ptr, local_cache_size,
291 peer_cache_ptr, peer_cache_size,
292 probing_notify);
293
294 /* Return status. */
295 return(status);
296 }
297
298
299 /**************************************************************************/
300 /* */
301 /* FUNCTION RELEASE */
302 /* */
303 /* _nx_mdns_create PORTABLE C */
304 /* 6.1.11 */
305 /* AUTHOR */
306 /* */
307 /* Yuxin Zhou, Microsoft Corporation */
308 /* */
309 /* DESCRIPTION */
310 /* */
311 /* This function initializes the mDNS structure and associated IP */
312 /* instance for mDNS operation. In doing so, it creates a UDP socket */
313 /* for communication with the server and a mDNS processing thread */
314 /* */
315 /* Note: the name string is generated by internal logic and it is */
316 /* always NULL-terminated. */
317 /* */
318 /* INPUT */
319 /* */
320 /* mdns_ptr Pointer to mDNS instance */
321 /* ip_ptr Pointer to IP instance */
322 /* priority The priority of mDNS Thread */
323 /* stack_ptr Stack pointer for mDNS Thread */
324 /* stack_size Stack size for mDNS Thread */
325 /* host_name Pointer to host name */
326 /* local_cache_ptr Pointer to local cache */
327 /* local_cache_size The size of local cache */
328 /* peer_cache_ptr Pointer to peer cache */
329 /* peer_cache_size The size of peer cache */
330 /* probing_notify mDNS probing notify */
331 /* */
332 /* OUTPUT */
333 /* */
334 /* status Completion status */
335 /* */
336 /* CALLS */
337 /* */
338 /* nx_udp_socket_create Create the mDNS UDP socket */
339 /* nx_udp_socket_delete Delete the mDNS UDP socket */
340 /* nx_udp_socket_bind Bind the mDNS UDP socket */
341 /* nx_udp_socket_unbind Unbind the mDNS UDP socket */
342 /* nx_udp_socket_receive_notify Register the mDNS function */
343 /* nx_ip_address_change_notify Register IPv4 address function*/
344 /* nxd_ipv6_address_change_notify Register IPv6 address function*/
345 /* tx_mutex_create Create the mDNS mutex */
346 /* tx_mutex_delete Delete the mDNS mutex */
347 /* tx_thread_create Create the mDNS thread */
348 /* tx_thread_delete Delete the mDNS thread */
349 /* tx_event_flags_create Create the ThreadX flag event */
350 /* _nx_mdns_cache_initialize Initialize the mDNS cache */
351 /* */
352 /* CALLED BY */
353 /* */
354 /* Application Code */
355 /* */
356 /* RELEASE HISTORY */
357 /* */
358 /* DATE NAME DESCRIPTION */
359 /* */
360 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
361 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
362 /* verified memcpy use cases, */
363 /* resulting in version 6.1 */
364 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
365 /* corrected the random value, */
366 /* used internal ip address */
367 /* change notification, */
368 /* resulting in version 6.1.11 */
369 /* */
370 /**************************************************************************/
_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))371 UINT _nx_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
372 UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
373 VOID *local_cache_ptr, UINT local_cache_size,
374 VOID *peer_cache_ptr, UINT peer_cache_size,
375 VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
376 {
377
378 UINT status;
379 UINT host_name_size;
380
381
382 /* Check the size of the host name string. The last four characters in the
383 host_name are reserved so DNS-SD is able to append " (2)" during the conflict
384 resolution process. */
385 #if (NX_MDNS_HOST_NAME_MAX >= NX_MDNS_LABEL_MAX)
386 if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_LABEL_MAX - 4)))
387 #else
388 if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_HOST_NAME_MAX - 4)))
389 #endif
390 {
391 return(NX_MDNS_DATA_SIZE_ERROR);
392 }
393
394 /* Initialize the mDNS control block to zero. */
395 memset((void *) mdns_ptr, 0, sizeof(NX_MDNS));
396
397 #ifdef NX_MDNS_ENABLE_IPV6
398
399 /* Initialize the IPv6 Multicast address. */
400 memset(&NX_MDNS_IPV6_MULTICAST_ADDRESS, 0, sizeof(NXD_ADDRESS));
401 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_version = NX_IP_VERSION_V6;
402 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0] = 0xFF020000;
403 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1] = 0x00000000;
404 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2] = 0x00000000;
405 NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3] = 0x000000FB;
406 #endif /* NX_MDNS_ENABLE_IPV6 */
407
408 /* Save the IP pointer. */
409 mdns_ptr -> nx_mdns_ip_ptr = ip_ptr;
410
411 /* Save the Packet pool. */
412 mdns_ptr -> nx_mdns_packet_pool_ptr = packet_pool;
413
414 /* Save the host name. */
415 memcpy((char*)mdns_ptr -> nx_mdns_host_name, (const char*)host_name, (host_name_size + 1)); /* Use case of memcpy is verified. */
416
417 /* Set the domain name as "local" by default. */
418 memcpy((char*)mdns_ptr -> nx_mdns_domain_name, "local", sizeof("local")); /* Use case of memcpy is verified. */
419
420 /* Assign the resource record change notify. */
421 mdns_ptr -> nx_mdns_probing_notify = probing_notify;
422
423 /* Set the mDNS announcing period. */
424 mdns_ptr -> nx_mdns_announcing_period = (USHORT)NX_MDNS_ANNOUNCING_PERIOD;
425
426 /* Set the mDNS announcing retransmission interval. */
427 mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)NX_MDNS_ANNOUNCING_RETRANS_INTERVAL;
428
429 /* Set the mDNS announcing period interval. */
430 mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)NX_MDNS_ANNOUNCING_PERIOD_INTERVAL;
431
432 /* Set the mDNS announcing count between one announcing period. */
433 mdns_ptr -> nx_mdns_announcing_count = (UCHAR)NX_MDNS_ANNOUNCING_COUNT;
434
435 /* Set the mDNS announcing factor. */
436 mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)NX_MDNS_ANNOUNCING_FACTOR;
437
438 /* Set the mDNS announcing max time. */
439 mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)NX_MDNS_ANNOUNCING_MAX_TIME;
440
441 /* Set the pointer of global variable mDNS. */
442 _nx_mdns_created_ptr = mdns_ptr;
443
444 #ifndef NX_MDNS_DISABLE_SERVER
445
446 #ifndef NX_DISABLE_IPV4
447 /* Setup the IP address change callback function. */
448 ip_ptr -> nx_ip_address_change_notify_internal = _nx_mdns_ip_address_change_notify;
449 #endif /* NX_DISABLE_IPV4 */
450
451 #ifdef NX_MDNS_ENABLE_IPV6
452
453 /* Setup the IPv6 address change callback function. */
454 ip_ptr -> nx_ipv6_address_change_notify_internal = _nx_mdns_ipv6_address_change_notify;
455 #endif /* NX_MDNS_ENABLE_IPV6 */
456 #endif /* NX_MDNS_DISABLE_SERVER */
457
458 /* Create the Socket and check the status */
459 status = nx_udp_socket_create(mdns_ptr -> nx_mdns_ip_ptr, &(mdns_ptr -> nx_mdns_socket), "Multicast DNS",
460 NX_MDNS_UDP_TYPE_OF_SERVICE, NX_MDNS_UDP_FRAGMENT_OPTION,
461 NX_MDNS_UDP_TIME_TO_LIVE, NX_MDNS_UDP_QUEUE_DEPTH);
462
463 /* Determine if it was successful. */
464 if (status != NX_SUCCESS)
465 {
466 return(status);
467 }
468
469 /* Bind the UDP socket to the mDNS port. */
470 status = nx_udp_socket_bind(&(mdns_ptr -> nx_mdns_socket), NX_MDNS_UDP_PORT, TX_NO_WAIT);
471
472 /* Check for error */
473 if (status)
474 {
475
476 /* Delete the UDP socket. */
477 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
478 return(status);
479 }
480
481 /* Register UDP receive callback. */
482 status = nx_udp_socket_receive_notify(&(mdns_ptr -> nx_mdns_socket), _nx_mdns_udp_receive_notify);
483
484 /* Check for error */
485 if (status)
486 {
487
488 /* Delete the UDP socket. */
489 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
490 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
491 return(status);
492 }
493
494 /* Create the mDNS mutex. */
495 status = tx_mutex_create(&(mdns_ptr -> nx_mdns_mutex),
496 "mDNS Mutex", TX_NO_INHERIT);
497
498 /* Determine if the semaphore creation was successful. */
499 if (status != NX_SUCCESS)
500 {
501
502 /* Delete the UDP socket. */
503 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
504 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
505
506 /* No, return error status. */
507 return(status);
508 }
509
510 /* Create the internal mDNS event flag object. */
511 status = tx_event_flags_create(&mdns_ptr -> nx_mdns_events, "mDNS Thread Events");
512
513 /* Determine if the event flags creation was successful. */
514 if (status)
515 {
516
517 /* Delete the UDP socket. */
518 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
519 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
520
521 /* Delete the mDNS mutex. */
522 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
523
524 /* No, return error status. */
525 return(status);
526 }
527
528 /* Create the mDNS processing thread. */
529 status = tx_thread_create(&(mdns_ptr -> nx_mdns_thread), "mDNS Thread",
530 _nx_mdns_thread_entry, (ULONG) mdns_ptr,
531 stack_ptr, stack_size, priority, priority,
532 1, TX_AUTO_START);
533
534 /* Determine if the thread creation was successful. */
535 if (status != NX_SUCCESS)
536 {
537
538 /* Delete the UDP socket. */
539 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
540 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
541
542 /* Delete the mDNS mutex. */
543 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
544
545 /* Delete the mDNS events. */
546 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
547
548 /* No, return error status. */
549 return(status);
550 }
551
552 /* Create the timer of Resource record lifetime. */
553 status = tx_timer_create(&(mdns_ptr -> nx_mdns_timer), "mDNS Timer",
554 _nx_mdns_timer_entry, (ULONG) mdns_ptr,
555 0xFFFFFFFF, 0, TX_NO_ACTIVATE);
556
557 /* Determine if the thread creation was successful. */
558 if (status != NX_SUCCESS)
559 {
560
561 /* Delete the UDP socket. */
562 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
563 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
564
565 /* Delete the mDNS mutex. */
566 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
567
568 /* Delete the mDNS events. */
569 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
570
571 /* Delete the mDNS thread. */
572 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
573
574 /* No, return error status. */
575 return(status);
576 }
577
578 /* Initialize the buffer. */
579 status = _nx_mdns_cache_initialize(mdns_ptr, local_cache_ptr, local_cache_size,
580 peer_cache_ptr, peer_cache_size);
581
582 /* Determine if the buffer initialize was successful. */
583 if (status != NX_SUCCESS)
584 {
585
586 /* Delete the UDP socket. */
587 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
588 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
589
590 /* Delete the mDNS timer. */
591 tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
592
593 /* Delete the mDNS mutex. */
594 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
595
596 /* Delete the mDNS events. */
597 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
598
599 /* Delete the mDNS thread. */
600 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
601
602 /* No, return error status. */
603 return(status);
604 }
605
606 /* Update the mDNS structure ID. */
607 mdns_ptr -> nx_mdns_id = NX_MDNS_ID;
608
609 /* The random delay of first probing for RR. */
610 mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (((ULONG)NX_RAND()) % NX_MDNS_PROBING_TIMER_COUNT));
611
612 /* Return a successful status. */
613 return(NX_SUCCESS);
614 }
615
616
617 /**************************************************************************/
618 /* */
619 /* FUNCTION RELEASE */
620 /* */
621 /* _nxe_mdns_delete PORTABLE C */
622 /* 6.1 */
623 /* AUTHOR */
624 /* */
625 /* Yuxin Zhou, Microsoft Corporation */
626 /* */
627 /* DESCRIPTION */
628 /* */
629 /* This function checks for errors in the mDNS delete function call. */
630 /* */
631 /* INPUT */
632 /* */
633 /* mdns_ptr Pointer to mDNS instance */
634 /* */
635 /* OUTPUT */
636 /* */
637 /* status Completion status */
638 /* */
639 /* CALLS */
640 /* */
641 /* _nx_mdns_delete Actual mDNS delete function */
642 /* */
643 /* CALLED BY */
644 /* */
645 /* Application Code */
646 /* */
647 /* RELEASE HISTORY */
648 /* */
649 /* DATE NAME DESCRIPTION */
650 /* */
651 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
652 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
653 /* resulting in version 6.1 */
654 /* */
655 /**************************************************************************/
_nxe_mdns_delete(NX_MDNS * mdns_ptr)656 UINT _nxe_mdns_delete(NX_MDNS *mdns_ptr)
657 {
658
659 UINT status;
660
661
662 /* Check for invalid input pointers. */
663 if (!mdns_ptr)
664 {
665 return(NX_PTR_ERROR);
666 }
667
668 /* Check for invalid server attributes. */
669 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
670 {
671 return(NX_MDNS_PARAM_ERROR);
672 }
673
674 /* Call actual mDNS delete service. */
675 status = _nx_mdns_delete(mdns_ptr);
676
677 /* Return status. */
678 return(status);
679 }
680
681
682 /**************************************************************************/
683 /* */
684 /* FUNCTION RELEASE */
685 /* */
686 /* _nx_mdns_delete PORTABLE C */
687 /* 6.1 */
688 /* AUTHOR */
689 /* */
690 /* Yuxin Zhou, Microsoft Corporation */
691 /* */
692 /* DESCRIPTION */
693 /* */
694 /* This function deletes the mDNS instance. */
695 /* */
696 /* INPUT */
697 /* */
698 /* mdns_ptr Pointer to mDNS instance */
699 /* */
700 /* OUTPUT */
701 /* */
702 /* status Completion status */
703 /* */
704 /* CALLS */
705 /* */
706 /* nx_udp_socket_unbind Unbind the mDNS UDP socket */
707 /* nx_udp_socket_delete Delete the mDNS UDP socket */
708 /* tx_mutex_get Get the mDNS mutex */
709 /* tx_mutex_put Put the mDNS mutex */
710 /* tx_mutex_delete Delete the mDNS mutex */
711 /* tx_thread_terminate Terminate the mDNS thread */
712 /* tx_thread_delete Delete the mDNS thread */
713 /* tx_event_flags_delete Delete the mDNS events flag */
714 /* */
715 /* CALLED BY */
716 /* */
717 /* Application Code */
718 /* */
719 /* RELEASE HISTORY */
720 /* */
721 /* DATE NAME DESCRIPTION */
722 /* */
723 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
724 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
725 /* resulting in version 6.1 */
726 /* */
727 /**************************************************************************/
_nx_mdns_delete(NX_MDNS * mdns_ptr)728 UINT _nx_mdns_delete(NX_MDNS *mdns_ptr)
729 {
730
731
732 /* Get the mDNS mutex. */
733 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
734
735 /* Clear the mDNS structure ID. */
736 mdns_ptr -> nx_mdns_id = 0;
737
738 /* Set the pointer of global variable mDNS. */
739 _nx_mdns_created_ptr = NX_NULL;
740
741 /* Unbind the port. */
742 nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
743
744 /* Delete the UDP socket. */
745 nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
746
747 /* Terminate the mDNS processing thread. */
748 tx_thread_terminate(&(mdns_ptr -> nx_mdns_thread));
749
750 /* Delete the mDNS processing thread. */
751 tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
752
753 /* Delete the event flags. */
754 tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
755
756 /* Delete the timer. */
757 tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
758
759 /* Release the mDNS mutex. */
760 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
761
762 /* Delete the mDNS mutex. */
763 tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
764
765 /* Return a successful status. */
766 return(NX_SUCCESS);
767 }
768
769
770 /**************************************************************************/
771 /* */
772 /* FUNCTION RELEASE */
773 /* */
774 /* _nxe_mdns_cache_notify_set PORTABLE C */
775 /* 6.1 */
776 /* AUTHOR */
777 /* */
778 /* Yuxin Zhou, Microsoft Corporation */
779 /* */
780 /* DESCRIPTION */
781 /* */
782 /* This function checks for errors in the mDNS cache full notify */
783 /* function call. */
784 /* */
785 /* INPUT */
786 /* */
787 /* mdns_ptr Pointer to mDNS instance */
788 /* cache_full_notify Cache full notify function */
789 /* */
790 /* OUTPUT */
791 /* */
792 /* status Completion status */
793 /* */
794 /* CALLS */
795 /* */
796 /* _nx_mdns_cache_notify_set Actual cache notify */
797 /* set function */
798 /* */
799 /* CALLED BY */
800 /* */
801 /* Application Code */
802 /* */
803 /* RELEASE HISTORY */
804 /* */
805 /* DATE NAME DESCRIPTION */
806 /* */
807 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
808 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
809 /* resulting in version 6.1 */
810 /* */
811 /**************************************************************************/
_nxe_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))812 UINT _nxe_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
813 {
814
815 UINT status;
816
817
818 /* Check for invalid input pointers. */
819 if (!mdns_ptr)
820 {
821 return(NX_PTR_ERROR);
822 }
823
824 /* Check for invalid non pointer input. */
825 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
826 {
827 return(NX_MDNS_PARAM_ERROR);
828 }
829
830 /* Call actual mDNS cache notify set function. */
831 status = _nx_mdns_cache_notify_set(mdns_ptr, cache_full_notify_cb);
832
833 /* Return status. */
834 return(status);
835 }
836
837
838 /**************************************************************************/
839 /* */
840 /* FUNCTION RELEASE */
841 /* */
842 /* _nx_mdns_cache_notify_set PORTABLE C */
843 /* 6.1 */
844 /* AUTHOR */
845 /* */
846 /* Yuxin Zhou, Microsoft Corporation */
847 /* */
848 /* DESCRIPTION */
849 /* */
850 /* This function set the cache full notify function. */
851 /* */
852 /* INPUT */
853 /* */
854 /* mdns_ptr Pointer to mDNS instance */
855 /* */
856 /* OUTPUT */
857 /* */
858 /* status Completion status */
859 /* */
860 /* CALLS */
861 /* */
862 /* tx_mutex_get Get the mDNS mutex */
863 /* tx_mutex_put Put the mDNS mutex */
864 /* */
865 /* CALLED BY */
866 /* */
867 /* Application Code */
868 /* */
869 /* RELEASE HISTORY */
870 /* */
871 /* DATE NAME DESCRIPTION */
872 /* */
873 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
874 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
875 /* resulting in version 6.1 */
876 /* */
877 /**************************************************************************/
_nx_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))878 UINT _nx_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
879 {
880
881
882 /* Get the mDNS mutex. */
883 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
884
885 /* Set the cache notify. */
886 mdns_ptr -> nx_mdns_cache_full_notify = cache_full_notify_cb;
887
888 /* Release the mDNS mutex. */
889 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
890
891 return(NX_MDNS_SUCCESS);
892 }
893
894
895 /**************************************************************************/
896 /* */
897 /* FUNCTION RELEASE */
898 /* */
899 /* _nxe_mdns_cache_notify_clear PORTABLE C */
900 /* 6.1 */
901 /* AUTHOR */
902 /* */
903 /* Yuxin Zhou, Microsoft Corporation */
904 /* */
905 /* DESCRIPTION */
906 /* */
907 /* This function checks for errors in the mDNS cache full notify */
908 /* function call. */
909 /* */
910 /* INPUT */
911 /* */
912 /* mdns_ptr Pointer to mDNS instance */
913 /* cache_full_notify Cache full notify function */
914 /* */
915 /* OUTPUT */
916 /* */
917 /* status Completion status */
918 /* */
919 /* CALLS */
920 /* */
921 /* _nx_mdns_cache_notify_clear Actual cache notify */
922 /* clear function */
923 /* */
924 /* CALLED BY */
925 /* */
926 /* Application Code */
927 /* */
928 /* RELEASE HISTORY */
929 /* */
930 /* DATE NAME DESCRIPTION */
931 /* */
932 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
933 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
934 /* resulting in version 6.1 */
935 /* */
936 /**************************************************************************/
_nxe_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)937 UINT _nxe_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
938 {
939
940 UINT status;
941
942
943 /* Check for invalid input pointers. */
944 if (!mdns_ptr)
945 {
946 return(NX_PTR_ERROR);
947 }
948
949 /* Check for invalid non pointer input. */
950 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
951 {
952 return(NX_MDNS_PARAM_ERROR);
953 }
954
955 /* Call actual mDNS cache notify clear function. */
956 status = _nx_mdns_cache_notify_clear(mdns_ptr);
957
958 /* Return status. */
959 return(status);
960 }
961
962
963 /**************************************************************************/
964 /* */
965 /* FUNCTION RELEASE */
966 /* */
967 /* _nx_mdns_cache_notify_clear PORTABLE C */
968 /* 6.1 */
969 /* AUTHOR */
970 /* */
971 /* Yuxin Zhou, Microsoft Corporation */
972 /* */
973 /* DESCRIPTION */
974 /* */
975 /* This function set the cache full notify function. */
976 /* */
977 /* INPUT */
978 /* */
979 /* mdns_ptr Pointer to mDNS instance */
980 /* */
981 /* OUTPUT */
982 /* */
983 /* status Completion status */
984 /* */
985 /* CALLS */
986 /* */
987 /* tx_mutex_get Get the mDNS mutex */
988 /* tx_mutex_put Put the mDNS mutex */
989 /* */
990 /* CALLED BY */
991 /* */
992 /* Application Code */
993 /* */
994 /* RELEASE HISTORY */
995 /* */
996 /* DATE NAME DESCRIPTION */
997 /* */
998 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
999 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1000 /* resulting in version 6.1 */
1001 /* */
1002 /**************************************************************************/
_nx_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)1003 UINT _nx_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
1004 {
1005
1006
1007 /* Get the mDNS mutex. */
1008 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1009
1010 /* Clear the cache notify. */
1011 mdns_ptr -> nx_mdns_cache_full_notify = NX_NULL;
1012
1013 /* Release the mDNS mutex. */
1014 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1015
1016 return(NX_MDNS_SUCCESS);
1017 }
1018
1019
1020 #ifndef NX_MDNS_DISABLE_CLIENT
1021 /**************************************************************************/
1022 /* */
1023 /* FUNCTION RELEASE */
1024 /* */
1025 /* _nxe_mdns_service_ignore_set PORTABLE C */
1026 /* 6.1 */
1027 /* AUTHOR */
1028 /* */
1029 /* Yuxin Zhou, Microsoft Corporation */
1030 /* */
1031 /* DESCRIPTION */
1032 /* */
1033 /* This function checks for errors in the mDNS service ignore mask */
1034 /* set function call. */
1035 /* */
1036 /* INPUT */
1037 /* */
1038 /* mdns_ptr Pointer to mDNS instance */
1039 /* service_mask The service mask */
1040 /* */
1041 /* OUTPUT */
1042 /* */
1043 /* status Completion status */
1044 /* */
1045 /* CALLS */
1046 /* */
1047 /* _nx_mdns_service_ignore_set Actual ignore set function */
1048 /* */
1049 /* CALLED BY */
1050 /* */
1051 /* Application Code */
1052 /* */
1053 /* RELEASE HISTORY */
1054 /* */
1055 /* DATE NAME DESCRIPTION */
1056 /* */
1057 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1058 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1059 /* resulting in version 6.1 */
1060 /* */
1061 /**************************************************************************/
_nxe_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1062 UINT _nxe_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1063 {
1064
1065 UINT status;
1066
1067
1068 /* Check for invalid input pointers. */
1069 if (!mdns_ptr)
1070 {
1071 return(NX_PTR_ERROR);
1072 }
1073
1074 /* Check for invalid non pointer input. */
1075 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1076 {
1077 return(NX_MDNS_PARAM_ERROR);
1078 }
1079
1080 /* Call actual mDNS service ignore mask set function. */
1081 status = _nx_mdns_service_ignore_set(mdns_ptr, service_mask);
1082
1083 /* Return status. */
1084 return(status);
1085 }
1086
1087
1088 /**************************************************************************/
1089 /* */
1090 /* FUNCTION RELEASE */
1091 /* */
1092 /* _nx_mdns_service_ignore_set PORTABLE C */
1093 /* 6.1 */
1094 /* AUTHOR */
1095 /* */
1096 /* Yuxin Zhou, Microsoft Corporation */
1097 /* */
1098 /* DESCRIPTION */
1099 /* */
1100 /* This function sets the service mask to ignore the service. */
1101 /* */
1102 /* INPUT */
1103 /* */
1104 /* mdns_ptr Pointer to mDNS instance */
1105 /* service_mask The service mask */
1106 /* */
1107 /* OUTPUT */
1108 /* */
1109 /* status Completion status */
1110 /* */
1111 /* CALLS */
1112 /* */
1113 /* tx_mutex_get Get the MDNS mutex */
1114 /* tx_mutex_put Put the MDNS mutex */
1115 /* */
1116 /* CALLED BY */
1117 /* */
1118 /* Application Code */
1119 /* */
1120 /* RELEASE HISTORY */
1121 /* */
1122 /* DATE NAME DESCRIPTION */
1123 /* */
1124 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1125 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1126 /* resulting in version 6.1 */
1127 /* */
1128 /**************************************************************************/
_nx_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1129 UINT _nx_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1130 {
1131
1132
1133 /* Get the mDNS mutex. */
1134 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1135
1136 /* Set the service ignore mask. */
1137 mdns_ptr -> nx_mdns_service_ignore_mask = service_mask;
1138
1139 /* Release the mDNS mutex. */
1140 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1141
1142 return(NX_MDNS_SUCCESS);
1143 }
1144
1145
1146 /**************************************************************************/
1147 /* */
1148 /* FUNCTION RELEASE */
1149 /* */
1150 /* _nxe_mdns_service_notify_set PORTABLE C */
1151 /* 6.1 */
1152 /* AUTHOR */
1153 /* */
1154 /* Yuxin Zhou, Microsoft Corporation */
1155 /* */
1156 /* DESCRIPTION */
1157 /* */
1158 /* This function checks for errors in the mDNS service notify function */
1159 /* call. */
1160 /* */
1161 /* INPUT */
1162 /* */
1163 /* mdns_ptr Pointer to mDNS instance */
1164 /* service_mask The service mask */
1165 /* service_change_notify Service change notify function*/
1166 /* */
1167 /* OUTPUT */
1168 /* */
1169 /* status Completion status */
1170 /* */
1171 /* CALLS */
1172 /* */
1173 /* _nx_mdns_service_notify_set Actual mDNS service notify */
1174 /* set function */
1175 /* */
1176 /* CALLED BY */
1177 /* */
1178 /* Application Code */
1179 /* */
1180 /* RELEASE HISTORY */
1181 /* */
1182 /* DATE NAME DESCRIPTION */
1183 /* */
1184 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1185 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1186 /* resulting in version 6.1 */
1187 /* */
1188 /**************************************************************************/
_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))1189 UINT _nxe_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1190 VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1191 {
1192
1193 UINT status;
1194
1195
1196 /* Check for invalid input pointers. */
1197 if (!mdns_ptr)
1198 {
1199 return(NX_PTR_ERROR);
1200 }
1201
1202 /* Check for invalid non pointer input. */
1203 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1204 {
1205 return(NX_MDNS_PARAM_ERROR);
1206 }
1207
1208 /* Call actual mDNS service notify set function. */
1209 status = _nx_mdns_service_notify_set(mdns_ptr, service_mask, service_change_notify);
1210
1211 /* Return status. */
1212 return(status);
1213 }
1214
1215
1216 /**************************************************************************/
1217 /* */
1218 /* FUNCTION RELEASE */
1219 /* */
1220 /* _nx_mdns_service_notify_set PORTABLE C */
1221 /* 6.1 */
1222 /* AUTHOR */
1223 /* */
1224 /* Yuxin Zhou, Microsoft Corporation */
1225 /* */
1226 /* DESCRIPTION */
1227 /* */
1228 /* This function set the service mask and notify callback function. */
1229 /* */
1230 /* INPUT */
1231 /* */
1232 /* mdns_ptr Pointer to mDNS instance */
1233 /* service_mask The service mask */
1234 /* service_change_notify Service change notify function*/
1235 /* */
1236 /* OUTPUT */
1237 /* */
1238 /* status Completion status */
1239 /* */
1240 /* CALLS */
1241 /* */
1242 /* tx_mutex_get Get the mDNS mutex */
1243 /* tx_mutex_put Put the mDNS mutex */
1244 /* */
1245 /* CALLED BY */
1246 /* */
1247 /* Application Code */
1248 /* */
1249 /* RELEASE HISTORY */
1250 /* */
1251 /* DATE NAME DESCRIPTION */
1252 /* */
1253 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1254 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1255 /* resulting in version 6.1 */
1256 /* */
1257 /**************************************************************************/
_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))1258 UINT _nx_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1259 VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1260 {
1261
1262
1263 /* Get the mDNS mutex. */
1264 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1265
1266 /* Set the service mask. */
1267 mdns_ptr -> nx_mdns_service_notify_mask = service_mask;
1268
1269 /* Assign the service change notify. */
1270 mdns_ptr -> nx_mdns_service_change_notify = service_change_notify;
1271
1272 /* Release the mDNS mutex. */
1273 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1274
1275 return(NX_MDNS_SUCCESS);
1276 }
1277
1278
1279 /**************************************************************************/
1280 /* */
1281 /* FUNCTION RELEASE */
1282 /* */
1283 /* _nxe_mdns_service_notify_clear PORTABLE C */
1284 /* 6.1 */
1285 /* AUTHOR */
1286 /* */
1287 /* Yuxin Zhou, Microsoft Corporation */
1288 /* */
1289 /* DESCRIPTION */
1290 /* */
1291 /* This function checks for errors in the mDNS service notify function */
1292 /* call. */
1293 /* */
1294 /* INPUT */
1295 /* */
1296 /* mdns_ptr Pointer to mDNS instance */
1297 /* */
1298 /* OUTPUT */
1299 /* */
1300 /* status Completion status */
1301 /* */
1302 /* CALLS */
1303 /* */
1304 /* _nx_mdns_service_notify_clear Actual service notify */
1305 /* clear function */
1306 /* */
1307 /* CALLED BY */
1308 /* */
1309 /* Application Code */
1310 /* */
1311 /* RELEASE HISTORY */
1312 /* */
1313 /* DATE NAME DESCRIPTION */
1314 /* */
1315 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1316 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1317 /* resulting in version 6.1 */
1318 /* */
1319 /**************************************************************************/
_nxe_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1320 UINT _nxe_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1321 {
1322
1323 UINT status;
1324
1325
1326 /* Check for invalid input pointers. */
1327 if (!mdns_ptr)
1328 {
1329
1330 return(NX_PTR_ERROR);
1331 }
1332
1333 /* Check for invalid non pointer input. */
1334 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1335 {
1336
1337 return(NX_MDNS_PARAM_ERROR);
1338 }
1339
1340 /* Call actual mDNS service notify clear function. */
1341 status = _nx_mdns_service_notify_clear(mdns_ptr);
1342
1343 /* Return status. */
1344 return(status);
1345 }
1346
1347
1348 /**************************************************************************/
1349 /* */
1350 /* FUNCTION RELEASE */
1351 /* */
1352 /* _nx_mdns_service_notify_clear PORTABLE C */
1353 /* 6.1 */
1354 /* AUTHOR */
1355 /* */
1356 /* Yuxin Zhou, Microsoft Corporation */
1357 /* */
1358 /* DESCRIPTION */
1359 /* */
1360 /* This function clears the service mask and notify callback function. */
1361 /* */
1362 /* INPUT */
1363 /* */
1364 /* mdns_ptr Pointer to mDNS instance */
1365 /* */
1366 /* OUTPUT */
1367 /* */
1368 /* status Completion status */
1369 /* */
1370 /* CALLS */
1371 /* */
1372 /* tx_mutex_get Get the mDNS mutex */
1373 /* tx_mutex_put Put the mDNS mutex */
1374 /* */
1375 /* CALLED BY */
1376 /* */
1377 /* Application Code */
1378 /* */
1379 /* RELEASE HISTORY */
1380 /* */
1381 /* DATE NAME DESCRIPTION */
1382 /* */
1383 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1384 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1385 /* resulting in version 6.1 */
1386 /* */
1387 /**************************************************************************/
_nx_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1388 UINT _nx_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1389 {
1390
1391
1392 /* Get the mDNS mutex. */
1393 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1394
1395 /* Clear the service mask. */
1396 mdns_ptr -> nx_mdns_service_notify_mask = 0;
1397
1398 /* Clear the service change notify. */
1399 mdns_ptr -> nx_mdns_service_change_notify = NX_NULL;
1400
1401 /* Release the mDNS mutex. */
1402 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1403
1404 return(NX_MDNS_SUCCESS);
1405 }
1406 #endif /* NX_MDNS_DISABLE_CLIENT */
1407
1408
1409 #ifndef NX_MDNS_DISABLE_SERVER
1410 /**************************************************************************/
1411 /* */
1412 /* FUNCTION RELEASE */
1413 /* */
1414 /* _nxe_mdns_service_announcement_timing_set PORTABLE C */
1415 /* 6.1 */
1416 /* AUTHOR */
1417 /* */
1418 /* Yuxin Zhou, Microsoft Corporation */
1419 /* */
1420 /* DESCRIPTION */
1421 /* */
1422 /* This function checks for errors in the mDNS announcement timing */
1423 /* set function call. */
1424 /* */
1425 /* INPUT */
1426 /* */
1427 /* mdns_ptr Pointer to mDNS instance */
1428 /* t Announcing period */
1429 /* p Announcing count */
1430 /* k Announcing factor */
1431 /* retrans_interval Announcing retransmission */
1432 /* interval */
1433 /* interval Announcing period interval */
1434 /* max_time Announcing max time */
1435 /* */
1436 /* OUTPUT */
1437 /* */
1438 /* status Completion status */
1439 /* */
1440 /* CALLS */
1441 /* */
1442 /* _nx_mdns_service_announcement_timing_set */
1443 /* Actual mDNS announcement */
1444 /* timing set function */
1445 /* */
1446 /* CALLED BY */
1447 /* */
1448 /* Application Code */
1449 /* */
1450 /* RELEASE HISTORY */
1451 /* */
1452 /* DATE NAME DESCRIPTION */
1453 /* */
1454 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1455 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1456 /* resulting in version 6.1 */
1457 /* */
1458 /**************************************************************************/
_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 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)
1460 {
1461
1462 UINT status;
1463
1464
1465 /* Check for invalid input pointers. */
1466 if ((!mdns_ptr) || (!t) || (!p) || (!k) || (!period_interval) || (!max_time))
1467 {
1468 return(NX_PTR_ERROR);
1469 }
1470
1471 /* Check for invalid non pointer input. */
1472 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1473 {
1474 return(NX_MDNS_PARAM_ERROR);
1475 }
1476
1477 /* Call actual mDNS delete service. */
1478 status = _nx_mdns_service_announcement_timing_set(mdns_ptr, t, p, k, retrans_interval, period_interval, max_time);
1479
1480 /* Return status. */
1481 return(status);
1482 }
1483
1484
1485 /**************************************************************************/
1486 /* */
1487 /* FUNCTION RELEASE */
1488 /* */
1489 /* _nx_mdns_service_announcement_timing_set PORTABLE C */
1490 /* 6.1 */
1491 /* AUTHOR */
1492 /* */
1493 /* Yuxin Zhou, Microsoft Corporation */
1494 /* */
1495 /* DESCRIPTION */
1496 /* */
1497 /* This function set the service mask and notify callback function. */
1498 /* */
1499 /* INPUT */
1500 /* */
1501 /* mdns_ptr Pointer to mDNS instance */
1502 /* t Announcing period */
1503 /* p Announcing count */
1504 /* k Announcing factor */
1505 /* retrans_interval Announcing retransmission */
1506 /* interval */
1507 /* interval Announcing period interval */
1508 /* max_time Announcing max time */
1509 /* */
1510 /* OUTPUT */
1511 /* */
1512 /* status Completion status */
1513 /* */
1514 /* CALLS */
1515 /* */
1516 /* tx_mutex_get Get the mDNS mutex */
1517 /* tx_mutex_put Put the mDNS mutex */
1518 /* */
1519 /* CALLED BY */
1520 /* */
1521 /* Application Code */
1522 /* */
1523 /* RELEASE HISTORY */
1524 /* */
1525 /* DATE NAME DESCRIPTION */
1526 /* */
1527 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1528 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1529 /* resulting in version 6.1 */
1530 /* */
1531 /**************************************************************************/
_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 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)
1533 {
1534
1535
1536 /* Get the mDNS mutex. */
1537 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1538
1539 /* Set the mDNS announcing period. */
1540 mdns_ptr -> nx_mdns_announcing_period = (USHORT)t;
1541
1542 /* Set the mDNS announcing count between one announcing period. */
1543 mdns_ptr -> nx_mdns_announcing_count = (UCHAR)p;
1544
1545 /* Set the mDNS announcing factor. */
1546 mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)k;
1547
1548 /* Set the mDNS announcing retransmission interval. */
1549 mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)retrans_interval;
1550
1551 /* Set the mDNS announcing period interval. */
1552 mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)period_interval;
1553
1554 /* Set the mDNS announcing max time. */
1555 mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)max_time;
1556
1557 /* Release the mDNS mutex. */
1558 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1559
1560 return(NX_MDNS_SUCCESS);
1561 }
1562 #endif /* NX_MDNS_DISABLE_SERVER */
1563
1564
1565 /**************************************************************************/
1566 /* */
1567 /* FUNCTION RELEASE */
1568 /* */
1569 /* _nxe_mdns_enable PORTABLE C */
1570 /* 6.1 */
1571 /* AUTHOR */
1572 /* */
1573 /* Yuxin Zhou, Microsoft Corporation */
1574 /* */
1575 /* DESCRIPTION */
1576 /* */
1577 /* This function checks for errors in the mDNS enable function call. */
1578 /* */
1579 /* INPUT */
1580 /* */
1581 /* mdns_ptr Pointer to mDNS instance */
1582 /* interface_index The interface index */
1583 /* */
1584 /* OUTPUT */
1585 /* */
1586 /* status Completion status */
1587 /* */
1588 /* CALLS */
1589 /* */
1590 /* _nx_mdns_enable Actual mDNS enable function */
1591 /* */
1592 /* CALLED BY */
1593 /* */
1594 /* Application Code */
1595 /* */
1596 /* RELEASE HISTORY */
1597 /* */
1598 /* DATE NAME DESCRIPTION */
1599 /* */
1600 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1601 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1602 /* resulting in version 6.1 */
1603 /* */
1604 /**************************************************************************/
_nxe_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1605 UINT _nxe_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1606 {
1607
1608 UINT status;
1609
1610
1611 /* Check for invalid input pointers. */
1612 if (!mdns_ptr)
1613 {
1614 return(NX_PTR_ERROR);
1615 }
1616
1617 /* Check for invalid non pointer input or invalid server attributes. */
1618 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1619 {
1620 return(NX_MDNS_PARAM_ERROR);
1621 }
1622
1623 /* Call actual mDNS delete service. */
1624 status = _nx_mdns_enable(mdns_ptr, interface_index);
1625
1626 /* Return status. */
1627 return(status);
1628 }
1629
1630
1631 /**************************************************************************/
1632 /* */
1633 /* FUNCTION RELEASE */
1634 /* */
1635 /* _nx_mdns_enable PORTABLE C */
1636 /* 6.1 */
1637 /* AUTHOR */
1638 /* */
1639 /* Yuxin Zhou, Microsoft Corporation */
1640 /* */
1641 /* DESCRIPTION */
1642 /* */
1643 /* This function enables the mDNS of the physical host interface by */
1644 /* interface index. */
1645 /* */
1646 /* INPUT */
1647 /* */
1648 /* mdns_ptr Pointer to mDNS instance */
1649 /* interface_index The interface index */
1650 /* */
1651 /* OUTPUT */
1652 /* */
1653 /* status Completion status */
1654 /* */
1655 /* CALLS */
1656 /* */
1657 /* tx_mutex_get Get the mDNS mutex */
1658 /* tx_mutex_put Put the mDNS mutex */
1659 /* nx_ipv4_multicast_interface_join Join the IPv4 Multicast group */
1660 /* nxd_ipv6_multicast_interface_join Join the IPv6 Multicast group */
1661 /* _nx_mdns_host_name_register Register the host name */
1662 /* _nx_mdns_timer_set Set the mDNS timer */
1663 /* */
1664 /* CALLED BY */
1665 /* */
1666 /* Application Code */
1667 /* */
1668 /* RELEASE HISTORY */
1669 /* */
1670 /* DATE NAME DESCRIPTION */
1671 /* */
1672 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1673 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1674 /* resulting in version 6.1 */
1675 /* */
1676 /**************************************************************************/
_nx_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1677 UINT _nx_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1678 {
1679
1680 UINT status;
1681
1682 #ifndef NX_MDNS_DISABLE_SERVER
1683 ULONG *head;
1684 NX_MDNS_RR *p;
1685 #endif /* NX_MDNS_DISABLE_SERVER */
1686
1687 #ifdef NX_MDNS_ENABLE_IPV6
1688 NX_INTERFACE *interface_ptr;
1689 NXD_IPV6_ADDRESS *ipv6_address;
1690 #endif /* NX_MDNS_ENABLE_IPV6 */
1691
1692 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1693 {
1694 return(NX_MDNS_PARAM_ERROR);
1695 }
1696
1697 /* Check to see if mDNS is already enabled on this interface. */
1698 if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_TRUE)
1699 {
1700 return(NX_MDNS_ALREADY_ENABLED);
1701 }
1702
1703 /* Get the mDNS mutex. */
1704 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1705
1706 /* Enable the mdns function. */
1707 mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_TRUE;
1708
1709 #ifdef NX_MDNS_ENABLE_IPV6
1710 /* Set the interface pointer. */
1711 interface_ptr = &(mdns_ptr -> nx_mdns_ip_ptr -> nx_ip_interface[interface_index]);
1712
1713 /* Find the link-local address as source adress. Get first address from interface. */
1714 ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
1715
1716 /* Loop to check the address. */
1717 while (ipv6_address)
1718 {
1719
1720 /* Check for link-local address. */
1721 if (IPv6_Address_Type(ipv6_address -> nxd_ipv6_address) & IPV6_ADDRESS_LINKLOCAL)
1722 {
1723 break;
1724 }
1725 ipv6_address = ipv6_address -> nxd_ipv6_address_next;
1726 }
1727
1728 /* Check if found the link-local address. */
1729 if(ipv6_address)
1730 {
1731
1732 /* Set the IPv6 link-local address index. */
1733 mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = ipv6_address -> nxd_ipv6_address_index;
1734 }
1735 else
1736 {
1737
1738 /* No available address, set the address index as 0xFFFFFFFF. */
1739 mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = 0xFFFFFFFF;
1740 }
1741 #endif /* NX_MDNS_ENABLE_IPV6 */
1742
1743 /* Join the group. */
1744 status = nx_ipv4_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
1745
1746 /* Check status. */
1747 if (status)
1748 {
1749
1750 /* Release the mDNS mutex. */
1751 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1752 return(status);
1753 }
1754
1755 #ifdef NX_MDNS_ENABLE_IPV6
1756 status = nxd_ipv6_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
1757
1758 /* Check status. */
1759 if (status)
1760 {
1761
1762 /* Release the mDNS mutex. */
1763 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1764 return(status);
1765 }
1766 #endif /* NX_MDNS_ENABLE_IPV6 */
1767
1768 #ifndef NX_MDNS_DISABLE_SERVER
1769
1770 /* Register the host name. */
1771 status = _nx_mdns_host_name_register(mdns_ptr, NX_TRUE, interface_index);
1772
1773 /* Check status. */
1774 if (status)
1775 {
1776
1777 /* Release the mDNS mutex. */
1778 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1779 return(status);
1780 }
1781
1782 /* 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. */
1783
1784 /* Get the header to the local buffer. */
1785 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
1786
1787 /* Set the pointer. */
1788 head = (ULONG*)(*head);
1789
1790 /* Check the resource record. */
1791 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
1792 {
1793
1794 /* Check the interface index. */
1795 if (p -> nx_mdns_rr_interface_index != interface_index)
1796 continue;
1797
1798 /* Check whether the resource record is valid. */
1799 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
1800 continue;
1801
1802 /* Check the state and delete flag, GOODBYE state and DELETE FLAG means this resource record should be deleted. */
1803 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) &&
1804 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE))
1805 {
1806
1807 /* Delete the resource records. */
1808 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
1809 continue;
1810 }
1811
1812 /* Check the resource reocrd type. */
1813 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) ||
1814 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))
1815 {
1816 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
1817 continue;
1818 }
1819
1820 /* Check the unique flag. */
1821 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
1822 {
1823 /* For a unique type, we need to probe it on the network
1824 to guarantee its uniqueness. */
1825 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
1826 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
1827 p -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
1828 }
1829 else
1830 {
1831 /* If the record is not marked as unique, start the announcement process. */
1832 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
1833 p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
1834 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
1835
1836 /* Check the announcing max time. */
1837 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
1838 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
1839 else
1840 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
1841
1842 /* Set the retransmit count. */
1843 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
1844 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
1845 else
1846 p -> nx_mdns_rr_retransmit_count = 1;
1847 }
1848
1849 /* Set the mDNS timer. */
1850 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
1851 }
1852 #endif /* NX_MDNS_DISABLE_SERVER */
1853
1854 /* Set the mdns started flag. */
1855 mdns_ptr -> nx_mdns_started = NX_TRUE;
1856
1857 /* Release the mDNS mutex. */
1858 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1859
1860 /* Return. */
1861 return(NX_MDNS_SUCCESS);
1862 }
1863
1864
1865 /**************************************************************************/
1866 /* */
1867 /* FUNCTION RELEASE */
1868 /* */
1869 /* _nxe_mdns_disable PORTABLE C */
1870 /* 6.1 */
1871 /* AUTHOR */
1872 /* */
1873 /* Yuxin Zhou, Microsoft Corporation */
1874 /* */
1875 /* DESCRIPTION */
1876 /* */
1877 /* This function checks for errors in the mDNS disable function call. */
1878 /* */
1879 /* INPUT */
1880 /* */
1881 /* mdns_ptr Pointer to mDNS instance */
1882 /* interface_index The interface index */
1883 /* */
1884 /* OUTPUT */
1885 /* */
1886 /* status Completion status */
1887 /* */
1888 /* CALLS */
1889 /* */
1890 /* _nx_mdns_disable Actual mDNS disable function */
1891 /* */
1892 /* CALLED BY */
1893 /* */
1894 /* Application Code */
1895 /* */
1896 /* RELEASE HISTORY */
1897 /* */
1898 /* DATE NAME DESCRIPTION */
1899 /* */
1900 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1901 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1902 /* resulting in version 6.1 */
1903 /* */
1904 /**************************************************************************/
_nxe_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1905 UINT _nxe_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1906 {
1907
1908 UINT status;
1909
1910
1911 /* Check for invalid input pointers. */
1912 if (!mdns_ptr)
1913 {
1914 return(NX_PTR_ERROR);
1915 }
1916
1917 /* Check for invalid non pointer input or invalid server attributes. */
1918 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1919 {
1920 return(NX_MDNS_PARAM_ERROR);
1921 }
1922
1923 /* Call actual mDNS delete service. */
1924 status = _nx_mdns_disable(mdns_ptr, interface_index);
1925
1926 /* Return status. */
1927 return(status);
1928 }
1929
1930
1931 /**************************************************************************/
1932 /* */
1933 /* FUNCTION RELEASE */
1934 /* */
1935 /* _nx_mdns_disable PORTABLE C */
1936 /* 6.1 */
1937 /* AUTHOR */
1938 /* */
1939 /* Yuxin Zhou, Microsoft Corporation */
1940 /* */
1941 /* DESCRIPTION */
1942 /* */
1943 /* This function disables the mDNS of the physical host interface by */
1944 /* interface index. */
1945 /* */
1946 /* INPUT */
1947 /* */
1948 /* mdns_ptr Pointer to mDNS instance */
1949 /* interface_index The interface index */
1950 /* */
1951 /* OUTPUT */
1952 /* */
1953 /* status Completion status */
1954 /* */
1955 /* CALLS */
1956 /* */
1957 /* tx_mutex_get Get the mDNS mutex */
1958 /* tx_mutex_put Put the mDNS mutex */
1959 /* nx_ipv4_multicast_leave Leave the IPv4 Multicast group*/
1960 /* nxd_ipv6_multicast_interface_leave Leave the IPv6 Multicast group*/
1961 /* _nx_mdns_cache_initialize Initialize the mDNS peer cache*/
1962 /* _nx_mdns_timer_set Set the mDNS timer */
1963 /* */
1964 /* CALLED BY */
1965 /* */
1966 /* Application Code */
1967 /* */
1968 /* RELEASE HISTORY */
1969 /* */
1970 /* DATE NAME DESCRIPTION */
1971 /* */
1972 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1973 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1974 /* resulting in version 6.1 */
1975 /* */
1976 /**************************************************************************/
_nx_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1977 UINT _nx_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1978 {
1979
1980 UINT dns_sd_size;
1981 UINT i;
1982 ULONG *head;
1983 NX_MDNS_RR *p;
1984
1985
1986 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1987 {
1988 return(NX_MDNS_PARAM_ERROR);
1989 }
1990
1991 /* Check to see if mDNS is not enabled on this interface.
1992 Note: Only support one interface yet. */
1993 if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_FALSE)
1994 {
1995 return(NX_MDNS_NOT_ENABLED);
1996 }
1997
1998 /* Check the DNS-SD string. */
1999 if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_size, NX_MDNS_DNS_SD_MAX))
2000 {
2001 return(NX_MDNS_DATA_SIZE_ERROR);
2002 }
2003
2004 /* Get the mDNS mutex. */
2005 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2006
2007 /* Disable the mdns function. */
2008 mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_FALSE;
2009
2010 /* Leave the group. */
2011 nx_ipv4_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
2012
2013 #ifdef NX_MDNS_ENABLE_IPV6
2014 nxd_ipv6_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
2015 #endif /* NX_MDNS_ENABLE_IPV6 */
2016
2017 #ifndef NX_MDNS_DISABLE_CLIENT
2018
2019 /* Get the local buffer head. */
2020 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
2021
2022 /* Set the pointer. */
2023 head = (ULONG*)(*head);
2024
2025 /* Delete all services on this interface. */
2026 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2027 {
2028
2029 /* Check whether the resource record is valid. */
2030 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2031 continue;
2032
2033 /* Check the interface index. */
2034 if (p -> nx_mdns_rr_interface_index != interface_index)
2035 continue;
2036
2037 /* Delete the resource record. */
2038 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
2039 }
2040 #endif /* NX_MDNS_DISABLE_CLIENT */
2041
2042 #ifndef NX_MDNS_DISABLE_SERVER
2043
2044 /* Get the local buffer head. */
2045 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2046
2047 /* Set the pointer. */
2048 head = (ULONG*)(*head);
2049
2050 /* Send the Goodbye message, RFC6762, Section10.1, Page33. */
2051 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2052 {
2053
2054 /* Check whether the resource record is valid. */
2055 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2056 continue;
2057
2058 /* Check the interface index. */
2059 if (p -> nx_mdns_rr_interface_index != interface_index)
2060 continue;
2061
2062 /* Skip the NSEC and DNS-SD PTR resource record. */
2063 if ((p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) ||
2064 ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
2065 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_size))))
2066 {
2067
2068 /* Suspend the resource record. */
2069 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
2070 }
2071 else
2072 {
2073
2074 /* Set the state to send Goodbye packet. */
2075 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
2076
2077 /* Clear the retransmit count. */
2078 p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
2079
2080 /* Set the timer count. 250ms. */
2081 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
2082
2083 /* Set the mDNS timer. */
2084 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
2085 }
2086 }
2087 #endif /* NX_MDNS_DISABLE_SERVER */
2088
2089 /* Check if all interfaces are disabled. */
2090 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
2091 {
2092 if (mdns_ptr -> nx_mdns_interface_enabled[i])
2093 break;
2094 }
2095
2096 /* Set the mdns started flag. */
2097 if (i == NX_MAX_PHYSICAL_INTERFACES)
2098 mdns_ptr -> nx_mdns_started = NX_FALSE;
2099
2100 /* Release the mDNS mutex. */
2101 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2102
2103 return(NX_MDNS_SUCCESS);
2104 }
2105
2106
2107 /**************************************************************************/
2108 /* */
2109 /* FUNCTION RELEASE */
2110 /* */
2111 /* _nxe_mdns_local_domain_set PORTABLE C */
2112 /* 6.1 */
2113 /* AUTHOR */
2114 /* */
2115 /* Yuxin Zhou, Microsoft Corporation */
2116 /* */
2117 /* DESCRIPTION */
2118 /* */
2119 /* This function checks for errors in the mDNS domain sets */
2120 /* function call. */
2121 /* */
2122 /* INPUT */
2123 /* */
2124 /* mdns_ptr Pointer to mDNS instance */
2125 /* domain_name Domain name */
2126 /* */
2127 /* OUTPUT */
2128 /* */
2129 /* status Completion status */
2130 /* */
2131 /* CALLS */
2132 /* */
2133 /* _nx_mdns_domain_name_set Actual domain set function */
2134 /* */
2135 /* CALLED BY */
2136 /* */
2137 /* Application Code */
2138 /* */
2139 /* RELEASE HISTORY */
2140 /* */
2141 /* DATE NAME DESCRIPTION */
2142 /* */
2143 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2144 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2145 /* resulting in version 6.1 */
2146 /* */
2147 /**************************************************************************/
_nxe_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2148 UINT _nxe_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2149 {
2150
2151 UINT status;
2152
2153
2154 /* Check for invalid input pointers. */
2155 if ((!mdns_ptr) || (!domain_name))
2156 {
2157 return(NX_PTR_ERROR);
2158 }
2159
2160 /* Check for invalid non pointer input or invalid server attributes. */
2161 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2162 {
2163 return(NX_MDNS_PARAM_ERROR);
2164 }
2165
2166 /* Call actual mDNS domain name set service. */
2167 status = _nx_mdns_domain_name_set(mdns_ptr, domain_name);
2168
2169 /* Return status. */
2170 return(status);
2171 }
2172
2173
2174 /**************************************************************************/
2175 /* */
2176 /* FUNCTION RELEASE */
2177 /* */
2178 /* _nx_mdns_domain_name_set PORTABLE C */
2179 /* 6.1 */
2180 /* AUTHOR */
2181 /* */
2182 /* Yuxin Zhou, Microsoft Corporation */
2183 /* */
2184 /* DESCRIPTION */
2185 /* */
2186 /* This function sets the mDNS domain name. By default is "local". */
2187 /* */
2188 /* INPUT */
2189 /* */
2190 /* mdns_ptr Pointer to mDNS instance */
2191 /* domain_name Domain name */
2192 /* */
2193 /* OUTPUT */
2194 /* */
2195 /* status Completion status */
2196 /* */
2197 /* CALLS */
2198 /* */
2199 /* tx_mutex_get Get the mDNS mutex */
2200 /* tx_mutex_put Put the mDNS mutex */
2201 /* */
2202 /* CALLED BY */
2203 /* */
2204 /* Application Code */
2205 /* */
2206 /* RELEASE HISTORY */
2207 /* */
2208 /* DATE NAME DESCRIPTION */
2209 /* */
2210 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2211 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2212 /* verified memcpy use cases, */
2213 /* resulting in version 6.1 */
2214 /* */
2215 /**************************************************************************/
_nx_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2216 UINT _nx_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2217 {
2218
2219 UINT index;
2220 UINT domain_name_size;
2221
2222
2223 /* Check the size. */
2224 if (_nx_utility_string_length_check((CHAR *)domain_name, &domain_name_size, NX_MDNS_DOMAIN_NAME_MAX))
2225 {
2226 return(NX_MDNS_DATA_SIZE_ERROR);
2227 }
2228
2229 /* Get the mDNS mutex. */
2230 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2231
2232 /* Save the new domain name. */
2233 memcpy(&mdns_ptr -> nx_mdns_domain_name[0], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2234 mdns_ptr -> nx_mdns_domain_name[domain_name_size] = NX_NULL;
2235
2236 /* Initialize the struct. */
2237 memset(_nx_mdns_dns_sd, 0, NX_MDNS_DNS_SD_MAX);
2238
2239 /* Update the services dns-sd. */
2240 memcpy(_nx_mdns_dns_sd, "_services._dns-sd._udp.", (sizeof("_services._dns-sd._udp.") - 1)); /* Use case of memcpy is verified. */
2241 index = (sizeof("_services._dns-sd._udp.") - 1);
2242 memcpy(&_nx_mdns_dns_sd[index], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2243
2244 /* Release the mDNS mutex. */
2245 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2246
2247 /* Return a successful status. */
2248 return(NX_SUCCESS);
2249 }
2250
2251
2252 #ifndef NX_MDNS_DISABLE_SERVER
2253 /**************************************************************************/
2254 /* */
2255 /* FUNCTION RELEASE */
2256 /* */
2257 /* _nxe_mdns_service_add PORTABLE C */
2258 /* 6.1 */
2259 /* AUTHOR */
2260 /* */
2261 /* Yuxin Zhou, Microsoft Corporation */
2262 /* */
2263 /* DESCRIPTION */
2264 /* */
2265 /* This function checks for errors in the mDNS service add */
2266 /* function call. */
2267 /* */
2268 /* INPUT */
2269 /* */
2270 /* mdns_ptr Pointer to mDNS instance */
2271 /* name Service instance name */
2272 /* type The type of the service */
2273 /* subtype The subtype of the service */
2274 /* txt The txt string of the service */
2275 /* ttl The ttl of the service */
2276 /* priority The priority of target host */
2277 /* weights Service weight */
2278 /* port The port on this target host */
2279 /* is_unique The RR set of the service */
2280 /* interface_index The interface index */
2281 /* */
2282 /* OUTPUT */
2283 /* */
2284 /* status Completion status */
2285 /* */
2286 /* CALLS */
2287 /* */
2288 /* _nx_mdns_service_add Actual service add function */
2289 /* */
2290 /* CALLED BY */
2291 /* */
2292 /* Application Code */
2293 /* */
2294 /* RELEASE HISTORY */
2295 /* */
2296 /* DATE NAME DESCRIPTION */
2297 /* */
2298 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2299 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2300 /* resulting in version 6.1 */
2301 /* */
2302 /**************************************************************************/
_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)2303 UINT _nxe_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2304 USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2305 {
2306
2307 UINT status;
2308
2309
2310 /* Check for invalid input pointers. */
2311 if (!mdns_ptr)
2312 {
2313 return(NX_PTR_ERROR);
2314 }
2315
2316 /* Check for invalid server attributes. */
2317 if ((mdns_ptr -> nx_mdns_id != NX_MDNS_ID) || (!port))
2318 {
2319 return(NX_MDNS_PARAM_ERROR);
2320 }
2321
2322 /* Check the size of the service name string. The last four characters in the
2323 service name are reserved so DNS-SD is able to append " (2)" during the conflict
2324 resolution process. */
2325 #if (NX_MDNS_SERVICE_NAME_MAX >= NX_MDNS_LABEL_MAX)
2326 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_LABEL_MAX - 4)))
2327 #else
2328 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_SERVICE_NAME_MAX - 4)))
2329 #endif
2330 {
2331 return(NX_MDNS_DATA_SIZE_ERROR);
2332 }
2333
2334 /* Check the type. */
2335 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2336 {
2337 return(NX_MDNS_DATA_SIZE_ERROR);
2338 }
2339
2340 /* Check the txt string size. */
2341 if (txt)
2342 {
2343 if (_nx_utility_string_length_check((CHAR *)txt, NX_NULL, NX_MDNS_NAME_MAX))
2344 {
2345 return(NX_MDNS_DATA_SIZE_ERROR);
2346 }
2347 }
2348
2349 /* Check the txt string size. */
2350 if (sub_type)
2351 {
2352 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
2353 {
2354 return(NX_MDNS_DATA_SIZE_ERROR);
2355 }
2356 }
2357
2358 /* Check the interface index. */
2359 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
2360 {
2361 return(NX_INVALID_INTERFACE);
2362 }
2363
2364 /* Call actual mDNS service add service. */
2365 status = _nx_mdns_service_add(mdns_ptr, name, type, sub_type, txt, ttl, priority,
2366 weights, port, is_unique, interface_index);
2367
2368 /* Return status. */
2369 return(status);
2370 }
2371
2372
2373 /**************************************************************************/
2374 /* */
2375 /* FUNCTION RELEASE */
2376 /* */
2377 /* _nx_mdns_service_add PORTABLE C */
2378 /* 6.1 */
2379 /* AUTHOR */
2380 /* */
2381 /* Yuxin Zhou, Microsoft Corporation */
2382 /* */
2383 /* DESCRIPTION */
2384 /* */
2385 /* This function adds the mDNS services, and the PTR, SRV and TXT */
2386 /* records into the local buffer. */
2387 /* */
2388 /* INPUT */
2389 /* */
2390 /* mdns_ptr Pointer to mDNS instance */
2391 /* name Service nstance name */
2392 /* type The type of the service */
2393 /* subtype The subtype of the service */
2394 /* txt The txt string of the service */
2395 /* ttl The ttl of the service */
2396 /* priority The priority of target host */
2397 /* weights Service weight */
2398 /* port The port on this target host */
2399 /* is_unique The RR set of the service */
2400 /* interface_index The interface index */
2401 /* */
2402 /* OUTPUT */
2403 /* */
2404 /* status Completion status */
2405 /* */
2406 /* CALLS */
2407 /* */
2408 /* tx_mutex_get Get the mDNS mutex */
2409 /* tx_mutex_put Put the mDNS mutex */
2410 /* _nx_mdns_service_name_assemble Assemble the service name */
2411 /* _nx_mdns_rr_srv_add Add the SRV resource record */
2412 /* _nx_mdns_rr_txt_add Add the TXT resource record */
2413 /* _nx_mdns_rr_ptr_add Add the PTR resource record */
2414 /* _nx_mdns_rr_delete Delete the resource record */
2415 /* */
2416 /* CALLED BY */
2417 /* */
2418 /* Application Code */
2419 /* */
2420 /* RELEASE HISTORY */
2421 /* */
2422 /* DATE NAME DESCRIPTION */
2423 /* */
2424 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2425 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2426 /* resulting in version 6.1 */
2427 /* */
2428 /**************************************************************************/
_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)2429 UINT _nx_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2430 USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2431 {
2432
2433 UINT status;
2434 UINT type_index;
2435 NX_MDNS_RR *srv_rr;
2436 NX_MDNS_RR *txt_rr;
2437 NX_MDNS_RR *ptr_rr;
2438 NX_MDNS_RR *dns_sd_rr;
2439 ULONG *head;
2440 NX_MDNS_RR *p;
2441 ULONG srv_ttl;
2442 ULONG txt_ttl;
2443 ULONG ptr_ttl;
2444 UINT string_length;
2445
2446
2447 /* Get the mDNS mutex. */
2448 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2449
2450 /* Check the ttl value. */
2451 if (ttl)
2452 {
2453
2454 /* Use user supplied TTL value if it is not zero. */
2455 srv_ttl = ttl;
2456 txt_ttl = ttl;
2457 ptr_ttl = ttl;
2458 }
2459 else
2460 {
2461
2462 /* Use the RFC recommended TTL values if user doesn't supply one. */
2463 srv_ttl = NX_MDNS_RR_TTL_HOST;
2464 txt_ttl = NX_MDNS_RR_TTL_OTHER;
2465 ptr_ttl = NX_MDNS_RR_TTL_OTHER;
2466 }
2467
2468 /* Construct the SRV name. */
2469 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);
2470
2471 /* Check the status. */
2472 if (status)
2473 {
2474
2475 /* Release the mDNS mutex. */
2476 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2477 return (status);
2478 }
2479
2480 /* Check string length. */
2481 if (_nx_utility_string_length_check((CHAR *)(&temp_string_buffer[0]), &string_length, NX_MDNS_NAME_MAX))
2482 {
2483
2484 /* Release the mDNS mutex. */
2485 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2486 return (NX_MDNS_DATA_SIZE_ERROR);
2487 }
2488
2489 /* Check whether the same service name exist. */
2490 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2491 head = (ULONG*)(*head);
2492
2493 /* Check the resource record. */
2494 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2495 {
2496 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2497 continue;
2498
2499 /* Check the interface. */
2500 if (p -> nx_mdns_rr_interface_index != interface_index)
2501 continue;
2502
2503 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
2504 {
2505
2506 /* Compare the service name. */
2507 if (!_nx_mdns_name_match(&temp_string_buffer[0], p -> nx_mdns_rr_name, string_length))
2508 {
2509
2510 /* Release the mDNS mutex. */
2511 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2512
2513 return(NX_MDNS_EXIST_SAME_SERVICE);
2514 }
2515 }
2516 }
2517
2518 /* Construct the SRV target name. */
2519 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);
2520
2521 /* Check the status. */
2522 if (status)
2523 {
2524
2525 /* Release the mDNS mutex. */
2526 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2527 return (status);
2528 }
2529
2530 /* Add the SRV resource records message. */
2531 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);
2532
2533 /* Check the status. */
2534 if (status)
2535 {
2536
2537 /* Release the mDNS mutex. */
2538 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2539 return(status);
2540 }
2541
2542 /* Add the TXT resource records message. */
2543 status = _nx_mdns_rr_txt_add(mdns_ptr, &temp_string_buffer[0], txt_ttl, is_unique, txt, &txt_rr, interface_index);
2544
2545 /* Check the status. */
2546 if (status)
2547 {
2548
2549 /* Delete the SRV records. */
2550 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2551
2552 /* Release the mDNS mutex. */
2553 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2554
2555 return(status);
2556 }
2557
2558 /* Add the dns-sd PTR resource records message. */
2559 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);
2560
2561 /* Check the status. */
2562 if (status)
2563 {
2564
2565 /* Delete the TXT records. */
2566 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2567
2568 /* Delete the SRV records. */
2569 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2570
2571 /* Release the mDNS mutex. */
2572 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2573
2574 return(status);
2575 }
2576
2577 /* Add the PTR resource records message. */
2578 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);
2579
2580 /* Check the status. */
2581 if (status)
2582 {
2583
2584 /* Delete the TXT records. */
2585 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2586
2587 /* Delete the SRV records. */
2588 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2589
2590 /* Delete the DNS_SD PTR records. */
2591 _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2592
2593 /* Release the mDNS mutex. */
2594 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2595
2596 return(status);
2597 }
2598
2599 /* Add another PTR type for the subtype. */
2600 if (sub_type)
2601 {
2602
2603 /* Construct the PTR target name. */
2604 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);
2605
2606 /* Check the status. */
2607 if (status)
2608 {
2609
2610 /* Release the mDNS mutex. */
2611 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2612
2613 return (status);
2614 }
2615
2616 /* Add the Sub PTR resource records message. */
2617 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);
2618
2619 /* Check the status. */
2620 if (status)
2621 {
2622
2623 /* Delete the PTR records. */
2624 _nx_mdns_rr_delete(mdns_ptr, ptr_rr);
2625
2626 /* Delete the DNS_SD PTR records. */
2627 _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2628
2629 /* Delete the SRV records. */
2630 _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2631
2632 /* Delete the TXT records. */
2633 _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2634
2635 /* Release the mDNS mutex. */
2636 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2637
2638 return(status);
2639 }
2640 }
2641
2642 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2643
2644 /* Add the NSEC resource record for service. */
2645 _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], NX_FALSE, NX_FALSE, NX_MDNS_ADD_NSEC_FOR_SERVICE, interface_index);
2646 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
2647
2648 /* Release the mDNS mutex. */
2649 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2650
2651 /* Return a successful status. */
2652 return(NX_SUCCESS);
2653 }
2654
2655
2656 /**************************************************************************/
2657 /* */
2658 /* FUNCTION RELEASE */
2659 /* */
2660 /* _nxe_mdns_service_delete PORTABLE C */
2661 /* 6.1 */
2662 /* AUTHOR */
2663 /* */
2664 /* Yuxin Zhou, Microsoft Corporation */
2665 /* */
2666 /* DESCRIPTION */
2667 /* */
2668 /* This function checks for errors in the mDNS service delete */
2669 /* function call. */
2670 /* */
2671 /* INPUT */
2672 /* */
2673 /* mdns_ptr Pointer to mDNS instance */
2674 /* name The name of the service */
2675 /* type The type of the service */
2676 /* subtype The subtype of the service */
2677 /* */
2678 /* OUTPUT */
2679 /* */
2680 /* status Completion status */
2681 /* */
2682 /* CALLS */
2683 /* */
2684 /* _nx_mdns_service_delete Actual service delete function*/
2685 /* */
2686 /* CALLED BY */
2687 /* */
2688 /* Application Code */
2689 /* */
2690 /* RELEASE HISTORY */
2691 /* */
2692 /* DATE NAME DESCRIPTION */
2693 /* */
2694 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2695 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2696 /* resulting in version 6.1 */
2697 /* */
2698 /**************************************************************************/
_nxe_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2699 UINT _nxe_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2700 {
2701
2702 UINT status;
2703
2704 /* Check for invalid input pointers. */
2705 if ((!mdns_ptr) || (!name) || (!type))
2706 {
2707 return(NX_PTR_ERROR);
2708 }
2709
2710 /* Check for invalid server attributes. */
2711 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2712 {
2713 return(NX_MDNS_PARAM_ERROR);
2714 }
2715
2716 /* Check the size. */
2717 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX) ||
2718 _nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2719 {
2720 return(NX_MDNS_DATA_SIZE_ERROR);
2721 }
2722
2723 /* Call actual mDNS service delete service. */
2724 status = _nx_mdns_service_delete(mdns_ptr, name, type, sub_type);
2725
2726 /* Return status. */
2727 return(status);
2728 }
2729
2730 /**************************************************************************/
2731 /* */
2732 /* FUNCTION RELEASE */
2733 /* */
2734 /* _nx_mdns_service_delete PORTABLE C */
2735 /* 6.1 */
2736 /* AUTHOR */
2737 /* */
2738 /* Yuxin Zhou, Microsoft Corporation */
2739 /* */
2740 /* DESCRIPTION */
2741 /* */
2742 /* This function deletes the mDNS services. */
2743 /* */
2744 /* INPUT */
2745 /* */
2746 /* mdns_ptr Pointer to mDNS instance */
2747 /* name The name of the service */
2748 /* type The type of the service */
2749 /* subtype The subtype of the service */
2750 /* */
2751 /* OUTPUT */
2752 /* */
2753 /* status Completion status */
2754 /* */
2755 /* CALLS */
2756 /* */
2757 /* _nx_mdns_service_delete_internal Actual service delete function*/
2758 /* */
2759 /* CALLED BY */
2760 /* */
2761 /* Application Code */
2762 /* */
2763 /* RELEASE HISTORY */
2764 /* */
2765 /* DATE NAME DESCRIPTION */
2766 /* */
2767 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2768 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2769 /* resulting in version 6.1 */
2770 /* */
2771 /**************************************************************************/
_nx_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2772 UINT _nx_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2773 {
2774
2775 UINT i;
2776 UINT status = NX_MDNS_NOT_ENABLED;
2777 UINT service_delete_success = NX_FALSE;
2778
2779 /* Delete service from all enabled interfaces. */
2780 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i ++)
2781 {
2782
2783 /* Call actual mDNS service delete service. */
2784 status = _nx_mdns_service_interface_delete(mdns_ptr, name, type, sub_type, i);
2785
2786 /* Check status. */
2787 if (status == NX_MDNS_SUCCESS)
2788 {
2789 service_delete_success = NX_TRUE;
2790 }
2791 }
2792
2793 /* Check if delete service on all enabled interface. */
2794 if (service_delete_success)
2795 return(NX_MDNS_SUCCESS);
2796 else
2797 return(status);
2798 }
2799
2800
2801 /**************************************************************************/
2802 /* */
2803 /* FUNCTION RELEASE */
2804 /* */
2805 /* _nx_mdns_service_interface_delete PORTABLE C */
2806 /* 6.1 */
2807 /* AUTHOR */
2808 /* */
2809 /* Yuxin Zhou, Microsoft Corporation */
2810 /* */
2811 /* DESCRIPTION */
2812 /* */
2813 /* This function deletes the mDNS services, and remove SRV and TXT */
2814 /* records from local buffer. */
2815 /* */
2816 /* INPUT */
2817 /* */
2818 /* mdns_ptr Pointer to mDNS instance */
2819 /* name The name of the service */
2820 /* type The type of the service */
2821 /* subtype The subtype of the service */
2822 /* interface_index The interface index */
2823 /* */
2824 /* OUTPUT */
2825 /* */
2826 /* status Completion status */
2827 /* */
2828 /* CALLS */
2829 /* */
2830 /* tx_mutex_get Get the mDNS mutex */
2831 /* tx_mutex_put Put the mDNS mutex */
2832 /* _nx_mdns_service_name_assemble Assemble the service name */
2833 /* _nx_mdns_name_match Match the name string */
2834 /* _nx_mdns_rr_delete Delete the resource record */
2835 /* */
2836 /* CALLED BY */
2837 /* */
2838 /* Application Code */
2839 /* */
2840 /* RELEASE HISTORY */
2841 /* */
2842 /* DATE NAME DESCRIPTION */
2843 /* */
2844 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2845 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2846 /* resulting in version 6.1 */
2847 /* */
2848 /**************************************************************************/
_nx_mdns_service_interface_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT interface_index)2849 UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index)
2850 {
2851
2852 UINT status;
2853 UINT found;
2854 UINT delete_flag;
2855 UINT type_index;
2856 ULONG *head;
2857 NX_MDNS_RR *p;
2858 UINT rr_name_length;
2859 UINT rr_ptr_name_length;
2860
2861 NX_PARAMETER_NOT_USED(sub_type);
2862
2863 /* Get the mDNS mutex. */
2864 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2865
2866 /* Initialize the parameters. */
2867 type_index = 0;
2868 delete_flag = NX_FALSE;
2869
2870 /* Construct the SRV name. */
2871 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);
2872
2873 /* Check the status. */
2874 if (status)
2875 {
2876
2877 /* Release the mDNS mutex. */
2878 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2879 return (status);
2880 }
2881
2882 /* Get head. */
2883 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2884 head = (ULONG*)(*head);
2885
2886 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2887 {
2888
2889 /* Clear the found value. */
2890 found = NX_FALSE;
2891
2892 /* Check the interface index. */
2893 if (p -> nx_mdns_rr_interface_index != interface_index)
2894 continue;
2895
2896 /* Check whether the resource record is valid. */
2897 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2898 continue;
2899
2900 /* Check string length. */
2901 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
2902 {
2903 continue;
2904 }
2905
2906 /* Compare the RDATA. */
2907 switch (p -> nx_mdns_rr_type)
2908 {
2909
2910 case NX_MDNS_RR_TYPE_SRV:
2911 case NX_MDNS_RR_TYPE_TXT:
2912 {
2913 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2914 {
2915 found = NX_TRUE;
2916 delete_flag = NX_TRUE;
2917 }
2918 break;
2919 }
2920 case NX_MDNS_RR_TYPE_PTR:
2921 {
2922
2923 /* Check string length. */
2924 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))
2925 {
2926 break;
2927 }
2928
2929 /* Find the PTR and Sub PTR resource record which pointer to the SRV resource record.*/
2930 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))
2931 {
2932 found = NX_TRUE;
2933 }
2934
2935 /* Find one DNS-SD PRT which pointer to the PTR resource record. */
2936 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)) &&
2937 (!_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)))
2938 {
2939
2940 /* Check the count. */
2941 if (p -> nx_mdns_rr_count)
2942 {
2943 p -> nx_mdns_rr_count --;
2944 }
2945 else
2946 {
2947
2948 /* Delete this resource record directly. */
2949 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2950 }
2951 }
2952 break;
2953 }
2954
2955 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2956 case NX_MDNS_RR_TYPE_NSEC:
2957 {
2958 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2959 {
2960
2961 /* Delete this resource record directly. */
2962 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2963 }
2964 break;
2965 }
2966 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
2967 }
2968
2969 if (found)
2970 {
2971
2972 /* Delete the resource records. */
2973 status = _nx_mdns_rr_delete(mdns_ptr, p);
2974
2975 /* Check the status. */
2976 if (status)
2977 {
2978 /* Release the mDNS mutex. */
2979 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2980
2981 return(status);
2982 }
2983 }
2984 }
2985
2986 /* Release the mDNS mutex. */
2987 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2988
2989 if (delete_flag == NX_TRUE)
2990 return(NX_MDNS_SUCCESS);
2991 else
2992 return(NX_MDNS_ERROR);
2993 }
2994 #endif /* NX_MDNS_DISABLE_SERVER */
2995
2996
2997 #ifndef NX_MDNS_DISABLE_CLIENT
2998 /**************************************************************************/
2999 /* */
3000 /* FUNCTION RELEASE */
3001 /* */
3002 /* _nxe_mdns_service_one_shot_query PORTABLE C */
3003 /* 6.1 */
3004 /* AUTHOR */
3005 /* */
3006 /* Yuxin Zhou, Microsoft Corporation */
3007 /* */
3008 /* DESCRIPTION */
3009 /* */
3010 /* This function checks for errors in the mDNS resource record query */
3011 /* add function call. */
3012 /* */
3013 /* INPUT */
3014 /* */
3015 /* mdns_ptr Pointer to mDNS instance */
3016 /* name The name of the service */
3017 /* type The type of the service */
3018 /* subtype The subtype of the service */
3019 /* service Pointer to response service */
3020 /* timeout The timeour for service query */
3021 /* */
3022 /* OUTPUT */
3023 /* */
3024 /* status Completion status */
3025 /* */
3026 /* CALLS */
3027 /* */
3028 /* _nx_mdns_service_one_shot_query Actual query service function */
3029 /* */
3030 /* CALLED BY */
3031 /* */
3032 /* Application Code */
3033 /* */
3034 /* RELEASE HISTORY */
3035 /* */
3036 /* DATE NAME DESCRIPTION */
3037 /* */
3038 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3039 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3040 /* resulting in version 6.1 */
3041 /* */
3042 /**************************************************************************/
_nxe_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3043 UINT _nxe_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3044 {
3045
3046 UINT status;
3047
3048
3049 /* Check for invalid input pointers. */
3050 if ((!mdns_ptr) || (!type) || (!service))
3051 {
3052 return(NX_PTR_ERROR);
3053 }
3054
3055 /* Check for mDNS started flag. */
3056 if (!mdns_ptr -> nx_mdns_started)
3057 {
3058 return(NX_MDNS_NOT_STARTED);
3059 }
3060
3061 /* Check for name. */
3062 if (name)
3063 {
3064
3065 /* Check the name size. */
3066 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3067 {
3068 return(NX_MDNS_DATA_SIZE_ERROR);
3069 }
3070 }
3071
3072 /* Check the type size. */
3073 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3074 {
3075 return(NX_MDNS_DATA_SIZE_ERROR);
3076 }
3077
3078 /* Check the sub type. */
3079 if (sub_type)
3080 {
3081
3082 /* Check the name size. */
3083 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3084 {
3085 return(NX_MDNS_DATA_SIZE_ERROR);
3086 }
3087 }
3088
3089 /* Call actual mDNS create service. */
3090 status = _nx_mdns_service_one_shot_query(mdns_ptr, name, type, sub_type, service, timeout);
3091
3092 /* Return status. */
3093 return(status);
3094 }
3095
3096
3097 /**************************************************************************/
3098 /* */
3099 /* FUNCTION RELEASE */
3100 /* */
3101 /* _nx_mdns_service_one_shot_query PORTABLE C */
3102 /* 6.1.11 */
3103 /* AUTHOR */
3104 /* */
3105 /* Yuxin Zhou, Microsoft Corporation */
3106 /* */
3107 /* DESCRIPTION */
3108 /* */
3109 /* This function starts service one-shot query on all enabled */
3110 /* interfaces. */
3111 /* */
3112 /* INPUT */
3113 /* */
3114 /* mdns_ptr Pointer to mDNS instance */
3115 /* name The name of the service */
3116 /* type The type of the service */
3117 /* subtype The subtype of the service */
3118 /* service Pointer to response service */
3119 /* timeout The timeour for service query */
3120 /* */
3121 /* OUTPUT */
3122 /* */
3123 /* status Completion status */
3124 /* */
3125 /* CALLS */
3126 /* */
3127 /* tx_mutex_get Get the mDNS mutex */
3128 /* tx_mutex_put Put the mDNS mutex */
3129 /* _nx_mdns_service_name_assemble Assemble the service name */
3130 /* _nx_mdns_service_name_resolve Resolve the service name */
3131 /* _nx_mdns_query Send the One Shot query */
3132 /* _nx_mdns_service_addition_info_get Get additional info of service*/
3133 /* */
3134 /* CALLED BY */
3135 /* */
3136 /* Application Code */
3137 /* */
3138 /* RELEASE HISTORY */
3139 /* */
3140 /* DATE NAME DESCRIPTION */
3141 /* */
3142 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3143 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
3144 /* verified memcpy use cases, */
3145 /* resulting in version 6.1 */
3146 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3147 /* fixed compiler warnings, */
3148 /* resulting in version 6.1.11 */
3149 /* */
3150 /**************************************************************************/
_nx_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3151 UINT _nx_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3152 {
3153
3154 UINT type_index;
3155 UINT status;
3156 NX_MDNS_RR *answer_rr;
3157 UCHAR *query_name;
3158 USHORT query_type;
3159 UINT i;
3160 UINT name_length;
3161
3162
3163 /* Get the mDNS mutex. */
3164 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3165
3166 /* Initialize the struct. */
3167 memset(service, 0, sizeof(NX_MDNS_SERVICE));
3168
3169 /* Loop to start one-shot query on all enabled interfaces until get the answer or query timeout. */
3170 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3171 {
3172
3173 /* Check if this interface is enabled. */
3174 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3175 continue;
3176
3177 /* Step1. Construct the query name and set the query type. */
3178 if (name)
3179 {
3180
3181 /* Construct the SRV name. */
3182 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);
3183
3184 /* Check the status. */
3185 if (status)
3186 {
3187
3188 /* Release the mDNS mutex. */
3189 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3190 return(status);
3191 }
3192
3193 /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT). */
3194 query_name = temp_string_buffer;
3195 query_type = NX_MDNS_RR_TYPE_ALL;
3196 }
3197 else
3198 {
3199
3200 /* Construct the PTR name. */
3201 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);
3202
3203 /* Check the status. */
3204 if (status)
3205 {
3206
3207 /* Release the mDNS mutex. */
3208 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3209 return (status);
3210 }
3211
3212 /* Set the query name and query type. */
3213 query_name = &temp_string_buffer[type_index];
3214 query_type = NX_MDNS_RR_TYPE_PTR;
3215 }
3216
3217 /* Step2. Start one shot query. */
3218 status = _nx_mdns_one_shot_query(mdns_ptr, query_name, query_type, &answer_rr, timeout, i);
3219
3220 /* Check the status. */
3221 if ((status == NX_SUCCESS) ||
3222 (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3223 (status == NX_MDNS_EXIST_SHARED_RR))
3224 {
3225
3226 /* Check the query type. */
3227 if (name)
3228 {
3229
3230 /* Store the service name from SRV record. */
3231 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_name, &name_length, NX_MDNS_NAME_MAX))
3232 {
3233
3234 /* Release the mDNS mutex. */
3235 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3236 return (NX_MDNS_DATA_SIZE_ERROR);
3237 }
3238 memcpy((char *)(service -> buffer), (char*)(answer_rr -> nx_mdns_rr_name), name_length); /* Use case of memcpy is verified. */
3239 }
3240 else
3241 {
3242
3243 /* Store the service name from PTR record. */
3244 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))
3245 {
3246
3247 /* Release the mDNS mutex. */
3248 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3249 return (NX_MDNS_DATA_SIZE_ERROR);
3250 }
3251 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. */
3252 }
3253
3254 /* Get the additional information of service. */
3255 _nx_mdns_service_addition_info_get(mdns_ptr, service -> buffer, service, i);
3256
3257 /* Reslove the service name. */
3258 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
3259
3260 /* Check status. */
3261 if (status)
3262 continue;
3263
3264 /* Release the mDNS mutex. */
3265 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3266
3267 /* Return success. */
3268 return (NX_MDNS_SUCCESS);
3269 }
3270 }
3271
3272 /* Release the mDNS mutex. */
3273 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3274
3275 /* Return error. */
3276 return (NX_MDNS_ERROR);
3277 }
3278
3279
3280 /**************************************************************************/
3281 /* */
3282 /* FUNCTION RELEASE */
3283 /* */
3284 /* _nx_mdns_one_shot_query PORTABLE C */
3285 /* 6.1.11 */
3286 /* AUTHOR */
3287 /* */
3288 /* Yuxin Zhou, Microsoft Corporation */
3289 /* */
3290 /* DESCRIPTION */
3291 /* */
3292 /* This function adds the mDNS resource record into remote buffer, */
3293 /* mDNS thread send the query message. */
3294 /* */
3295 /* INPUT */
3296 /* */
3297 /* mdns_ptr Pointer to mDNS instance */
3298 /* name The resource record name */
3299 /* type The resource record type */
3300 /* out_rr Pointer to response RR */
3301 /* one_shot One shot or continuous */
3302 /* wait_option Wait option */
3303 /* */
3304 /* OUTPUT */
3305 /* */
3306 /* status Completion status */
3307 /* */
3308 /* CALLS */
3309 /* */
3310 /* tx_mutex_get Get the mDNS mutex */
3311 /* tx_mutex_put Put the mDNS mutex */
3312 /* _tx_thread_system_suspend Suspend the thread */
3313 /* _nx_mdns_query_check Check the query RR */
3314 /* _nx_mdns_cache_add_string Add the string into cache */
3315 /* _nx_mdns_cache_delete_string Delete the string from cache */
3316 /* _nx_mdns_cache_add_resource_record Add the resource record */
3317 /* into cache */
3318 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
3319 /* from cache */
3320 /* */
3321 /* CALLED BY */
3322 /* */
3323 /* Application Code */
3324 /* */
3325 /* RELEASE HISTORY */
3326 /* */
3327 /* DATE NAME DESCRIPTION */
3328 /* */
3329 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3330 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3331 /* resulting in version 6.1 */
3332 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3333 /* corrected the random value, */
3334 /* fixed the issue of timer, */
3335 /* resulting in version 6.1.11 */
3336 /* */
3337 /**************************************************************************/
_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 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)
3339 {
3340
3341 UINT status;
3342 NX_MDNS_RR *rr;
3343 NX_MDNS_RR *insert_rr;
3344 NX_MDNS_RR temp_resource_record;
3345 UINT name_length;
3346
3347
3348 /* Clear the return record. */
3349 *out_rr = NX_NULL;
3350
3351 /* Check the query RR. */
3352 status = _nx_mdns_query_check(mdns_ptr, name, type, NX_TRUE, &rr, interface_index);
3353
3354 /* Check the state. */
3355 if (status)
3356 {
3357
3358 /* Whether exists unique resource record in cache. */
3359 if ((status == NX_MDNS_EXIST_UNIQUE_RR) ||
3360 (status == NX_MDNS_EXIST_SHARED_RR))
3361 {
3362 *out_rr = rr;
3363 return (NX_MDNS_SUCCESS);
3364 }
3365 else
3366 {
3367 return(status);
3368 }
3369 }
3370
3371 if (wait_option != 0)
3372 {
3373
3374 /* Initialize the struct. */
3375 memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3376
3377 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3378 {
3379 return (NX_MDNS_DATA_SIZE_ERROR);
3380 }
3381
3382 /* Add the name. */
3383 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3384 (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3385
3386 /* Check for error. */
3387 if (status)
3388 {
3389 return(status);
3390 }
3391
3392 /* Add the parameters. */
3393 temp_resource_record.nx_mdns_rr_type = type;
3394 temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3395
3396 /* Set the resource record status. */
3397 temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3398
3399 /* Remote resource record, set the owner flag. */
3400 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3401
3402 /* Set the interface index. */
3403 temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3404
3405 /* Add the resource record. */
3406 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3407
3408 /* Check for error. */
3409 if (status)
3410 {
3411
3412 /* Delete the same strings. */
3413 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3414 return(status);
3415 }
3416
3417 /* A multicast DNS querier should also delay the first query of the series by
3418 a randomly chosen amount in the range 20-120ms. */
3419 insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3420 insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3421
3422 /* Set the mDNS timer. */
3423 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3424
3425 /* Release the mDNS mutex to process response. */
3426 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3427
3428 /* Suspend the thread on this mDNS query attempt. */
3429 _nx_mdns_query_thread_suspend(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), _nx_mdns_query_cleanup, mdns_ptr, out_rr, wait_option);
3430
3431 /* Get the mDNS mutex. */
3432 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3433
3434 /* Determine if a packet was received successfully. */
3435 if (_tx_thread_current_ptr -> tx_thread_suspend_status != NX_MDNS_SUCCESS)
3436 {
3437
3438 /* Delete the query resource record. */
3439 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, insert_rr);
3440 }
3441
3442 /* Return the status. */
3443 return(_tx_thread_current_ptr -> tx_thread_suspend_status);
3444 }
3445 else
3446 {
3447
3448 /* Immediate return, return error completion. */
3449 return(NX_MDNS_NO_RR);
3450 }
3451 }
3452
3453
3454 /**************************************************************************/
3455 /* */
3456 /* FUNCTION RELEASE */
3457 /* */
3458 /* _nxe_mdns_service_continuous_query PORTABLE C */
3459 /* 6.1 */
3460 /* AUTHOR */
3461 /* */
3462 /* Yuxin Zhou, Microsoft Corporation */
3463 /* */
3464 /* DESCRIPTION */
3465 /* */
3466 /* This function checks for errors in the mDNS resource record query */
3467 /* add function call. */
3468 /* */
3469 /* INPUT */
3470 /* */
3471 /* mdns_ptr Pointer to mDNS instance */
3472 /* name The name of the service */
3473 /* type The type of the service */
3474 /* subtype The subtype of the service */
3475 /* */
3476 /* OUTPUT */
3477 /* */
3478 /* status Completion status */
3479 /* */
3480 /* CALLS */
3481 /* */
3482 /* _nx_mdns_service_continuous_query Actual mDNS query RR function */
3483 /* */
3484 /* CALLED BY */
3485 /* */
3486 /* Application Code */
3487 /* */
3488 /* RELEASE HISTORY */
3489 /* */
3490 /* DATE NAME DESCRIPTION */
3491 /* */
3492 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3493 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3494 /* resulting in version 6.1 */
3495 /* */
3496 /**************************************************************************/
_nxe_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3497 UINT _nxe_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3498 {
3499
3500 UINT status;
3501
3502
3503 /* Check for invalid input pointers. */
3504 if (!mdns_ptr)
3505 {
3506 return(NX_PTR_ERROR);
3507 }
3508
3509 /* Check for invalid server attributes. */
3510 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3511 {
3512 return(NX_MDNS_PARAM_ERROR);
3513 }
3514
3515 /* Check for mDNS stareted flag. */
3516 if (!mdns_ptr -> nx_mdns_started)
3517 {
3518 return(NX_MDNS_NOT_STARTED);
3519 }
3520
3521 /* Check the type. If the type is null,indicate lookup the all service type, the name and sub type must be null. */
3522 if (!type)
3523 {
3524 if ((name) || (sub_type))
3525 {
3526 return(NX_MDNS_PARAM_ERROR);
3527 }
3528 }
3529 else
3530 {
3531
3532 /* Check the name, If the name is non-null, the sub type must be null. */
3533 if ((name) && (sub_type))
3534 {
3535 return(NX_MDNS_PARAM_ERROR);
3536 }
3537 }
3538
3539 /* Check the name. */
3540 if (name)
3541 {
3542
3543 /* Check the name size. */
3544 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3545 {
3546 return(NX_MDNS_DATA_SIZE_ERROR);
3547 }
3548 }
3549
3550 /* Check the type. */
3551 if (type)
3552 {
3553
3554 /* Check the type size. */
3555 if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3556 {
3557 return(NX_MDNS_DATA_SIZE_ERROR);
3558 }
3559 }
3560
3561 /* Check the sub type. */
3562 if (sub_type)
3563 {
3564
3565 /* Check the sub type size. */
3566 if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3567 {
3568 return(NX_MDNS_DATA_SIZE_ERROR);
3569 }
3570 }
3571
3572 /* Call actual mDNS create service. */
3573 status = _nx_mdns_service_continuous_query(mdns_ptr, name, type, sub_type);
3574
3575 /* Return status. */
3576 return(status);
3577 }
3578
3579
3580 /**************************************************************************/
3581 /* */
3582 /* FUNCTION RELEASE */
3583 /* */
3584 /* _nx_mdns_service_continuous_query PORTABLE C */
3585 /* 6.1 */
3586 /* AUTHOR */
3587 /* */
3588 /* Yuxin Zhou, Microsoft Corporation */
3589 /* */
3590 /* DESCRIPTION */
3591 /* */
3592 /* This function starts service continuous query on all enabled */
3593 /* interfaces. */
3594 /* */
3595 /* INPUT */
3596 /* */
3597 /* mdns_ptr Pointer to mDNS instance */
3598 /* name The name of the service */
3599 /* type The type of the service */
3600 /* subtype The subtype of the service */
3601 /* */
3602 /* OUTPUT */
3603 /* */
3604 /* status Completion status */
3605 /* */
3606 /* CALLS */
3607 /* */
3608 /* tx_mutex_get Get the mDNS mutex */
3609 /* tx_mutex_put Put the mDNS mutex */
3610 /* _nx_mdns_service_name_assemble Assemble the service name */
3611 /* _nx_mdns_service_name_resolve Resolve the service name */
3612 /* _nx_mdns_query Send the One Shot query */
3613 /* _nx_mdns_service_addition_info_get Get additional info of service*/
3614 /* */
3615 /* CALLED BY */
3616 /* */
3617 /* Application Code */
3618 /* */
3619 /* RELEASE HISTORY */
3620 /* */
3621 /* DATE NAME DESCRIPTION */
3622 /* */
3623 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3624 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3625 /* resulting in version 6.1 */
3626 /* */
3627 /**************************************************************************/
_nx_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3628 UINT _nx_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3629 {
3630
3631 UINT status = NX_MDNS_ERROR;
3632 UINT type_index;
3633 UCHAR *query_name;
3634 USHORT query_type;
3635 UINT query_success = NX_FALSE;
3636 UINT i;
3637
3638
3639 /* Get the mDNS mutex. */
3640 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3641
3642 /* Step1. Construct the query name and set the query type. */
3643 /* Check the type. if the type is null, indicate search all service. */
3644 if (!type)
3645 {
3646
3647 /* Set the query name and query type. */
3648 query_name = (UCHAR *)_nx_mdns_dns_sd;
3649 query_type = NX_MDNS_RR_TYPE_PTR;
3650 }
3651 else if (name)
3652 {
3653
3654 /* Construct the SRV name. */
3655 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);
3656
3657 /* Check the status. */
3658 if (status)
3659 {
3660
3661 /* Release the mDNS mutex. */
3662 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3663 return (status);
3664 }
3665
3666 /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT). */
3667 query_name = temp_string_buffer;
3668 query_type = NX_MDNS_RR_TYPE_ALL;
3669 }
3670 else
3671 {
3672
3673 /* Construct the PTR name. */
3674 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);
3675
3676 /* Check the status. */
3677 if (status)
3678 {
3679
3680 /* Release the mDNS mutex. */
3681 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3682 return (status);
3683 }
3684
3685 /* Set the query name and query type. */
3686 query_name = &temp_string_buffer[type_index];
3687 query_type = NX_MDNS_RR_TYPE_PTR;
3688 }
3689
3690 /* Step2. Loop to start continuous query on all enabled interfaces. */
3691 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3692 {
3693
3694 /* Check if this interface is enabled. */
3695 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3696 continue;
3697
3698 /* Start continuous query. */
3699 status = _nx_mdns_continuous_query(mdns_ptr, query_name, query_type, i);
3700
3701 /* Check the status. */
3702 if ((status == NX_SUCCESS) ||
3703 (status == NX_MDNS_EXIST_SAME_QUERY) ||
3704 (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3705 (status == NX_MDNS_EXIST_SHARED_RR))
3706 query_success = NX_TRUE;
3707 }
3708
3709 /* Release the mDNS mutex. */
3710 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3711
3712 /* Check if start continuous query success. */
3713 if (query_success)
3714 return (NX_MDNS_SUCCESS);
3715 else
3716 return(status);
3717 }
3718
3719
3720 /**************************************************************************/
3721 /* */
3722 /* FUNCTION RELEASE */
3723 /* */
3724 /* _nx_mdns_continuous_query PORTABLE C */
3725 /* 6.1.11 */
3726 /* AUTHOR */
3727 /* */
3728 /* Yuxin Zhou, Microsoft Corporation */
3729 /* */
3730 /* DESCRIPTION */
3731 /* */
3732 /* This function starts continuous query on specified interfaces. */
3733 /* */
3734 /* INPUT */
3735 /* */
3736 /* mdns_ptr Pointer to mDNS instance */
3737 /* interface_index The interface index */
3738 /* name The resource record name */
3739 /* type The resource record type */
3740 /* */
3741 /* OUTPUT */
3742 /* */
3743 /* status Completion status */
3744 /* */
3745 /* CALLS */
3746 /* */
3747 /* tx_mutex_get Get the mDNS mutex */
3748 /* tx_mutex_put Put the mDNS mutex */
3749 /* _nx_mdns_query_check Check the query RR */
3750 /* _nx_mdns_cache_add_string Add the string into cache */
3751 /* _nx_mdns_cache_delete_string Delete the string from cache */
3752 /* _nx_mdns_cache_add_resource_record Add the resource record */
3753 /* into cache */
3754 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
3755 /* from cache */
3756 /* */
3757 /* CALLED BY */
3758 /* */
3759 /* Application Code */
3760 /* */
3761 /* RELEASE HISTORY */
3762 /* */
3763 /* DATE NAME DESCRIPTION */
3764 /* */
3765 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3766 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3767 /* resulting in version 6.1 */
3768 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
3769 /* corrected the random value, */
3770 /* fixed the issue of timer, */
3771 /* resulting in version 6.1.11 */
3772 /* */
3773 /**************************************************************************/
_nx_mdns_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT interface_index)3774 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index)
3775 {
3776
3777 UINT status;
3778 NX_MDNS_RR *insert_rr;
3779 NX_MDNS_RR temp_resource_record;
3780 UINT name_length;
3781
3782
3783 /* Check the query RR. */
3784 status = _nx_mdns_query_check(mdns_ptr, name, type, NX_FALSE, NX_NULL, interface_index);
3785
3786 /* Check the state. */
3787 if (status)
3788 {
3789 return(status);
3790 }
3791
3792 /* Initialize the struct. */
3793 memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3794
3795 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3796 {
3797 return (NX_MDNS_DATA_SIZE_ERROR);
3798 }
3799
3800 /* Add the name. */
3801 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3802 (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3803
3804 /* Check for error. */
3805 if (status)
3806 {
3807 return(status);
3808 }
3809
3810 /* Add the parameters. */
3811 temp_resource_record.nx_mdns_rr_type = type;
3812 temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3813
3814 /* Set the resource record status. */
3815 temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3816
3817 /* Remote resource record, set the owner flag. */
3818 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3819
3820 /* Continuous query, set the query type flag. */
3821 if ((type != NX_MDNS_RR_TYPE_A) &&
3822 (type != NX_MDNS_RR_TYPE_AAAA))
3823 {
3824 temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_CONTINUOUS_QUERY);
3825 }
3826
3827 /* Set the interface index. */
3828 temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3829
3830 /* Add the resource record. */
3831 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3832
3833 /* Check for error. */
3834 if (status)
3835 {
3836
3837 /* Delete the same strings. */
3838 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3839 return(status);
3840 }
3841
3842 /* A multicast DNS querier should also delay the first query of the series by
3843 a randomly chosen amount in the range 20-120ms. */
3844 insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3845 insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3846
3847 /* Set the mDNS timer. */
3848 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3849
3850 /* Return success. */
3851 return NX_SUCCESS;
3852 }
3853
3854
3855 /**************************************************************************/
3856 /* */
3857 /* FUNCTION RELEASE */
3858 /* */
3859 /* _nxe_mdns_service_query_stop PORTABLE C */
3860 /* 6.1 */
3861 /* AUTHOR */
3862 /* */
3863 /* Yuxin Zhou, Microsoft Corporation */
3864 /* */
3865 /* DESCRIPTION */
3866 /* */
3867 /* This function checks for errors in the mDNS resource record query */
3868 /* add function call. */
3869 /* */
3870 /* INPUT */
3871 /* */
3872 /* mdns_ptr Pointer to mDNS instance */
3873 /* name The name of the service */
3874 /* type The type of the service */
3875 /* subtype The subtype of the service */
3876 /* */
3877 /* OUTPUT */
3878 /* */
3879 /* status Completion status */
3880 /* */
3881 /* CALLS */
3882 /* */
3883 /* _nx_mdns_service_query_stop Actual query RR function */
3884 /* */
3885 /* CALLED BY */
3886 /* */
3887 /* Application Code */
3888 /* */
3889 /* RELEASE HISTORY */
3890 /* */
3891 /* DATE NAME DESCRIPTION */
3892 /* */
3893 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3894 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3895 /* resulting in version 6.1 */
3896 /* */
3897 /**************************************************************************/
_nxe_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3898 UINT _nxe_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3899 {
3900
3901 UINT status;
3902
3903
3904 /* Check for invalid input pointers. */
3905 if (!mdns_ptr)
3906 {
3907 return(NX_PTR_ERROR);
3908 }
3909
3910 /* Check for invalid server attributes. */
3911 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3912 {
3913 return(NX_MDNS_PARAM_ERROR);
3914 }
3915
3916 if (name)
3917 {
3918
3919 /* Check the size. */
3920 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
3921 {
3922 return(NX_MDNS_DATA_SIZE_ERROR);
3923 }
3924 }
3925
3926 /* Call actual mDNS create service. */
3927 status = _nx_mdns_service_query_stop(mdns_ptr, name, type, sub_type);
3928
3929 /* Return status. */
3930 return(status);
3931 }
3932
3933
3934 /**************************************************************************/
3935 /* */
3936 /* FUNCTION RELEASE */
3937 /* */
3938 /* _nx_mdns_service_query_stop PORTABLE C */
3939 /* 6.1 */
3940 /* AUTHOR */
3941 /* */
3942 /* Yuxin Zhou, Microsoft Corporation */
3943 /* */
3944 /* DESCRIPTION */
3945 /* */
3946 /* This function adds the mDNS resource record into peer service cache,*/
3947 /* mDNS thread send the query message using continuous type. */
3948 /* */
3949 /* INPUT */
3950 /* */
3951 /* mdns_ptr Pointer to mDNS instance */
3952 /* name The name of the service */
3953 /* type The type of the service */
3954 /* subtype The subtype of the service */
3955 /* */
3956 /* OUTPUT */
3957 /* */
3958 /* status Completion status */
3959 /* */
3960 /* CALLS */
3961 /* */
3962 /* tx_mutex_get Get the mDNS mutex */
3963 /* tx_mutex_put Put the mDNS mutex */
3964 /* _nx_mdns_service_name_assemble Assemble the service name */
3965 /* _nx_mdns_name_match Match the name string */
3966 /* _nx_mdns_rr_delete Delete the resource record */
3967 /* */
3968 /* CALLED BY */
3969 /* */
3970 /* Application Code */
3971 /* */
3972 /* RELEASE HISTORY */
3973 /* */
3974 /* DATE NAME DESCRIPTION */
3975 /* */
3976 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3977 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3978 /* resulting in version 6.1 */
3979 /* */
3980 /**************************************************************************/
_nx_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3981 UINT _nx_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3982 {
3983
3984 UINT status;
3985 UINT type_index = 0;
3986 UINT query_stop = NX_FALSE;
3987 ULONG *head;
3988 NX_MDNS_RR *p;
3989 UINT rr_name_length;
3990
3991
3992 /* Get the mDNS mutex. */
3993 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3994
3995 if (type)
3996 {
3997 if (name)
3998 {
3999
4000 /* Construct the SRV name. */
4001 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);
4002
4003 /* Check the status. */
4004 if (status)
4005 {
4006
4007 /* Release the mDNS mutex. */
4008 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4009 return (status);
4010 }
4011 }
4012 else
4013 {
4014
4015 /* Construct the PTR name. */
4016 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);
4017
4018 /* Check the status. */
4019 if (status)
4020 {
4021
4022 /* Release the mDNS mutex. */
4023 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4024 return (status);
4025 }
4026 }
4027 }
4028
4029 /* Get the remote buffer head. */
4030 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4031
4032 if (!head)
4033 {
4034
4035 /* Release the mDNS mutex. */
4036 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4037
4038 /* Return a successful status. */
4039 return(NX_MDNS_CACHE_ERROR);
4040 }
4041
4042 /* Set the pointer. */
4043 head = (ULONG*)(*head);
4044
4045 /* Loop to delete query resource record. */
4046 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
4047 {
4048
4049 /* Check the resource record state. */
4050 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
4051 continue;
4052
4053 /* Check string length. */
4054 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
4055 {
4056 continue;
4057 }
4058
4059 if (!type)
4060 {
4061 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
4062 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
4063 {
4064
4065 /* Delete the resource records. */
4066 status = _nx_mdns_rr_delete(mdns_ptr, p);
4067
4068 /* Check status. */
4069 if (status == NX_MDNS_SUCCESS)
4070 query_stop = NX_TRUE;
4071 }
4072 }
4073 else
4074 {
4075 if (name)
4076 {
4077 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) &&
4078 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length)))
4079 {
4080
4081 /* Delete the resource records. */
4082 status = _nx_mdns_rr_delete(mdns_ptr, p);
4083
4084 /* Check status. */
4085 if (status == NX_MDNS_SUCCESS)
4086 query_stop = NX_TRUE;
4087 }
4088 }
4089 else
4090 {
4091 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)&&
4092 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[type_index], rr_name_length)))
4093 {
4094
4095 /* Delete the resource records. */
4096 status = _nx_mdns_rr_delete(mdns_ptr, p);
4097
4098 /* Check status. */
4099 if (status == NX_MDNS_SUCCESS)
4100 query_stop = NX_TRUE;
4101 }
4102 }
4103 }
4104 }
4105
4106 /* Release the mDNS mutex. */
4107 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4108
4109 /* Check if stop service continuous query. */
4110 if (query_stop == NX_TRUE)
4111 return(NX_MDNS_SUCCESS);
4112 else
4113 return(NX_MDNS_ERROR);
4114 }
4115
4116
4117 /**************************************************************************/
4118 /* */
4119 /* FUNCTION RELEASE */
4120 /* */
4121 /* _nxe_mdns_service_lookup PORTABLE C */
4122 /* 6.1 */
4123 /* AUTHOR */
4124 /* */
4125 /* Yuxin Zhou, Microsoft Corporation */
4126 /* */
4127 /* DESCRIPTION */
4128 /* */
4129 /* This function checks for errors in the mDNS resource record query */
4130 /* add function call. */
4131 /* */
4132 /* INPUT */
4133 /* */
4134 /* mdns_ptr Pointer to mDNS instance */
4135 /* name The name of the service */
4136 /* type The type of the service */
4137 /* subtype The subtype of the service */
4138 /* service_index The index of the service */
4139 /* service Pointer to Service instance */
4140 /* */
4141 /* OUTPUT */
4142 /* */
4143 /* status Completion status */
4144 /* */
4145 /* CALLS */
4146 /* */
4147 /* _nx_mdns_service_lookup Actual mDNS query RR function */
4148 /* */
4149 /* CALLED BY */
4150 /* */
4151 /* Application Code */
4152 /* */
4153 /* RELEASE HISTORY */
4154 /* */
4155 /* DATE NAME DESCRIPTION */
4156 /* */
4157 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4158 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4159 /* resulting in version 6.1 */
4160 /* */
4161 /**************************************************************************/
_nxe_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4162 UINT _nxe_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4163 {
4164
4165 UINT status;
4166
4167
4168 /* Check for invalid input pointers. */
4169 if (!mdns_ptr)
4170 {
4171 return(NX_PTR_ERROR);
4172 }
4173
4174 /* Check for invalid server attributes. */
4175 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4176 {
4177 return(NX_MDNS_PARAM_ERROR);
4178 }
4179
4180 if (name)
4181 {
4182
4183 /* Check the size. */
4184 if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
4185 {
4186 return(NX_MDNS_DATA_SIZE_ERROR);
4187 }
4188 }
4189
4190 /* Call actual mDNS create service. */
4191 status = _nx_mdns_service_lookup(mdns_ptr, name, type, sub_type, service_index, service);
4192
4193 /* Return status. */
4194 return(status);
4195 }
4196
4197
4198 /**************************************************************************/
4199 /* */
4200 /* FUNCTION RELEASE */
4201 /* */
4202 /* _nx_mdns_service_lookup PORTABLE C */
4203 /* 6.1.11 */
4204 /* AUTHOR */
4205 /* */
4206 /* Yuxin Zhou, Microsoft Corporation */
4207 /* */
4208 /* DESCRIPTION */
4209 /* */
4210 /* This function adds the mDNS resource record into peer service cache,*/
4211 /* mDNS thread send the query message using continuous type. */
4212 /* */
4213 /* INPUT */
4214 /* */
4215 /* mdns_ptr Pointer to mDNS instance */
4216 /* name The name of the service */
4217 /* type The type of the service */
4218 /* subtype The subtype of the service */
4219 /* service_index The index of the service */
4220 /* service Pointer to Service instance */
4221 /* */
4222 /* OUTPUT */
4223 /* */
4224 /* status Completion status */
4225 /* */
4226 /* CALLS */
4227 /* */
4228 /* tx_mutex_get Get the mDNS mutex */
4229 /* tx_mutex_put Put the mDNS mutex */
4230 /* tx_time_get Get the time */
4231 /* _nx_mdns_service_name_assemble Assemble the service name */
4232 /* _nx_mdns_service_name_resolve Resolve the service name */
4233 /* _nx_mdns_service_addition_info_get Get additional info of service*/
4234 /* _nx_mdns_name_match Match the name string */
4235 /* */
4236 /* CALLED BY */
4237 /* */
4238 /* Application Code */
4239 /* */
4240 /* RELEASE HISTORY */
4241 /* */
4242 /* DATE NAME DESCRIPTION */
4243 /* */
4244 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4245 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4246 /* verified memcpy use cases, */
4247 /* resulting in version 6.1 */
4248 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
4249 /* fixed compiler warnings, */
4250 /* resulting in version 6.1.11 */
4251 /* */
4252 /**************************************************************************/
_nx_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4253 UINT _nx_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4254 {
4255
4256 UINT status;
4257 UINT type_index;
4258 UINT dns_sd_flag;
4259 UINT sub_type_flag;
4260 UINT index;
4261 UINT count;
4262 UINT found;
4263 UCHAR *srv_name = NX_NULL;
4264 UCHAR *ptr;
4265 UCHAR *tmp_sub_type;
4266 UCHAR *tmp_type;
4267 UCHAR *tmp_domain;
4268 NX_MDNS_RR *p = NX_NULL;
4269 NX_MDNS_RR *p1;
4270 ULONG *head, *tail;
4271 UCHAR i;
4272 UINT interface_index = 0;
4273 UINT temp_string_length;
4274 UINT dns_sd_length;
4275 UINT srv_name_length;
4276 UINT target_string_length;
4277
4278
4279 /* Get the mDNS mutex. */
4280 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4281
4282 /* Zero out the content of service */
4283 memset(service, 0, sizeof(NX_MDNS_SERVICE));
4284
4285 /* Initialize the struct. */
4286 count = 0;
4287 found = NX_FALSE;
4288
4289 /* Check the type. */
4290 if (type)
4291 {
4292 if (name)
4293 {
4294
4295 /* Construct the Service name. */
4296 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);
4297
4298 }
4299 else
4300 {
4301
4302 /* Construct the Service name. */
4303 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);
4304 }
4305 /* Check the status. */
4306 if (status)
4307 {
4308
4309 /* Release the mDNS mutex. */
4310 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4311 return (status);
4312 }
4313
4314 /* Check string length. */
4315 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
4316 {
4317
4318 /* Release the mDNS mutex. */
4319 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4320 return (NX_MDNS_DATA_SIZE_ERROR);
4321 }
4322 }
4323
4324 /* Check the DNS-SD string. */
4325 if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_length, NX_MDNS_DNS_SD_MAX))
4326 {
4327
4328 /* Release the mDNS mutex. */
4329 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4330 return (NX_MDNS_DATA_SIZE_ERROR);
4331 }
4332
4333 /* Loop to search local and peer cache. */
4334 for(i = 0; i < 2; i++)
4335 {
4336
4337 /* Set the pointer. */
4338 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
4339 {
4340 #ifndef NX_MDNS_DISABLE_SERVER
4341 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
4342 #else
4343 continue;
4344 #endif /* NX_MDNS_DISABLE_SERVER */
4345 }
4346 else
4347 {
4348 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4349 }
4350
4351 if(head == NX_NULL)
4352 continue;
4353
4354 /* Set the pointer. */
4355 tail = (ULONG*)(*head);
4356
4357 /* Check the resource record. */
4358 for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
4359 {
4360
4361 /* Check whether the resource record is valid. */
4362 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4363 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4364 continue;
4365
4366 if((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) || (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4367 {
4368
4369 if(type)
4370 {
4371 if (_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], temp_string_length))
4372 continue;
4373 }
4374 else if(p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
4375 continue;
4376
4377 if(name && (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4378 {
4379
4380 /* Store the service name. */
4381 srv_name = p -> nx_mdns_rr_name;
4382 interface_index = p -> nx_mdns_rr_interface_index;
4383 }
4384 else
4385 {
4386
4387 /* Set the service name pointer. */
4388 srv_name = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name;
4389 interface_index = p -> nx_mdns_rr_interface_index;
4390 }
4391
4392 /* Check string length. */
4393 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
4394 continue;
4395
4396 /* Store the service name. */
4397 memcpy((CHAR *)(service -> buffer), (CHAR *)srv_name, srv_name_length + 1); /* Use case of memcpy is verified. */
4398
4399 /* Reslove the service name and check the PTR rdata name. Ignore the PTR when the PTR rdata does not pointer the service. */
4400 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
4401
4402 if (status)
4403 continue;
4404
4405 if(type == NX_NULL)
4406 {
4407
4408 /* Set the parameters. */
4409 sub_type_flag = NX_FALSE;
4410 dns_sd_flag = NX_FALSE;
4411 index = 0;
4412
4413 /* Check the PTR resource record with sub type. */
4414 ptr = p -> nx_mdns_rr_name;
4415 while (*ptr != '\0')
4416 {
4417 if (*ptr == '.')
4418 {
4419 if (!_nx_mdns_name_match(ptr - index, (UCHAR *)"_sub", 4))
4420 {
4421 sub_type_flag = NX_TRUE;
4422 break;
4423 }
4424 index = 0;
4425 }
4426 else
4427 index ++;
4428 ptr ++;
4429 }
4430 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_length))
4431 {
4432 dns_sd_flag = NX_TRUE;
4433 }
4434
4435 /* Check the DNS-SD PTR reousrce record. */
4436 if ((dns_sd_flag == NX_TRUE) ||
4437 (sub_type_flag == NX_TRUE))
4438 {
4439
4440 /* Find the PTR resource record which pointer to the service. */
4441 for(p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
4442 {
4443
4444 /* Check whether the resource record is valid. */
4445 if ((p1 == p) ||
4446 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4447 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4448 continue;
4449
4450 /* Check the interface index. */
4451 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
4452 continue;
4453
4454 if (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
4455 {
4456 if ((dns_sd_flag == NX_TRUE))
4457 {
4458
4459 /* Check string length. */
4460 if (_nx_utility_string_length_check((CHAR *)(p1 -> nx_mdns_rr_name), &target_string_length, NX_MDNS_NAME_MAX))
4461 {
4462 continue;
4463 }
4464
4465 /* Set the pointer. */
4466 memcpy((CHAR *)&target_string_buffer[0], (CHAR *)(p1 -> nx_mdns_rr_name), target_string_length + 1); /* Use case of memcpy is verified. */
4467
4468 /* Reslove the type. */
4469 status = _nx_mdns_service_name_resolve(&target_string_buffer[0], &tmp_sub_type, &tmp_type, &tmp_domain);
4470
4471 if (status)
4472 continue;
4473
4474 /* Check string length. */
4475 if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4476 {
4477 continue;
4478 }
4479
4480 /* Construct the type and doamin, _http._tcp.local. */
4481 *(tmp_type + target_string_length) = '.';
4482
4483 /* Check string length. */
4484 if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4485 {
4486 continue;
4487 }
4488
4489 /* Compare the DNS_SD rdata. */
4490 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))
4491 {
4492
4493 /* Exist resource record including more info. */
4494 count --;
4495 break;
4496 }
4497 }
4498 else
4499 {
4500
4501 /* Exist the PTR RR which pointer to the same service. */
4502 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)
4503 {
4504 count --;
4505 break;
4506 }
4507 }
4508 }
4509 }
4510 }
4511 }
4512
4513 /* Check the count state. */
4514 if (count == service_index)
4515 {
4516 /* Yes, find. */
4517 found = NX_TRUE;
4518 break;
4519 }
4520 count ++;
4521 }
4522 }
4523
4524 /* Check if find the service. */
4525 if (found == NX_TRUE)
4526 {
4527 break;
4528 }
4529 }
4530
4531 if (found)
4532 {
4533
4534 /* Update the elasped time. */
4535 p -> nx_mdns_rr_elapsed_time = tx_time_get();
4536
4537 /* Get the additional information. */
4538 _nx_mdns_service_addition_info_get(mdns_ptr, srv_name, service, interface_index);
4539
4540 /* Release the mDNS mutex. */
4541 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4542 return(NX_MDNS_SUCCESS);
4543 }
4544 else
4545 {
4546 /* Release the mDNS mutex. */
4547 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4548 return(NX_MDNS_NO_MORE_ENTRIES);
4549 }
4550 }
4551
4552
4553 /**************************************************************************/
4554 /* */
4555 /* FUNCTION RELEASE */
4556 /* */
4557 /* _nxe_mdns_peer_cache_clear PORTABLE C */
4558 /* 6.1 */
4559 /* AUTHOR */
4560 /* */
4561 /* Yuxin Zhou, Microsoft Corporation */
4562 /* */
4563 /* DESCRIPTION */
4564 /* */
4565 /* This function checks for errors in the mDNS peer service cache */
4566 /* clear function call. */
4567 /* */
4568 /* INPUT */
4569 /* */
4570 /* mdns_ptr Pointer to mDNS instance */
4571 /* */
4572 /* OUTPUT */
4573 /* */
4574 /* status Completion status */
4575 /* */
4576 /* CALLS */
4577 /* */
4578 /* _nx_mdns_peer_cache_clear Actual peer cache clear */
4579 /* function */
4580 /* */
4581 /* CALLED BY */
4582 /* */
4583 /* Application Code */
4584 /* */
4585 /* RELEASE HISTORY */
4586 /* */
4587 /* DATE NAME DESCRIPTION */
4588 /* */
4589 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4590 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4591 /* resulting in version 6.1 */
4592 /* */
4593 /**************************************************************************/
_nxe_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4594 UINT _nxe_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4595 {
4596
4597 UINT status;
4598
4599
4600 /* Check for invalid input pointers. */
4601 if (!mdns_ptr)
4602 {
4603 return(NX_PTR_ERROR);
4604 }
4605
4606 /* Check for invalid server attributes. */
4607 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4608 {
4609 return(NX_MDNS_PARAM_ERROR);
4610 }
4611
4612 /* Call actual mDNS create service. */
4613 status = _nx_mdns_peer_cache_clear(mdns_ptr);
4614
4615 /* Return status. */
4616 return(status);
4617 }
4618
4619
4620 /**************************************************************************/
4621 /* */
4622 /* FUNCTION RELEASE */
4623 /* */
4624 /* _nx_mdns_peer_cache_clear PORTABLE C */
4625 /* 6.1 */
4626 /* AUTHOR */
4627 /* */
4628 /* Yuxin Zhou, Microsoft Corporation */
4629 /* */
4630 /* DESCRIPTION */
4631 /* */
4632 /* This function clears the mDNS peer service cache. */
4633 /* */
4634 /* INPUT */
4635 /* */
4636 /* mdns_ptr Pointer to mDNS instance */
4637 /* */
4638 /* OUTPUT */
4639 /* */
4640 /* status Completion status */
4641 /* */
4642 /* CALLS */
4643 /* */
4644 /* tx_mutex_get Get the mDNS mutex */
4645 /* tx_mutex_put Put the mDNS mutex */
4646 /* _nx_mdns_cache_initialize Initialize the cache */
4647 /* */
4648 /* CALLED BY */
4649 /* */
4650 /* Application Code */
4651 /* */
4652 /* RELEASE HISTORY */
4653 /* */
4654 /* DATE NAME DESCRIPTION */
4655 /* */
4656 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4657 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4658 /* resulting in version 6.1 */
4659 /* */
4660 /**************************************************************************/
_nx_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4661 UINT _nx_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4662 {
4663
4664 UINT status;
4665
4666
4667 /* Get the mDNS mutex. */
4668 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4669
4670 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);
4671
4672 /* Release the mDNS mutex. */
4673 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4674
4675 /* Return a error status. */
4676 return(status);
4677 }
4678
4679
4680 /**************************************************************************/
4681 /* */
4682 /* FUNCTION RELEASE */
4683 /* */
4684 /* _nxe_mdns_host_address_get PORTABLE C */
4685 /* 6.1 */
4686 /* AUTHOR */
4687 /* */
4688 /* Yuxin Zhou, Microsoft Corporation */
4689 /* */
4690 /* DESCRIPTION */
4691 /* */
4692 /* This function checks for errors in the mDNS host address get */
4693 /* function call. */
4694 /* */
4695 /* INPUT */
4696 /* */
4697 /* mdns_ptr Pointer to mDNS instance */
4698 /* name The name of the service */
4699 /* type The type of the service */
4700 /* subtype The subtype of the service */
4701 /* service Pointer to response service */
4702 /* timeout The timeour for service query */
4703 /* */
4704 /* OUTPUT */
4705 /* */
4706 /* status Completion status */
4707 /* */
4708 /* CALLS */
4709 /* */
4710 /* _nx_mdns_host_address_get Actual mDNS host address */
4711 /* get function */
4712 /* */
4713 /* CALLED BY */
4714 /* */
4715 /* Application Code */
4716 /* */
4717 /* RELEASE HISTORY */
4718 /* */
4719 /* DATE NAME DESCRIPTION */
4720 /* */
4721 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4722 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
4723 /* buffer length verification, */
4724 /* resulting in version 6.1 */
4725 /* */
4726 /**************************************************************************/
_nxe_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4727 UINT _nxe_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4728 {
4729
4730 UINT status;
4731
4732
4733 /* Check for invalid input pointers. */
4734 if ((!mdns_ptr) || (!host_name))
4735 {
4736 return(NX_PTR_ERROR);
4737 }
4738
4739 /* Check for mDNS started flag. */
4740 if (!mdns_ptr -> nx_mdns_started)
4741 {
4742 return(NX_MDNS_NOT_STARTED);
4743 }
4744
4745 /* Call actual mDNS create service. */
4746 status = _nx_mdns_host_address_get(mdns_ptr, host_name, ipv4_address, ipv6_address, timeout);
4747
4748 /* Return status. */
4749 return(status);
4750 }
4751
4752
4753 /**************************************************************************/
4754 /* */
4755 /* FUNCTION RELEASE */
4756 /* */
4757 /* _nx_mdns_host_address_get PORTABLE C */
4758 /* 6.1 */
4759 /* AUTHOR */
4760 /* */
4761 /* Yuxin Zhou, Microsoft Corporation */
4762 /* */
4763 /* DESCRIPTION */
4764 /* */
4765 /* This function adds the mDNS query record into peer buffer, */
4766 /* mDNS thread send the query message using one-shot type. */
4767 /* */
4768 /* INPUT */
4769 /* */
4770 /* mdns_ptr Pointer to mDNS instance */
4771 /* name The name of the service */
4772 /* type The type of the service */
4773 /* subtype The subtype of the service */
4774 /* service Pointer to response service */
4775 /* timeout The timeour for service query */
4776 /* */
4777 /* OUTPUT */
4778 /* */
4779 /* status Completion status */
4780 /* */
4781 /* CALLS */
4782 /* */
4783 /* tx_mutex_get Get the mDNS mutex */
4784 /* tx_mutex_put Put the mDNS mutex */
4785 /* tx_time_get Get the mDNS time */
4786 /* _nx_mdns_host_check Check the host info */
4787 /* _nx_mdns_answer_wait Wait the answer */
4788 /* _nx_mdns_cache_add_query Add the query into cache */
4789 /* _nx_mdns_cache_delete_query Delete the query from cache */
4790 /* */
4791 /* CALLED BY */
4792 /* */
4793 /* Application Code */
4794 /* */
4795 /* RELEASE HISTORY */
4796 /* */
4797 /* DATE NAME DESCRIPTION */
4798 /* */
4799 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4800 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4801 /* verified memcpy use cases, */
4802 /* resulting in version 6.1 */
4803 /* */
4804 /**************************************************************************/
_nx_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4805 UINT _nx_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4806 {
4807
4808 UINT status;
4809 ULONG start_time;
4810 ULONG current_time;
4811 ULONG elapsed_time;
4812 ULONG wait_time = timeout;
4813 NX_MDNS_RR *a_rr;
4814 NX_MDNS_RR *aaaa_rr;
4815 UCHAR host_name_query[NX_MDNS_NAME_MAX + 1];
4816 UINT i = 0;
4817 UCHAR domain_flag = NX_FALSE;
4818 UINT answer = NX_FALSE;
4819 UINT domain_name_length;
4820
4821
4822 /* Check string length. */
4823 if (_nx_utility_string_length_check((CHAR *)host_name, NX_NULL, NX_MDNS_HOST_NAME_MAX))
4824 {
4825 return(NX_MDNS_DATA_SIZE_ERROR);
4826 }
4827
4828 /* Get the mDNS mutex. */
4829 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
4830
4831 /* Clear the buffer. */
4832 memset(host_name_query, 0, NX_MDNS_NAME_MAX + 1);
4833
4834 /* Copy the host name into host name query buffer. */
4835 while(host_name[i] != NX_NULL)
4836 {
4837 host_name_query[i] = host_name[i];
4838 if (host_name[i] == '.')
4839 {
4840
4841 /* Update the flag. */
4842 domain_flag = NX_TRUE;
4843 }
4844 i++;
4845 }
4846
4847 /* Check if include the domain. */
4848 if (domain_flag == NX_FALSE)
4849 {
4850 host_name_query[i++] = '.';
4851
4852 /* Check string length. */
4853 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &domain_name_length, NX_MDNS_DOMAIN_NAME_MAX))
4854 {
4855
4856 /* Release the mDNS mutex. */
4857 tx_mutex_put(&(mdns_ptr->nx_mdns_mutex));
4858 return (NX_MDNS_DATA_SIZE_ERROR);
4859 }
4860
4861 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. */
4862 }
4863
4864 /* Initialize the value. */
4865 if (ipv4_address)
4866 *ipv4_address = NX_NULL;
4867 if (ipv6_address)
4868 memset(ipv6_address, 0, 16);
4869
4870 /* Start host address query on all enabled interfaces until get the answer or query timeout. */
4871 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
4872 {
4873
4874 /* Check if this interface is enabled. */
4875 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
4876 continue;
4877
4878 /* Get the query start time. */
4879 wait_time = timeout;
4880 start_time = tx_time_get();
4881
4882 /* Get the host IPv4 address. */
4883 if (ipv4_address)
4884 {
4885
4886 /* One shot query for host name. */
4887 status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_A, &a_rr, wait_time, i);
4888
4889 /* Check the status. */
4890 if (status == NX_MDNS_SUCCESS)
4891 {
4892
4893 /* Set the IPv4 address. */
4894 *ipv4_address = a_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
4895 answer = NX_TRUE;
4896 }
4897 }
4898
4899 /* Get the host IPv6 address. */
4900 if (ipv6_address)
4901 {
4902
4903 /* How much time has elapsed? */
4904 current_time = tx_time_get();
4905
4906 /* Has the time wrapped? */
4907 if (current_time >= start_time)
4908 {
4909 /* No, simply subtract to get the elapsed time. */
4910 elapsed_time = current_time - start_time;
4911 }
4912 else
4913 {
4914
4915 /* Yes it has. Time has rolled over the 32-bit boundary. */
4916 elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time;
4917 }
4918
4919 /* Update the timeout. */
4920 if (wait_time > elapsed_time)
4921 wait_time -= elapsed_time;
4922 else
4923 wait_time = 0;
4924
4925 /* Lookup the service. */
4926 status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_AAAA, &aaaa_rr, wait_time, i);
4927
4928 /* Check the status. */
4929 if (status == NX_MDNS_SUCCESS)
4930 {
4931
4932 /* Set the IPv6 address. */
4933 *ipv6_address = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[0];
4934 *(ipv6_address + 1) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[1];
4935 *(ipv6_address + 2) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[2];
4936 *(ipv6_address + 3) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[3];
4937 answer = NX_TRUE;
4938 }
4939 }
4940
4941 /* Check if get IPv4 address or IPv6 address. */
4942 if (answer == NX_TRUE)
4943 {
4944
4945 /* Release the mDNS mutex. */
4946 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4947 return (NX_MDNS_SUCCESS);
4948 }
4949 }
4950
4951 /* Release the mDNS mutex. */
4952 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4953 return (NX_MDNS_ERROR);
4954 }
4955 #endif /* NX_MDNS_DISABLE_CLIENT */
4956
4957
4958 #ifndef NX_MDNS_DISABLE_SERVER
4959 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
4960 /**************************************************************************/
4961 /* */
4962 /* FUNCTION RELEASE */
4963 /* */
4964 /* _nx_mdns_rr_a_aaaa_add PORTABLE C */
4965 /* 6.1 */
4966 /* AUTHOR */
4967 /* */
4968 /* Yuxin Zhou, Microsoft Corporation */
4969 /* */
4970 /* DESCRIPTION */
4971 /* */
4972 /* This function adds the mDNS A/AAAA resource record into local cache.*/
4973 /* */
4974 /* INPUT */
4975 /* */
4976 /* mdns_ptr Pointer to mDNS instance */
4977 /* set The resource record set */
4978 /* address The resource record address */
4979 /* insert_rr Pointer to insert resource */
4980 /* record */
4981 /* name Host name */
4982 /* ttl The resource record ttl */
4983 /* */
4984 /* OUTPUT */
4985 /* */
4986 /* status Completion status */
4987 /* */
4988 /* CALLS */
4989 /* */
4990 /* tx_mutex_get Get the mDNS mutex */
4991 /* tx_mutex_put Put the mDNS mutex */
4992 /* _nx_mdns_timer_set Set the mDNS timer */
4993 /* _nx_mdns_cache_add_string Add the string into cache */
4994 /* _nx_mdns_cache_delete_string Delete the string from cache */
4995 /* _nx_mdns_cache_add_resource_record Add the resource record */
4996 /* into cache */
4997 /* */
4998 /* CALLED BY */
4999 /* */
5000 /* _nx_mdns_host_name_register Register the host name */
5001 /* */
5002 /* RELEASE HISTORY */
5003 /* */
5004 /* DATE NAME DESCRIPTION */
5005 /* */
5006 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5007 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5008 /* resulting in version 6.1 */
5009 /* */
5010 /**************************************************************************/
_nx_mdns_rr_a_aaaa_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG * address,UINT addr_length,UCHAR type,UINT interface_index)5011 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index)
5012 {
5013 UINT status;
5014 NX_MDNS_RR *insert_rr;
5015 USHORT rr_type;
5016 NX_MDNS_RR temp_resource_record;
5017
5018
5019 /* Set the resource record type. */
5020 if(addr_length == 4)
5021 rr_type = NX_MDNS_RR_TYPE_A;
5022 else
5023 rr_type = NX_MDNS_RR_TYPE_AAAA;
5024
5025 /* Set the resource record parameters. */
5026 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);
5027
5028 /* Check for error. */
5029 if (status)
5030 {
5031 return(status);
5032 }
5033
5034 /* Add the parameters. */
5035 if(rr_type == NX_MDNS_RR_TYPE_A)
5036 {
5037 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = *address;
5038 }
5039 else
5040 {
5041 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = *address;
5042 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = *(address +1);
5043 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = *(address + 2);
5044 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = *(address + 3);
5045 }
5046
5047 /* Add the resource record. */
5048 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5049
5050 /* Check for error. */
5051 if (status)
5052 {
5053
5054 /* Delete the name strings. */
5055 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5056 return(status);
5057 }
5058
5059 /* Set the mDNS timer. */
5060 _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
5061
5062 /* Return a successful status. */
5063 return(NX_SUCCESS);
5064 }
5065 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
5066
5067
5068 /**************************************************************************/
5069 /* */
5070 /* FUNCTION RELEASE */
5071 /* */
5072 /* _nx_mdns_rr_ptr_add PORTABLE C */
5073 /* 6.1 */
5074 /* AUTHOR */
5075 /* */
5076 /* Yuxin Zhou, Microsoft Corporation */
5077 /* */
5078 /* DESCRIPTION */
5079 /* */
5080 /* This function adds the mDNS PTR resource record into local buffer. */
5081 /* */
5082 /* INPUT */
5083 /* */
5084 /* mdns_ptr Pointer to mDNS instance */
5085 /* name The resource record name */
5086 /* ttl The resource record ttl */
5087 /* set The resource record set */
5088 /* ptr_name The domain name */
5089 /* insert_rr Pointer to insert resource */
5090 /* record */
5091 /* */
5092 /* OUTPUT */
5093 /* */
5094 /* status Completion status */
5095 /* */
5096 /* CALLS */
5097 /* */
5098 /* tx_mutex_get Get the mDNS mutex */
5099 /* tx_mutex_put Put the mDNS mutex */
5100 /* _nx_mdns_timer_set Set the mDNS timer */
5101 /* _nx_mdns_cache_add_string Add the string into cache */
5102 /* _nx_mdns_cache_delete_string Delete the string from cache */
5103 /* _nx_mdns_cache_add_resource_record Add the resource record */
5104 /* into cache */
5105 /* */
5106 /* CALLED BY */
5107 /* */
5108 /* Application Code */
5109 /* */
5110 /* RELEASE HISTORY */
5111 /* */
5112 /* DATE NAME DESCRIPTION */
5113 /* */
5114 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5115 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5116 /* resulting in version 6.1 */
5117 /* */
5118 /**************************************************************************/
_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 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)
5120 {
5121
5122 UINT status;
5123 NX_MDNS_RR *ptr_rr;
5124 NX_MDNS_RR temp_resource_record;
5125 UINT ptr_name_length;
5126
5127
5128 if (_nx_utility_string_length_check((CHAR *)ptr_name, &ptr_name_length, NX_MDNS_NAME_MAX))
5129 {
5130 return (NX_MDNS_DATA_SIZE_ERROR);
5131 }
5132
5133 /* Get the mDNS mutex. */
5134 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5135
5136 /* Set the resource record parameters. Rdata length: PTR name, string should include the first'.' and last '\0'. */
5137 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);
5138
5139 /* Check for error. */
5140 if (status)
5141 {
5142
5143 /* Release the mDNS mutex. */
5144 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5145
5146 return(status);
5147 }
5148
5149 /* Add the ptr name. */
5150 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, ptr_name, ptr_name_length,
5151 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name),
5152 NX_FALSE, NX_TRUE);
5153
5154 /* Check for error. */
5155 if (status)
5156 {
5157
5158 /* Delete the strings. */
5159 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5160
5161 /* Release the mDNS mutex. */
5162 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5163
5164 return(status);
5165 }
5166
5167 /* Add the resource record. */
5168 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &ptr_rr, NX_NULL);
5169
5170 /* Check for error. */
5171 if (status)
5172 {
5173
5174 /* Delete the same strings. */
5175 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5176
5177 /* Delete the same strings. */
5178 _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);
5179
5180 /* Release the mDNS mutex. */
5181 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5182
5183 return(status);
5184 }
5185
5186 /* Set the mDNS timer. */
5187 _nx_mdns_timer_set(mdns_ptr, ptr_rr, ptr_rr -> nx_mdns_rr_timer_count);
5188
5189 if (insert_rr)
5190 *insert_rr = ptr_rr;
5191
5192 /* Release the mDNS mutex. */
5193 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5194
5195 /* Return a successful status. */
5196 return(NX_SUCCESS);
5197 }
5198
5199
5200 /**************************************************************************/
5201 /* */
5202 /* FUNCTION RELEASE */
5203 /* */
5204 /* _nx_mdns_rr_srv_add PORTABLE C */
5205 /* 6.1 */
5206 /* AUTHOR */
5207 /* */
5208 /* Yuxin Zhou, Microsoft Corporation */
5209 /* */
5210 /* DESCRIPTION */
5211 /* */
5212 /* This function adds the mDNS SRV resource record into local buffer. */
5213 /* */
5214 /* INPUT */
5215 /* */
5216 /* mdns_ptr Pointer to mDNS instance */
5217 /* name Service nstance name */
5218 /* ttl The ttl of the service */
5219 /* set The resource record set */
5220 /* priority The priority of target host */
5221 /* weights Service weight */
5222 /* port The port on this target host */
5223 /* target The target host */
5224 /* insert_rr Pointer to insert record */
5225 /* */
5226 /* OUTPUT */
5227 /* */
5228 /* status Completion status */
5229 /* */
5230 /* CALLS */
5231 /* */
5232 /* tx_mutex_get Get the mDNS mutex */
5233 /* tx_mutex_put Put the mDNS mutex */
5234 /* _nx_mdns_timer_set Set the mDNS timer */
5235 /* _nx_mdns_cache_add_string Add the string into cache */
5236 /* _nx_mdns_cache_delete_string Delete the string from cache */
5237 /* _nx_mdns_cache_add_resource_record Add the resource record */
5238 /* into cache */
5239 /* */
5240 /* CALLED BY */
5241 /* */
5242 /* Application Code */
5243 /* */
5244 /* RELEASE HISTORY */
5245 /* */
5246 /* DATE NAME DESCRIPTION */
5247 /* */
5248 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5249 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5250 /* resulting in version 6.1 */
5251 /* */
5252 /**************************************************************************/
_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)5253 static UINT _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority,
5254 USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index)
5255 {
5256
5257 UINT status;
5258 NX_MDNS_RR *srv_rr;
5259 NX_MDNS_RR temp_resource_record;
5260 UINT target_length;
5261
5262 if (_nx_utility_string_length_check((CHAR *)target, &target_length, NX_MDNS_NAME_MAX))
5263 {
5264 return (NX_MDNS_DATA_SIZE_ERROR);
5265 }
5266
5267 /* Get the mDNS mutex. */
5268 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5269
5270 /* Set the resource record parameters. Rdata length: PRIORITY, WEIGHTS, PORT, TARGET, name string should include the first'.' and last '\0'. */
5271 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);
5272
5273 /* Check for error. */
5274 if (status)
5275 {
5276 /* Release the mDNS mutex. */
5277 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5278
5279 return(status);
5280 }
5281
5282 /* Add the name. */
5283 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, target, target_length,
5284 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
5285 NX_FALSE, NX_TRUE);
5286
5287 /* Check for error. */
5288 if (status)
5289 {
5290
5291 /* Delete the same strings. */
5292 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5293
5294 /* Release the mDNS mutex. */
5295 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5296
5297 return(status);
5298 }
5299
5300 /* Set the SRV parameters. */
5301 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = priority;
5302 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = weights;
5303 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = port;
5304
5305 /* Add the resource record. */
5306 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &srv_rr, NX_NULL);
5307
5308 /* Check for error. */
5309 if (status)
5310 {
5311 /* Delete the same strings. */
5312 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5313
5314 /* Delete the same strings. */
5315 _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);
5316
5317 /* Release the mDNS mutex. */
5318 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5319
5320 return(status);
5321 }
5322
5323 /* Set the mDNS timer. */
5324 _nx_mdns_timer_set(mdns_ptr, srv_rr, srv_rr -> nx_mdns_rr_timer_count);
5325
5326 if (insert_rr)
5327 *insert_rr = srv_rr;
5328
5329 /* Release the mDNS mutex. */
5330 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5331
5332 /* Return a successful status. */
5333 return(NX_SUCCESS);
5334 }
5335
5336
5337 /**************************************************************************/
5338 /* */
5339 /* FUNCTION RELEASE */
5340 /* */
5341 /* _nx_mdns_rr_txt_add PORTABLE C */
5342 /* 6.1 */
5343 /* AUTHOR */
5344 /* */
5345 /* Yuxin Zhou, Microsoft Corporation */
5346 /* */
5347 /* DESCRIPTION */
5348 /* */
5349 /* This function adds the mDNS TXT resource record into local buffer. */
5350 /* the TXT records are formatted in a "key=value" notation with ";" */
5351 /* acting as separator when more then one key is available. */
5352 /* */
5353 /* INPUT */
5354 /* */
5355 /* mdns_ptr Pointer to mDNS instance */
5356 /* name The resource record name */
5357 /* ttl The resource record ttl */
5358 /* set The resource record set */
5359 /* txt The txt string */
5360 /* insert_rr Pointer to insert record */
5361 /* */
5362 /* OUTPUT */
5363 /* */
5364 /* status Completion status */
5365 /* */
5366 /* CALLS */
5367 /* */
5368 /* tx_mutex_get Get the mDNS mutex */
5369 /* tx_mutex_put Put the mDNS mutex */
5370 /* _nx_mdns_timer_set Set the mDNS timer */
5371 /* _nx_mdns_cache_add_string Add the string into cache */
5372 /* _nx_mdns_cache_delete_string Delete the string from cache */
5373 /* _nx_mdns_cache_add_resource_record Add the resource record */
5374 /* into the cache */
5375 /* */
5376 /* CALLED BY */
5377 /* */
5378 /* Application Code */
5379 /* */
5380 /* RELEASE HISTORY */
5381 /* */
5382 /* DATE NAME DESCRIPTION */
5383 /* */
5384 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5385 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5386 /* resulting in version 6.1 */
5387 /* */
5388 /**************************************************************************/
_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 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)
5390 {
5391
5392 UINT status;
5393 NX_MDNS_RR *txt_rr;
5394 NX_MDNS_RR temp_resource_record;
5395 UINT txt_length;
5396
5397
5398 /* Get the mDNS mutex. */
5399 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5400
5401 /* Set the resource record parameters. */
5402 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);
5403
5404 /* Check for error. */
5405 if (status)
5406 {
5407 /* Release the mDNS mutex. */
5408 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5409
5410 return(status);
5411 }
5412
5413 if (txt)
5414 {
5415
5416 /* Check string length. */
5417 if (_nx_utility_string_length_check((CHAR *)txt, &txt_length, NX_MDNS_NAME_MAX))
5418 {
5419
5420 /* Release the mDNS mutex. */
5421 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5422 return (NX_MDNS_DATA_SIZE_ERROR);
5423 }
5424
5425 /* Calculate the text string.inlcude the one byte label. */
5426 temp_resource_record.nx_mdns_rr_rdata_length = (USHORT)(txt_length + 1);
5427
5428 /* Add the name. */
5429 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, txt, txt_length,
5430 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data),
5431 NX_FALSE, NX_TRUE);
5432
5433 /* Check for error. */
5434 if (status)
5435 {
5436
5437 /* Delete the same strings. */
5438 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5439
5440 /* Release the mDNS mutex. */
5441 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5442
5443 return(status);
5444 }
5445 }
5446 else
5447 {
5448 temp_resource_record.nx_mdns_rr_rdata_length = 1;
5449 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = NX_NULL;
5450 }
5451
5452 /* Add the resource record. */
5453 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &txt_rr, NX_NULL);
5454
5455 /* Check for error. */
5456 if (status)
5457 {
5458
5459 /* Delete the same strings. */
5460 _nx_mdns_cache_delete_string(mdns_ptr,NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5461
5462 if (txt)
5463 {
5464
5465 /* Delete the same strings. */
5466 _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);
5467 }
5468
5469 /* Release the mDNS mutex. */
5470 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5471
5472 return(status);
5473 }
5474
5475 /* Set the mDNS timer. */
5476 _nx_mdns_timer_set(mdns_ptr, txt_rr, txt_rr -> nx_mdns_rr_timer_count);
5477
5478 if (insert_rr)
5479 *insert_rr = txt_rr;
5480
5481 /* Release the mDNS mutex. */
5482 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5483
5484 /* Return a successful status. */
5485 return(NX_SUCCESS);
5486 }
5487
5488
5489 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
5490 /**************************************************************************/
5491 /* */
5492 /* FUNCTION RELEASE */
5493 /* */
5494 /* _nx_mdns_rr_nsec_add PORTABLE C */
5495 /* 6.1 */
5496 /* AUTHOR */
5497 /* */
5498 /* Yuxin Zhou, Microsoft Corporation */
5499 /* */
5500 /* DESCRIPTION */
5501 /* */
5502 /* This function adds the mDNS A resource record into local cache. */
5503 /* */
5504 /* INPUT */
5505 /* */
5506 /* mdns_ptr Pointer to mDNS instance */
5507 /* name The resource record name */
5508 /* add_a Flag for adding A record */
5509 /* add_aaaa Flag for adding AAAA record */
5510 /* type Type for host or service */
5511 /* */
5512 /* OUTPUT */
5513 /* */
5514 /* status Completion status */
5515 /* */
5516 /* CALLS */
5517 /* */
5518 /* tx_mutex_get Get the mDNS mutex */
5519 /* tx_mutex_put Put the mDNS mutex */
5520 /* _nx_mdns_timer_set Set the mDNS timer */
5521 /* _nx_mdns_cache_add_string Add the string into cache */
5522 /* _nx_mdns_cache_delete_string Delete the string from cache */
5523 /* _nx_mdns_cache_add_resource_record Add the resource record */
5524 /* into cache */
5525 /* */
5526 /* CALLED BY */
5527 /* */
5528 /* _nx_mdns_host_name_register Register the host name */
5529 /* */
5530 /* RELEASE HISTORY */
5531 /* */
5532 /* DATE NAME DESCRIPTION */
5533 /* */
5534 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5535 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5536 /* resulting in version 6.1 */
5537 /* */
5538 /**************************************************************************/
_nx_mdns_rr_nsec_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR add_a,UCHAR add_aaaa,UCHAR type,UINT interface_index)5539 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index)
5540 {
5541 UINT status;
5542 NX_MDNS_RR *insert_rr;
5543 UCHAR bitmap_length = 0;
5544 ULONG rdata_length = 0;
5545 NX_MDNS_RR temp_resource_record;
5546 UINT name_length;
5547
5548
5549 /* Check string length. */
5550 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5551 {
5552 return (NX_MDNS_DATA_SIZE_ERROR);
5553 }
5554
5555 /* Add the next domain name, include the first'.' and last '\0'. */
5556 rdata_length = name_length + 2;
5557
5558 /* Add the window block and bitmap length. */
5559 rdata_length += 2;
5560
5561 /* Add the NSEC with A/AAAA Bitmap. */
5562 if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5563 {
5564 /* Set the Bitmaps length. */
5565 if (add_aaaa == NX_TRUE)
5566 bitmap_length = 4;
5567 else
5568 bitmap_length = 1;
5569 }
5570 else
5571 {
5572
5573 /* Add the NSEC with SRV/TXT Bitmap. */
5574 bitmap_length = 5;
5575 }
5576
5577 /* Add the Bitmaps. */
5578 rdata_length += bitmap_length;
5579
5580 /* Set the resource record parameters. */
5581 status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_NSEC, NX_MDNS_RR_TTL_HOST, rdata_length,
5582 NX_MDNS_RR_SET_UNIQUE, NX_FALSE, NX_TRUE, &temp_resource_record, interface_index);
5583
5584 /* Check for error. */
5585 if (status)
5586 {
5587 return(status);
5588 }
5589
5590 /* Add the next domain name. */
5591 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5592 (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain),
5593 NX_FALSE, NX_TRUE);
5594
5595 /* Check for error. */
5596 if (status)
5597 {
5598 /* Delete the same strings. */
5599 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5600
5601 return(status);
5602 }
5603
5604 /* Set the window block and bitmap length. */
5605 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block = 0;
5606 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length = bitmap_length;
5607
5608 /* Add the Bitmap for host. */
5609 if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5610 {
5611
5612 /* Encode the Bitmap. */
5613 if ((add_a == NX_TRUE) && (add_aaaa == NX_TRUE))
5614 {
5615
5616 /* Add the A Bitmap. */
5617 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5618
5619 /* Add the AAAA Bitmap. */
5620 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5621 }
5622 else if ((add_a == NX_TRUE))
5623 {
5624
5625 /* Add the A Bit map. */
5626 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5627 }
5628 else
5629 {
5630
5631 /* Add the AAAA Bitmap. */
5632 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5633 }
5634 }
5635 else
5636 {
5637 /* Add the TXT Bitmap for service. */
5638 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[2] = 128;
5639
5640 /* Add the SRV Bitmap for service. */
5641 temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[4] = 64;
5642
5643 }
5644
5645 /* Add the resource record. */
5646 status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5647
5648 /* Check for error. */
5649 if (status)
5650 {
5651 /* Delete the same strings. */
5652 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5653
5654 /* Delete the same strings. */
5655 _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);
5656
5657 return(status);
5658 }
5659
5660 /* Return a successful status. */
5661 return(NX_SUCCESS);
5662 }
5663 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
5664
5665
5666 /**************************************************************************/
5667 /* */
5668 /* FUNCTION RELEASE */
5669 /* */
5670 /* _nx_mdns_rr_parameter_set PORTABLE C */
5671 /* 6.1.11 */
5672 /* AUTHOR */
5673 /* */
5674 /* Yuxin Zhou, Microsoft Corporation */
5675 /* */
5676 /* DESCRIPTION */
5677 /* */
5678 /* This function sets the parameters of resource record. */
5679 /* */
5680 /* INPUT */
5681 /* */
5682 /* mdns_ptr Pointer to mDNS instance */
5683 /* name The resource record name */
5684 /* type The resource record type */
5685 /* ttl The resource record ttl */
5686 /* rdata_lenth The resource record length */
5687 /* set The resource record set */
5688 /* is_register Register flag */
5689 /* is_valid Valid flag */
5690 /* rr_record Pointer to resource record */
5691 /* */
5692 /* OUTPUT */
5693 /* */
5694 /* status Completion status */
5695 /* */
5696 /* CALLS */
5697 /* */
5698 /* None */
5699 /* */
5700 /* CALLED BY */
5701 /* */
5702 /* Application Code */
5703 /* */
5704 /* RELEASE HISTORY */
5705 /* */
5706 /* DATE NAME DESCRIPTION */
5707 /* */
5708 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5709 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5710 /* resulting in version 6.1 */
5711 /* 04-25-2022 Yuxin Zhou Modified comment(s), */
5712 /* fixed the issue of timer, */
5713 /* resulting in version 6.1.11 */
5714 /* */
5715 /**************************************************************************/
_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)5716 static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length,
5717 UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index)
5718 {
5719
5720 UINT status;
5721 UINT name_length;
5722
5723
5724 /* Check string length. */
5725 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5726 {
5727 return (NX_MDNS_DATA_SIZE_ERROR);
5728 }
5729
5730 /* Initialize the struct. */
5731 memset(rr_record, 0, sizeof(NX_MDNS_RR));
5732
5733 /* Add the name. */
5734 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5735 (VOID **)(&rr_record -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
5736
5737 /* Check for error. */
5738 if (status)
5739 return(status);
5740
5741 /* Set the parameters. */
5742 rr_record -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
5743 rr_record -> nx_mdns_rr_type = type;
5744 rr_record -> nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
5745 rr_record -> nx_mdns_rr_ttl = ttl;
5746 rr_record -> nx_mdns_rr_rdata_length = (USHORT)rdata_length;
5747
5748 /* Set the resource record as uniqure. */
5749 if (set == NX_MDNS_RR_SET_UNIQUE)
5750 rr_record -> nx_mdns_rr_word = (rr_record -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_UNIQUE);
5751
5752 /* Check for mDNS started flag. */
5753 if (mdns_ptr -> nx_mdns_started)
5754 {
5755
5756 /* Check the valid flag for PTR resource record. */
5757 if (is_valid == NX_TRUE)
5758 {
5759 /* Set the resource record state. */
5760 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
5761 }
5762 else
5763 {
5764
5765 /* 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). */
5766 if ((set == NX_MDNS_RR_SET_UNIQUE) && (is_register == NX_TRUE))
5767 {
5768
5769 /* Set the resource record status. */
5770 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
5771 rr_record -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
5772 rr_record -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
5773 }
5774 else
5775 {
5776
5777 /* Set the resource record state. */
5778 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
5779 rr_record -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
5780 rr_record -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
5781
5782 /* Check the announcing max time. */
5783 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
5784 rr_record -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
5785 else
5786 rr_record -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
5787
5788 /* Set the retransmit count. */
5789 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
5790 rr_record -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
5791 else
5792 rr_record -> nx_mdns_rr_retransmit_count = 1;
5793 }
5794 }
5795 }
5796 else
5797 {
5798
5799 /* Set the resource record status. */
5800 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
5801 }
5802
5803 return(NX_MDNS_SUCCESS);
5804 }
5805 #endif /* NX_MDNS_DISABLE_SERVER */
5806
5807
5808 /**************************************************************************/
5809 /* */
5810 /* FUNCTION RELEASE */
5811 /* */
5812 /* _nx_mdns_rr_delete PORTABLE C */
5813 /* 6.1 */
5814 /* AUTHOR */
5815 /* */
5816 /* Yuxin Zhou, Microsoft Corporation */
5817 /* */
5818 /* DESCRIPTION */
5819 /* */
5820 /* This function deletes the mDNS resource record from the */
5821 /* local bufferor remote buffer according to the resource record set. */
5822 /* */
5823 /* INPUT */
5824 /* */
5825 /* mdns_ptr Pointer to mDNS instance */
5826 /* record_rr The resource record */
5827 /* */
5828 /* OUTPUT */
5829 /* */
5830 /* status Completion status */
5831 /* */
5832 /* CALLS */
5833 /* */
5834 /* tx_mutex_get Get the mDNS mutex */
5835 /* tx_mutex_put Put the mDNS mutex */
5836 /* _nx_mdns_timer_set Set the mDNS timer */
5837 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
5838 /* from cache */
5839 /* */
5840 /* CALLED BY */
5841 /* */
5842 /* Application Code */
5843 /* */
5844 /* RELEASE HISTORY */
5845 /* */
5846 /* DATE NAME DESCRIPTION */
5847 /* */
5848 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5849 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5850 /* resulting in version 6.1 */
5851 /* */
5852 /**************************************************************************/
_nx_mdns_rr_delete(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)5853 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
5854 {
5855
5856 UINT status = NX_MDNS_SUCCESS;
5857
5858 #ifndef NX_MDNS_DISABLE_CLIENT
5859 ULONG *head;
5860 NX_MDNS_RR *p;
5861 #endif /* NX_MDNS_DISABLE_CLIENT */
5862
5863 /* Get the mDNS mutex. */
5864 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5865
5866
5867 /* Check for mDNS started flag. */
5868 if (mdns_ptr -> nx_mdns_started)
5869 {
5870
5871 /* Check the RR owner. */
5872 if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5873 {
5874
5875 #ifndef NX_MDNS_DISABLE_SERVER
5876 if ((record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
5877 (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
5878 {
5879
5880 /* Set the state to send Goodbye packet. */
5881 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
5882
5883 /* Set the retransmit count. */
5884 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
5885
5886 /* Set the timer count. */
5887 record_rr -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
5888
5889 /* Set the delete flag. */
5890 record_rr -> nx_mdns_rr_word = (record_rr -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
5891
5892 /* Set the mDNS timer. */
5893 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
5894 }
5895 else
5896 {
5897
5898 /* Delete the resource records. */
5899 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5900 }
5901
5902 #endif /* NX_MDNS_DISABLE_SERVER */
5903 }
5904 else
5905 {
5906
5907 #ifndef NX_MDNS_DISABLE_CLIENT
5908 if (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
5909 {
5910
5911 /* Set the pointer. */
5912 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
5913
5914 if(head)
5915 {
5916 head = (ULONG*)(*head);
5917
5918 /* Check the remote resource record, stop the updating resource record. */
5919 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
5920 {
5921
5922 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
5923 continue;
5924
5925 if (p == record_rr)
5926 continue;
5927
5928 if ((p -> nx_mdns_rr_name == record_rr -> nx_mdns_rr_name) &&
5929 (p -> nx_mdns_rr_type == record_rr -> nx_mdns_rr_type) &&
5930 (p -> nx_mdns_rr_class == record_rr -> nx_mdns_rr_class))
5931 {
5932
5933 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)
5934 {
5935
5936 /* Clear the Updating flag. */
5937 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_UPDATING));
5938 }
5939
5940 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
5941 {
5942 if (p -> nx_mdns_rr_retransmit_count)
5943 {
5944
5945 /* mDNS querier need not update the RR, The original updating ttl is at 80%, 85%, 90%, 95%. Update the timer.*/
5946 /* timer_count: P, timer_count: C, rr_ttl: T.
5947 P = P + C * T * 5%. */
5948 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);
5949
5950 /* Clear the retransmit count. */
5951 p -> nx_mdns_rr_retransmit_count = 0;
5952
5953 /* Set the mDNS timer. */
5954 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
5955 }
5956 }
5957 }
5958 }
5959 }
5960 }
5961
5962 /* Delete the resource record. */
5963 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5964
5965 #endif /* NX_MDNS_DISABLE_CLIENT */
5966 }
5967 }
5968 else
5969 {
5970 /* Check the RR owner. */
5971 if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5972 {
5973
5974 #ifndef NX_MDNS_DISABLE_SERVER
5975 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5976 #endif /* NX_MDNS_DISABLE_SERVER */
5977 }
5978 else
5979 {
5980
5981 #ifndef NX_MDNS_DISABLE_CLIENT
5982 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5983 #endif /* NX_MDNS_DISABLE_CLIENT */
5984 }
5985 }
5986
5987 /* Release the mDNS mutex. */
5988 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5989
5990 /* Return status. */
5991 return (status);
5992 }
5993
5994
5995 #ifndef NX_MDNS_DISABLE_SERVER
5996 /**************************************************************************/
5997 /* */
5998 /* FUNCTION RELEASE */
5999 /* */
6000 /* _nx_mdns_local_cache_clear PORTABLE C */
6001 /* 6.1 */
6002 /* AUTHOR */
6003 /* */
6004 /* Yuxin Zhou, Microsoft Corporation */
6005 /* */
6006 /* DESCRIPTION */
6007 /* */
6008 /* This function deletes the mDNS instance. */
6009 /* */
6010 /* INPUT */
6011 /* */
6012 /* mdns_ptr Pointer to mDNS instance */
6013 /* */
6014 /* OUTPUT */
6015 /* */
6016 /* status Completion status */
6017 /* */
6018 /* CALLS */
6019 /* */
6020 /* _nx_mdns_local_cache_clear Actual local cache clear */
6021 /* function */
6022 /* */
6023 /* CALLED BY */
6024 /* */
6025 /* Application Code */
6026 /* */
6027 /* RELEASE HISTORY */
6028 /* */
6029 /* DATE NAME DESCRIPTION */
6030 /* */
6031 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6032 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6033 /* resulting in version 6.1 */
6034 /* */
6035 /**************************************************************************/
_nxe_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6036 UINT _nxe_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6037 {
6038
6039 UINT status;
6040
6041
6042 /* Check for invalid input pointers. */
6043 if (!mdns_ptr)
6044 {
6045 return(NX_PTR_ERROR);
6046 }
6047
6048 /* Check for invalid server attributes. */
6049 if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
6050 {
6051 return(NX_MDNS_PARAM_ERROR);
6052 }
6053
6054 /* Call actual mDNS local cache clear service. */
6055 status = _nx_mdns_local_cache_clear(mdns_ptr);
6056
6057 /* Return status. */
6058 return(status);
6059 }
6060
6061
6062 /**************************************************************************/
6063 /* */
6064 /* FUNCTION RELEASE */
6065 /* */
6066 /* _nx_mdns_local_cache_clear PORTABLE C */
6067 /* 6.1 */
6068 /* AUTHOR */
6069 /* */
6070 /* Yuxin Zhou, Microsoft Corporation */
6071 /* */
6072 /* DESCRIPTION */
6073 /* */
6074 /* This function clears the mDNS local cache. */
6075 /* */
6076 /* INPUT */
6077 /* */
6078 /* mdns_ptr Pointer to mDNS instance */
6079 /* */
6080 /* OUTPUT */
6081 /* */
6082 /* status Completion status */
6083 /* */
6084 /* CALLS */
6085 /* */
6086 /* _nx_mdns_timer_set Set the mDNS timer */
6087 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
6088 /* from cache */
6089 /* */
6090 /* CALLED BY */
6091 /* */
6092 /* Application Code */
6093 /* */
6094 /* RELEASE HISTORY */
6095 /* */
6096 /* DATE NAME DESCRIPTION */
6097 /* */
6098 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6099 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6100 /* resulting in version 6.1 */
6101 /* */
6102 /**************************************************************************/
_nx_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6103 UINT _nx_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6104 {
6105
6106 UINT status = NX_MDNS_SUCCESS;
6107 ULONG *head;
6108 NX_MDNS_RR *p;
6109
6110
6111 /* Get the mDNS mutex. */
6112 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
6113
6114 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6115 head = (ULONG*)(*head);
6116
6117 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
6118 {
6119
6120 /* Delete the resource records. */
6121 status = _nx_mdns_rr_delete(mdns_ptr, p);
6122
6123 /* Check the status. */
6124 if (status)
6125 break;
6126 }
6127
6128 /* Release the mDNS mutex. */
6129 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
6130
6131 /* Return a successful status. */
6132 return(status);
6133 }
6134 #endif /* NX_MDNS_DISABLE_SERVER */
6135
6136
6137 /**************************************************************************/
6138 /* */
6139 /* FUNCTION RELEASE */
6140 /* */
6141 /* _nx_mdns_service_name_resolve PORTABLE C */
6142 /* 6.1 */
6143 /* AUTHOR */
6144 /* */
6145 /* Yuxin Zhou, Microsoft Corporation */
6146 /* */
6147 /* DESCRIPTION */
6148 /* */
6149 /* This function resloves the service name, type, domain. */
6150 /* */
6151 /* INPUT */
6152 /* */
6153 /* srv_name Pointer to SRV name */
6154 /* name The name of the service */
6155 /* type The type of to the service */
6156 /* domain The domain */
6157 /* */
6158 /* OUTPUT */
6159 /* */
6160 /* status Completion status */
6161 /* */
6162 /* CALLS */
6163 /* */
6164 /* tx_mutex_get Get the mDNS mutex */
6165 /* tx_mutex_put Put the mDNS mutex */
6166 /* */
6167 /* CALLED BY */
6168 /* */
6169 /* mDNS component */
6170 /* */
6171 /* RELEASE HISTORY */
6172 /* */
6173 /* DATE NAME DESCRIPTION */
6174 /* */
6175 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6176 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6177 /* resulting in version 6.1 */
6178 /* */
6179 /**************************************************************************/
_nx_mdns_service_name_resolve(UCHAR * srv_name,UCHAR ** name,UCHAR ** type,UCHAR ** domain)6180 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain)
6181 {
6182
6183 UINT i;
6184 UINT count;
6185 UINT prepend_index;
6186 UINT append_index;
6187 UINT type_index;
6188 UINT domain_index;
6189 UCHAR *pointer;
6190 UINT protocol_length;
6191
6192
6193 /* Initialize the parameters. */
6194 count = 0;
6195 prepend_index = 0;
6196 append_index = 0;
6197 type_index = 0;
6198 domain_index = 0;
6199
6200 /* Set the service name pointer. */
6201 pointer = srv_name;
6202
6203 /* Service Instance name, */
6204 /* <Instance>.<sn>._tcp.<domain> :
6205 name: <Instance>
6206 type: <sn>._tcp
6207 domain: <domain>. */
6208 while (*srv_name != '\0')
6209 {
6210
6211 /* Update the index. */
6212 append_index ++;
6213
6214 if (*srv_name == '.')
6215 {
6216
6217 /* Set the value. */
6218 i = 0;
6219
6220 while (nx_mdns_app_protocol[i])
6221 {
6222
6223 /* Check string length. */
6224 if (_nx_utility_string_length_check(nx_mdns_app_protocol[i], &protocol_length, NX_MDNS_TYPE_MAX))
6225 {
6226 continue;
6227 }
6228
6229 /* Find the key string. "_tcp" , "_udp" etc. */
6230 if (!_nx_mdns_name_match(pointer + prepend_index, (UCHAR *)(nx_mdns_app_protocol[i]), protocol_length))
6231 {
6232
6233 /* Get the <domain> pointer. */
6234 /* EL-PC.Test._http._tcp.local
6235 type index pointer to the _http._tcp,
6236 domain_index pointer to the local. */
6237 domain_index = append_index;
6238
6239 /* Set the name pointer. */
6240 if (type_index)
6241 {
6242 *name = pointer;
6243
6244 /* Set the trailing null of name. */
6245 *(pointer + type_index -1) = '\0';
6246 }
6247 else
6248 {
6249 *name = NX_NULL;
6250 }
6251
6252 /* Set the type pointer. */
6253 *type = pointer + type_index;
6254
6255 /* Set the trailing null of type. */
6256 *(pointer + domain_index -1) = '\0';
6257
6258 /* Set the type pointer. */
6259 *domain = pointer + domain_index;
6260
6261 return(NX_MDNS_SUCCESS);
6262 }
6263 i ++;
6264 }
6265
6266 /* Update the '.' count. */
6267 count ++;
6268
6269 /* The type index is pointer to the <sn>. */
6270 if (count != 1)
6271 {
6272
6273 /* Update the type index. */
6274 type_index = prepend_index;
6275 }
6276
6277 prepend_index = append_index;
6278 }
6279
6280 srv_name ++;
6281 }
6282
6283 return(NX_MDNS_ERROR);
6284 }
6285
6286
6287 /**************************************************************************/
6288 /* */
6289 /* FUNCTION RELEASE */
6290 /* */
6291 /* _nx_mdns_service_name_assemble PORTABLE C */
6292 /* 6.1 */
6293 /* AUTHOR */
6294 /* */
6295 /* Yuxin Zhou, Microsoft Corporation */
6296 /* */
6297 /* DESCRIPTION */
6298 /* */
6299 /* This function resloves the service name, type, domain. */
6300 /* */
6301 /* INPUT */
6302 /* */
6303 /* srv_name Pointer to SRV name */
6304 /* name The name of the service */
6305 /* type The type of to the service */
6306 /* domain The domain */
6307 /* */
6308 /* OUTPUT */
6309 /* */
6310 /* status Completion status */
6311 /* */
6312 /* CALLS */
6313 /* */
6314 /* tx_mutex_get Get the mDNS mutex */
6315 /* tx_mutex_put Put the mDNS mutex */
6316 /* */
6317 /* CALLED BY */
6318 /* */
6319 /* mDNS component */
6320 /* */
6321 /* RELEASE HISTORY */
6322 /* */
6323 /* DATE NAME DESCRIPTION */
6324 /* */
6325 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6326 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
6327 /* buffer length verification, */
6328 /* verified memcpy use cases, */
6329 /* resulting in version 6.1 */
6330 /* */
6331 /**************************************************************************/
_nx_mdns_service_name_assemble(UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * domain,UCHAR * record_buffer,UINT buffer_size,UINT * type_index)6332 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)
6333 {
6334
6335 UINT index;
6336 UINT length;
6337
6338 /* Initialize the struct. */
6339 index = 0;
6340 memset(record_buffer, 0, buffer_size);
6341 if (type_index)
6342 {
6343 *type_index = 0;
6344 }
6345
6346 /* Construct the service name. */
6347
6348 /* Add the name. */
6349 if (name)
6350 {
6351
6352 /* Check string length. */
6353 if (_nx_utility_string_length_check((CHAR *)name, &length, NX_MDNS_NAME_MAX))
6354 {
6355 return (NX_MDNS_DATA_SIZE_ERROR);
6356 }
6357
6358 /* Verify buffer length. */
6359 if (index + length + 1 > buffer_size)
6360 {
6361 return (NX_MDNS_DATA_SIZE_ERROR);
6362 }
6363
6364 memcpy((CHAR *)(record_buffer + index), (const char*)name, length); /* Use case of memcpy is verified. */
6365 index += length;
6366
6367 *(record_buffer + index) = '.';
6368 index ++;
6369 }
6370
6371 /* Add the sub type. */
6372 if (sub_type)
6373 {
6374
6375 /* Check string length. */
6376 if (_nx_utility_string_length_check((CHAR *)sub_type, &length, NX_MDNS_LABEL_MAX))
6377 {
6378 return (NX_MDNS_DATA_SIZE_ERROR);
6379 }
6380
6381 /* Verify buffer length. */
6382 if (index + length + 1 + 4 + 1 > buffer_size)
6383 {
6384 return (NX_MDNS_DATA_SIZE_ERROR);
6385 }
6386
6387 if (type_index)
6388 {
6389 *type_index = index;
6390 }
6391 memcpy((CHAR *)(record_buffer + index), (const char*)sub_type, length); /* Use case of memcpy is verified. */
6392 index += length;
6393 *(record_buffer + index) = '.';
6394 index ++;
6395
6396 /* Add the key word "_sub". */
6397 memcpy((CHAR *)(record_buffer + index), (const char*)"_sub", 4); /* Use case of memcpy is verified. */
6398 index += 4;
6399 *(record_buffer + index) = '.';
6400 index ++;
6401 }
6402
6403 /* Add the type. */
6404 if (type)
6405 {
6406
6407 /* Check string length. */
6408 if (_nx_utility_string_length_check((CHAR *)type, &length, NX_MDNS_TYPE_MAX))
6409 {
6410 return (NX_MDNS_DATA_SIZE_ERROR);
6411 }
6412
6413 /* Verify buffer length. */
6414 if (index + length + 1 > buffer_size)
6415 {
6416 return (NX_MDNS_DATA_SIZE_ERROR);
6417 }
6418
6419 /* Set the type index. */
6420 if ((type_index) &&
6421 (!sub_type))
6422 {
6423 *type_index = index;
6424 }
6425
6426 memcpy((CHAR *)record_buffer + index, (const char*)type, length); /* Use case of memcpy is verified. */
6427 index += length;
6428 *(record_buffer + index) = '.';
6429 index ++;
6430 }
6431
6432 /* Add the domain. */
6433 if (domain)
6434 {
6435
6436 /* Check string length. */
6437 if (_nx_utility_string_length_check((CHAR *)domain, &length, NX_MDNS_DOMAIN_NAME_MAX))
6438 {
6439 return (NX_MDNS_DATA_SIZE_ERROR);
6440 }
6441
6442 /* Verify buffer length. */
6443 if (index + length > buffer_size)
6444 {
6445 return (NX_MDNS_DATA_SIZE_ERROR);
6446 }
6447
6448 memcpy((CHAR *)(record_buffer + index), (const char*)domain, length); /* Use case of memcpy is verified. */
6449 index += length;
6450 }
6451
6452 return(NX_MDNS_SUCCESS);
6453 }
6454
6455
6456 #ifndef NX_MDNS_DISABLE_SERVER
6457 /**************************************************************************/
6458 /* */
6459 /* FUNCTION RELEASE */
6460 /* */
6461 /* nx_mdns_host_name_register PORTABLE C */
6462 /* 6.1 */
6463 /* AUTHOR */
6464 /* */
6465 /* Yuxin Zhou, Microsoft Corporation */
6466 /* */
6467 /* DESCRIPTION */
6468 /* */
6469 /* This function resloves the service name, type, domain. */
6470 /* */
6471 /* INPUT */
6472 /* */
6473 /* mdns_ptr Pointer to mDNS instance */
6474 /* type The type of operation */
6475 /* interface_index The interface index */
6476 /* */
6477 /* OUTPUT */
6478 /* */
6479 /* status Completion status */
6480 /* */
6481 /* CALLS */
6482 /* */
6483 /* tx_mutex_get Get the mDNS mutex */
6484 /* tx_mutex_put Put the mDNS mutex */
6485 /* _nx_mdns_rr_a_aaaa_add Add the A/AAAA resource record*/
6486 /* */
6487 /* CALLED BY */
6488 /* */
6489 /* _nx_mdns_enable Enable mDNS */
6490 /* _nx_mdns_address_change_process Process address change */
6491 /* */
6492 /* RELEASE HISTORY */
6493 /* */
6494 /* DATE NAME DESCRIPTION */
6495 /* */
6496 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6497 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6498 /* verified memcpy use cases, */
6499 /* resulting in version 6.1 */
6500 /* */
6501 /**************************************************************************/
_nx_mdns_host_name_register(NX_MDNS * mdns_ptr,UCHAR type,UINT interface_index)6502 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index)
6503 {
6504
6505 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
6506 UINT status;
6507 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
6508 NX_IP *ip_ptr;
6509 UINT index = 0;
6510 UCHAR add_a = NX_FALSE;
6511 UCHAR add_aaaa = NX_FALSE;
6512 UINT host_name_length;
6513
6514 #ifdef NX_MDNS_ENABLE_IPV6
6515 NXD_IPV6_ADDRESS *ipv6_address_ptr;
6516 #endif /* NX_MDNS_ENABLE_IPV6 */
6517
6518
6519 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
6520 NX_PARAMETER_NOT_USED(type);
6521 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6 */
6522
6523 /* Check string length. */
6524 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_host_name, &host_name_length, NX_MDNS_HOST_NAME_MAX))
6525 {
6526 return (NX_MDNS_DATA_SIZE_ERROR);
6527 }
6528
6529 /* Construct the A/AAAA name. */
6530 memcpy((CHAR *)(&temp_string_buffer[index]), (const char*)mdns_ptr -> nx_mdns_host_name, host_name_length); /* Use case of memcpy is verified. */
6531 index += host_name_length;
6532
6533 temp_string_buffer[index] = '.';
6534 index ++;
6535 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.*/
6536
6537 /* Set the ip pointer. */
6538 ip_ptr = mdns_ptr -> nx_mdns_ip_ptr;
6539
6540 /* Get the IP mutex. */
6541 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
6542
6543 #ifndef NX_DISABLE_IPV4
6544 /* Add the A resource records message. */
6545 if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
6546 {
6547
6548 /* Add the A resource records message. */
6549 status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], &(ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address),
6550 NX_MDNS_IPV4_ADDRESS_LENGTH, type, interface_index);
6551
6552 /* Check the status. */
6553 if (status)
6554 {
6555
6556 /* Release the IP mutex. */
6557 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6558
6559 return(status);
6560 }
6561
6562 /* Set the flag. */
6563 add_a = NX_TRUE;
6564 }
6565 #endif /* NX_DISABLE_IPV4 */
6566
6567 #ifdef NX_MDNS_ENABLE_IPV6
6568 /* Get the IPv6 address pointer.*/
6569 ipv6_address_ptr = ip_ptr -> nx_ip_interface[interface_index].nxd_interface_ipv6_address_list_head;
6570
6571 while(ipv6_address_ptr)
6572 {
6573
6574 if (ipv6_address_ptr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)
6575 {
6576
6577 /* Add the AAAA resource records message. */
6578 status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], (ULONG *)(&ipv6_address_ptr -> nxd_ipv6_address[0]),
6579 NX_MDNS_IPV6_ADDRESS_LENGTH, type, interface_index);
6580
6581 /* Check the status. */
6582 if (status)
6583 {
6584
6585 /* Release the IP mutex. */
6586 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6587
6588 return(status);
6589 }
6590
6591 /* Set the flag. */
6592 add_aaaa = NX_TRUE;
6593 }
6594
6595 /* Update the pointer. */
6596 ipv6_address_ptr = ipv6_address_ptr -> nxd_ipv6_address_next;
6597 }
6598 #endif /* NX_MDNS_ENABLE_IPV6 */
6599
6600 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
6601
6602 /* Add the NSEC resource record. */
6603 if ((add_a == NX_TRUE) || (add_aaaa == NX_TRUE))
6604 _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], add_a, add_aaaa, NX_MDNS_ADD_NSEC_FOR_HOST, interface_index);
6605 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
6606
6607 /* Release the IP mutex. */
6608 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6609
6610 /* Return a successful status. */
6611 return(NX_SUCCESS);
6612 }
6613 #endif /* NX_MDNS_DISABLE_SERVER */
6614
6615
6616 /**************************************************************************/
6617 /* */
6618 /* FUNCTION RELEASE */
6619 /* */
6620 /* _nx_mdns_timer_entry PORTABLE C */
6621 /* 6.1 */
6622 /* AUTHOR */
6623 /* */
6624 /* Yuxin Zhou, Microsoft Corporation */
6625 /* */
6626 /* DESCRIPTION */
6627 /* */
6628 /* This function handles waking up the mDNS helper thread to process */
6629 /* the timer event on a periodic basis. */
6630 /* */
6631 /* INPUT */
6632 /* */
6633 /* mdns_value mDNS instance for a ulong */
6634 /* */
6635 /* OUTPUT */
6636 /* */
6637 /* None */
6638 /* */
6639 /* CALLS */
6640 /* */
6641 /* tx_event_flags_set Set event flags */
6642 /* */
6643 /* CALLED BY */
6644 /* */
6645 /* ThreadX system timer thread */
6646 /* */
6647 /* RELEASE HISTORY */
6648 /* */
6649 /* DATE NAME DESCRIPTION */
6650 /* */
6651 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6652 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6653 /* resulting in version 6.1 */
6654 /* */
6655 /**************************************************************************/
_nx_mdns_timer_entry(ULONG mdns_value)6656 static VOID _nx_mdns_timer_entry(ULONG mdns_value)
6657 {
6658
6659 NX_MDNS *mdns_ptr;
6660
6661
6662 /* Setup mDNS pointer from the input value. */
6663 mdns_ptr = (NX_MDNS *) mdns_value;
6664
6665 /* Set the timer event. */
6666 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_TIMER_EVENT, TX_OR);
6667
6668 return;
6669 }
6670
6671
6672 /**************************************************************************/
6673 /* */
6674 /* FUNCTION RELEASE */
6675 /* */
6676 /* _nx_mdns_timer_set PORTABLE C */
6677 /* 6.1 */
6678 /* AUTHOR */
6679 /* */
6680 /* Yuxin Zhou, Microsoft Corporation */
6681 /* */
6682 /* DESCRIPTION */
6683 /* */
6684 /* This function process all resource records according to the state, */
6685 /* Set the flags to send the probing, announcing, query, response and */
6686 /* goodbye mDNS message. Delete the resource record when the resource */
6687 /* record is invalid. */
6688 /* */
6689 /* INPUT */
6690 /* */
6691 /* mdns_ptr Pointer to mDNS instance */
6692 /* */
6693 /* OUTPUT */
6694 /* */
6695 /* status Completion status */
6696 /* */
6697 /* CALLS */
6698 /* */
6699 /* tx_timer_info_get Get the timer info */
6700 /* tx_timer_deactivate Deactivate the timer */
6701 /* tx_timer_change Change the timer */
6702 /* tx_timer_activate Activate the timer */
6703 /* */
6704 /* CALLED BY */
6705 /* */
6706 /* _nx_mdns_enable Enable the mDNS */
6707 /* _nx_mdns_rr_a_aaaa_add Add the A/AAAA resource record*/
6708 /* _nx_mdns_rr_ptr_add Add the ptr resource record */
6709 /* _nx_mdns_rr_srv_add Add the srv resource record */
6710 /* _nx_mdns_rr_txt_add Add the txt resource record */
6711 /* _nx_mdns_rr_delete Delete the resource record */
6712 /* _nx_mdns_local_cache_clear Clear the local cache */
6713 /* _nx_mdns_query Send the continuous query */
6714 /* _nx_mdns_packet_process Process mDNS packet */
6715 /* _nx_mdns_conflict_process Process the conflict */
6716 /* */
6717 /* RELEASE HISTORY */
6718 /* */
6719 /* DATE NAME DESCRIPTION */
6720 /* */
6721 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6722 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6723 /* resulting in version 6.1 */
6724 /* */
6725 /**************************************************************************/
_nx_mdns_timer_set(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr,ULONG timer_count)6726 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr, ULONG timer_count)
6727 {
6728
6729
6730 TX_INTERRUPT_SAVE_AREA
6731 ULONG remaining_ticks;
6732 ULONG schedule_count;
6733 UINT active;
6734
6735 if (timer_count)
6736 {
6737
6738 /* Disable interrupt */
6739 TX_DISABLE
6740
6741 /* Get the remaining_ticks of mDNS timer;*/
6742 tx_timer_info_get(&mdns_ptr -> nx_mdns_timer, TX_NULL, &active, &remaining_ticks, TX_NULL, TX_NULL);
6743
6744 /* If the timer is not active, the remaining ticks and schedule count are set to 0. */
6745 if(active == NX_FALSE)
6746 {
6747 remaining_ticks = 0;
6748 schedule_count = 0;
6749 }
6750 else
6751 {
6752
6753 /* Get the reschedule timer count of last timer. */
6754 schedule_count = mdns_ptr -> nx_mdns_timer_min_count;
6755 }
6756
6757 /* Check the timer. if exceed the timer count range, update the timer. */
6758 if((timer_count < remaining_ticks) || active == NX_FALSE)
6759 {
6760
6761 /* Set the minimum timer count.
6762 The minimum timer count indicate the intervals between last timer event and next timer event. */
6763 mdns_ptr -> nx_mdns_timer_min_count = (schedule_count - remaining_ticks) + timer_count;
6764
6765 /* Change the timer ticks with minimum timer count.*/
6766 tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
6767 tx_timer_change(&(mdns_ptr -> nx_mdns_timer), timer_count, timer_count );
6768 tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
6769 }
6770
6771 /* Update the Resource record life timer count*/
6772 record_rr -> nx_mdns_rr_timer_count = (schedule_count - remaining_ticks) + timer_count;
6773
6774 /* Restore interrupts. */
6775 TX_RESTORE
6776 }
6777 }
6778
6779
6780 /**************************************************************************/
6781 /* */
6782 /* FUNCTION RELEASE */
6783 /* */
6784 /* _nx_mdns_timer_event_process PORTABLE C */
6785 /* 6.1.11 */
6786 /* AUTHOR */
6787 /* */
6788 /* Yuxin Zhou, Microsoft Corporation */
6789 /* */
6790 /* DESCRIPTION */
6791 /* */
6792 /* This function process all resource records according to the state, */
6793 /* Set the flags to send the probing, announcing, query, response and */
6794 /* goodbye mDNS message. Delete the resource record when the resource */
6795 /* record is invalid. */
6796 /* */
6797 /* INPUT */
6798 /* */
6799 /* mdns_ptr Pointer to mDNS instance */
6800 /* */
6801 /* OUTPUT */
6802 /* */
6803 /* status Completion status */
6804 /* */
6805 /* CALLS */
6806 /* */
6807 /* tx_event_flags_set Set event flags to wake mDNS */
6808 /* tx_timer_deactivate Deactivate the timer */
6809 /* tx_timer_change Change the timer */
6810 /* tx_timer_activate Activate the timer */
6811 /* _nx_mdns_service_name_resolve Resolve the service name */
6812 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
6813 /* from the cache */
6814 /* */
6815 /* CALLED BY */
6816 /* */
6817 /* _nx_mdns_thread_entry Processing thread for mDNS */
6818 /* */
6819 /* RELEASE HISTORY */
6820 /* */
6821 /* DATE NAME DESCRIPTION */
6822 /* */
6823 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6824 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
6825 /* verified memcpy use cases, */
6826 /* resulting in version 6.1 */
6827 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
6828 /* corrected the random value, */
6829 /* fixed the issue of timer, */
6830 /* resulting in version 6.1.11 */
6831 /* */
6832 /**************************************************************************/
_nx_mdns_timer_event_process(NX_MDNS * mdns_ptr)6833 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr)
6834 {
6835
6836 ULONG event_flags = 0;
6837 ULONG timer_min_count = 0xFFFFFFFF;
6838 ULONG *head, *tail;
6839 NX_MDNS_RR *p;
6840 UCHAR i;
6841
6842 #ifndef NX_MDNS_DISABLE_CLIENT
6843 ULONG remaining_ticks;
6844 #endif /* NX_MDNS_DISABLE_CLIENT */
6845
6846 #ifndef NX_MDNS_DISABLE_SERVER
6847 UINT status;
6848 NX_MDNS_RR *p1;
6849 UCHAR *service_name;
6850 UCHAR *service_type;
6851 UCHAR *service_domain;
6852 UINT rr_name_length;
6853 #endif /* NX_MDNS_DISABLE_SERVER */
6854
6855
6856 for(i = 0; i < 2; i++)
6857 {
6858
6859 /* Set the pointer. */
6860 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
6861 {
6862 #ifndef NX_MDNS_DISABLE_SERVER
6863 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6864 #else
6865 continue;
6866 #endif /* NX_MDNS_DISABLE_SERVER */
6867 }
6868 else
6869 {
6870 #ifndef NX_MDNS_DISABLE_CLIENT
6871 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
6872 #else
6873 continue;
6874 #endif /* NX_MDNS_DISABLE_CLIENT */
6875 }
6876
6877 if(head == NX_NULL)
6878 continue;
6879
6880 tail = (ULONG*)(*head);
6881
6882 /* Check the remote resource record lifetime. */
6883 for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
6884 {
6885
6886 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
6887 continue;
6888
6889 /* Update the remaining ticks of peer resource record. */
6890 if (((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
6891 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)))
6892 {
6893 if (p -> nx_mdns_rr_remaining_ticks > mdns_ptr -> nx_mdns_timer_min_count)
6894 {
6895 p -> nx_mdns_rr_remaining_ticks -= mdns_ptr -> nx_mdns_timer_min_count;
6896 }
6897 else
6898 {
6899 p -> nx_mdns_rr_remaining_ticks = 0;
6900 }
6901 }
6902
6903 /* Calculate the time interval for two responses.*/
6904 if (p -> nx_mdns_rr_response_interval > mdns_ptr -> nx_mdns_timer_min_count)
6905 {
6906 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count);
6907
6908 /* Compare the timer count.and set the minimum timer count. */
6909 if ((p -> nx_mdns_rr_response_interval != 0) &&
6910 (p -> nx_mdns_rr_response_interval < timer_min_count))
6911 {
6912 timer_min_count = p -> nx_mdns_rr_response_interval;
6913 }
6914 }
6915 else
6916 {
6917 p -> nx_mdns_rr_response_interval = 0;
6918 }
6919
6920 /* If the timer count is zero, means do not do anything */
6921 if (p -> nx_mdns_rr_timer_count == 0)
6922 continue;
6923
6924 if (p -> nx_mdns_rr_timer_count > mdns_ptr -> nx_mdns_timer_min_count)
6925 {
6926 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_timer_count - mdns_ptr -> nx_mdns_timer_min_count;
6927
6928 /* Check the timer count range. */
6929 if (p -> nx_mdns_rr_timer_count <= NX_MDNS_TIMER_COUNT_RANGE)
6930 {
6931 p -> nx_mdns_rr_timer_count = 0;
6932 }
6933 else
6934 {
6935 /* Compare the timer count.and set the minimum timer count. */
6936 if (p -> nx_mdns_rr_timer_count < timer_min_count)
6937 {
6938 timer_min_count = p -> nx_mdns_rr_timer_count;
6939 }
6940 }
6941 }
6942 else
6943 {
6944 p -> nx_mdns_rr_timer_count = 0;
6945 }
6946
6947 /* If the timer count is zero, means the timeout. */
6948 if (p -> nx_mdns_rr_timer_count != 0)
6949 continue;
6950
6951 /* Check the state. */
6952 switch (p -> nx_mdns_rr_state)
6953 {
6954
6955 #ifndef NX_MDNS_DISABLE_SERVER
6956 case NX_MDNS_RR_STATE_PROBING:
6957 {
6958
6959 /* mDNS Server probing the RRs at 0ms, 250ms, 500ms. RFC6762, Section8.1, Page26. */
6960 if (p -> nx_mdns_rr_retransmit_count)
6961 {
6962
6963 /* Set the send flag.*/
6964 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
6965
6966 /* Set the probing flag. */
6967 event_flags = event_flags | NX_MDNS_PROBING_SEND_EVENT;
6968
6969 /* Set the timer count. 250ms. */
6970 p -> nx_mdns_rr_timer_count = NX_MDNS_PROBING_TIMER_COUNT;
6971
6972 /* Compare the timer count.and set the minimum timer count. */
6973 if (p -> nx_mdns_rr_timer_count < timer_min_count)
6974 {
6975 timer_min_count = p -> nx_mdns_rr_timer_count;
6976 }
6977 }
6978 else
6979 {
6980
6981 /* Probing complete, and move to the next step, Announcing. */
6982 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
6983
6984 /* Set the first announcing timer interval. */
6985 p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
6986
6987 /* Set the retransmit count. */
6988 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
6989 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
6990 else
6991 p -> nx_mdns_rr_retransmit_count = 1;
6992
6993 /* Set the next timer count. */
6994 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
6995
6996 /* Check the announcing max time. */
6997 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
6998 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
6999 else
7000 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
7001
7002 /* Yes, probing complete, add the related PTR resource records. */
7003 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
7004 {
7005
7006 /* Check string length. */
7007 if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
7008 {
7009 break;
7010 }
7011
7012 /* Store the service name. */
7013 memcpy((CHAR *)(&temp_string_buffer[0]), (const char*)p -> nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
7014
7015 /* Reslove the service name. */
7016 status = _nx_mdns_service_name_resolve(&temp_string_buffer[0], &service_name, &service_type, &service_domain);
7017
7018 /* Check the status. */
7019 if (status)
7020 {
7021 break;
7022 }
7023
7024 /* Service name registered success, invoke the notify function. */
7025 if (mdns_ptr -> nx_mdns_probing_notify)
7026 {
7027 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, service_name, NX_MDNS_LOCAL_SERVICE_REGISTERED_SUCCESS);
7028 }
7029 }
7030
7031 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A)
7032 {
7033
7034 /* Service name registered success, invoke the notify function. */
7035 if (mdns_ptr -> nx_mdns_probing_notify)
7036 {
7037 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, mdns_ptr -> nx_mdns_host_name, NX_MDNS_LOCAL_HOST_REGISTERED_SUCCESS);
7038 }
7039 }
7040
7041 /* Probing complete, Has been wating for 250ms, Directly announcing the resource record. */
7042 p --;
7043 }
7044 break;
7045 }
7046
7047 case NX_MDNS_RR_STATE_ANNOUNCING:
7048 {
7049
7050 /* mDNS Server Announcing the Resource records. */
7051 if (p -> nx_mdns_rr_retransmit_count)
7052 {
7053
7054 /* Set the send flag to send the probing. */
7055 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7056
7057 /* Set the announcing flag. */
7058 event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7059
7060 /* Yes, probing complete, add the related PTR resource records and NSEC resource records. */
7061 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
7062 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
7063 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
7064 {
7065
7066 for (p1 = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p1 < tail; p1++)
7067 {
7068
7069 /* Check the state. */
7070 if (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
7071 continue;
7072
7073 /* Check the interface. */
7074 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
7075 continue;
7076
7077 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7078 if ((p1 ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
7079 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name))
7080 {
7081
7082 /* Set the send flag to send the probing. */
7083 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7084 }
7085 #endif /*NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7086
7087 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
7088 (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
7089 (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_name))
7090 {
7091
7092 /* Set the send flag to send the probing. */
7093 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7094 }
7095 }
7096 }
7097
7098 /* Check last the retransmit in this period announcing. */
7099 if (p -> nx_mdns_rr_retransmit_count - 1)
7100 {
7101
7102 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7103 {
7104
7105 /* Set the timer count. */
7106 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_announcing_retrans_interval;
7107
7108 /* Compare the timer count and set the minimum timer count. */
7109 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7110 {
7111 timer_min_count = p -> nx_mdns_rr_timer_count;
7112 }
7113 }
7114 }
7115 else
7116 {
7117 if (p -> nx_mdns_rr_announcing_max_time)
7118 {
7119
7120 /* Update the timer count. */
7121 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7122
7123 /* Calculate the next timer count. */
7124 p -> nx_mdns_rr_retransmit_lifetime = (ULONG)(p -> nx_mdns_rr_retransmit_lifetime * (ULONG)(2 << (mdns_ptr -> nx_mdns_announcing_factor - 1)));
7125
7126 /* Check the announcing period time interval. */
7127 if (p -> nx_mdns_rr_retransmit_lifetime > mdns_ptr -> nx_mdns_announcing_period_interval)
7128 p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period_interval;
7129
7130 /* Set the retransmit count. */
7131 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7132 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
7133 else
7134 p -> nx_mdns_rr_retransmit_count = 1;
7135
7136 /* Set the retransmit count. */
7137 p -> nx_mdns_rr_retransmit_count++;
7138
7139 /* Check the announcing time. */
7140 if (p -> nx_mdns_rr_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
7141 p -> nx_mdns_rr_announcing_max_time--;
7142
7143 /* Compare the timer count and set the minimum timer count. */
7144 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7145 {
7146 timer_min_count = p -> nx_mdns_rr_timer_count;
7147 }
7148 }
7149 else
7150 {
7151
7152 /* Announcing complete, Update the resource record state valid, . */
7153 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
7154
7155 /* Clear the timer count. */
7156 p -> nx_mdns_rr_timer_count = 0;
7157 }
7158 }
7159 }
7160 break;
7161 }
7162
7163 case NX_MDNS_RR_STATE_GOODBYE:
7164 {
7165
7166 /* mDNS Server send Goodbye packet. */
7167 if (p -> nx_mdns_rr_retransmit_count)
7168 {
7169
7170 /* Set the send flag to send the probing. */
7171 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7172
7173 /* Set the announcing flag. */
7174 event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7175
7176 /* Set the timer count. */
7177 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
7178
7179 /* Compare the timer count.and set the minimum timer count. */
7180 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7181 {
7182 timer_min_count = p -> nx_mdns_rr_timer_count;
7183 }
7184 }
7185 else
7186 {
7187
7188 /* Check for RR delete flag. */
7189 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE)
7190 {
7191
7192 /* Delete the resource records. */
7193 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
7194 }
7195 else
7196 {
7197
7198 /* Suspend the resource record. */
7199 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
7200 p -> nx_mdns_rr_timer_count = 0;
7201 }
7202 }
7203 break;
7204 }
7205 #endif /* NX_MDNS_DISABLE_SERVER */
7206
7207
7208 case NX_MDNS_RR_STATE_VALID:
7209 {
7210
7211 if(i == NX_MDNS_CACHE_TYPE_PEER)
7212 {
7213 /* Set the resource record status. */
7214 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_UPDATING;
7215
7216 /* Check the updating flag. */
7217 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UPDATING)
7218 {
7219
7220 /* Set the retransmit count. */
7221 p -> nx_mdns_rr_retransmit_count = NX_MDNS_RR_UPDATE_COUNT;
7222
7223 /* 50% of the record lifetime has elapsed,the querier should plan to issure a query at 80%-82% of the record lifetime */
7224 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (((ULONG)NX_RAND()) % 3)) / 100;
7225 }
7226 else
7227 {
7228 /* Set the retransmit count. */
7229 p -> nx_mdns_rr_retransmit_count = 0;
7230
7231 /* 50% of the record lifetime has elapsed, Delete the resource record at 100% of the record lifetime */
7232 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
7233 }
7234
7235 /* Compare the timer count.and set the minimum timer count. */
7236 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7237 {
7238 timer_min_count = p -> nx_mdns_rr_timer_count;
7239 }
7240 }
7241
7242 /* Check the send flag. */
7243 else
7244 {
7245 if (p -> nx_mdns_rr_send_flag)
7246 {
7247
7248 /* Set the send flag to send the response. */
7249 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7250
7251 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7252 /* Clear the NSEC additional send. */
7253 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7254 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7255 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7256
7257 /* 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. */
7258 /* Set the next response time interval. */
7259 p -> nx_mdns_rr_response_interval = (ULONG)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE);
7260
7261 /* Compare the timer count.and set the minimum timer count. */
7262 if (p -> nx_mdns_rr_response_interval < timer_min_count)
7263 {
7264 timer_min_count = p -> nx_mdns_rr_response_interval;
7265 }
7266
7267 /* Set the announcing flag. */
7268 event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7269 }
7270
7271 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7272 else
7273 {
7274 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7275 {
7276 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send)
7277 {
7278 p -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_ADDITIONAL;
7279 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7280
7281 /* Set the announcing flag. */
7282 event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7283 }
7284 }
7285 }
7286 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7287 }
7288 break;
7289 }
7290
7291
7292 #ifndef NX_MDNS_DISABLE_CLIENT
7293 case NX_MDNS_RR_STATE_QUERY:
7294 {
7295
7296 /* mDNS Client did not receive the response, send the query again. */
7297 if (!p -> nx_mdns_rr_timer_count)
7298 {
7299
7300 /* Check the Duplicate Question. If the flag set, Host should not send the query until the next timeout. */
7301 if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DUPLICATE_QUERY))
7302 {
7303
7304 /* Set the send flag to send the query. */
7305 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7306
7307 /* Set the query flag. */
7308 event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7309 }
7310
7311 /* Clear the duplicate flag. */
7312 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
7313
7314 /* Double the next timer count. */
7315 p -> nx_mdns_rr_retransmit_lifetime = p -> nx_mdns_rr_retransmit_lifetime << 1;
7316
7317 /* The interval between the first two queries MUST be at least one second. RFC6762, Section5.2, Page9. */
7318 if (p -> nx_mdns_rr_retransmit_lifetime < NX_MDNS_QUERY_MIN_TIMER_COUNT)
7319 {
7320 p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MIN_TIMER_COUNT;
7321 }
7322
7323 /* 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. */
7324 if (p -> nx_mdns_rr_retransmit_lifetime > NX_MDNS_QUERY_MAX_TIMER_COUNT)
7325 {
7326 p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MAX_TIMER_COUNT;
7327 }
7328
7329 /* Update the timer count. */
7330 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7331
7332 /* Compare the timer count.and set the minimum timer count. */
7333 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7334 {
7335 timer_min_count = p -> nx_mdns_rr_timer_count;
7336 }
7337 }
7338 break;
7339 }
7340
7341 case NX_MDNS_RR_STATE_UPDATING:
7342 {
7343
7344 /* The querier should plan to issure a query at 80%-82% of the record lifetime, and then if no answer is received,
7345 at 85%-87%, 90%-92% and 95%-97%. the record is deleted when it reaches 100% of its lifetime. RFC6762, Section5.2, Page10. */
7346 if (p -> nx_mdns_rr_retransmit_count)
7347 {
7348
7349 /* Set the send flag to retransmit its query. */
7350 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7351
7352 /* Set the query flag. */
7353 event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7354
7355 /* Update the timer count. Client should send the updating message every 5% of ttl. */
7356 if (p -> nx_mdns_rr_retransmit_count == 1)
7357 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_remaining_ticks;
7358 else
7359 {
7360 remaining_ticks = p -> nx_mdns_rr_remaining_ticks;
7361 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 / 100;
7362
7363 /* Get the remaining ticks in 5% of TTL. */
7364 while(remaining_ticks > p -> nx_mdns_rr_timer_count)
7365 remaining_ticks -= p -> nx_mdns_rr_timer_count;
7366
7367 p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(((ULONG)NX_RAND()) % 3) / 100);
7368 }
7369
7370 /* Compare the timer count.and set the minimum timer count. */
7371 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7372 {
7373 timer_min_count = p -> nx_mdns_rr_timer_count;
7374 }
7375 }
7376 else
7377 {
7378
7379 /* Delete the resource record. */
7380 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7381 }
7382 break;
7383 }
7384
7385 case NX_MDNS_RR_STATE_DELETE:
7386 case NX_MDNS_RR_STATE_POOF_DELETE:
7387 {
7388
7389 /* Delete the resource record. */
7390 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7391 break;
7392 }
7393 #endif /* NX_MDNS_DISABLE_CLIENT */
7394
7395 default:
7396 {
7397 break;
7398 }
7399 }
7400 }
7401 }
7402
7403 /* If the specified timer rate is different with the new timer min count,then update it.*/
7404 if (mdns_ptr -> nx_mdns_timer_min_count != timer_min_count)
7405 {
7406
7407 /* Set the minimum timer count.*/
7408 mdns_ptr -> nx_mdns_timer_min_count = timer_min_count;
7409
7410 /* Deactivate the timer. */
7411 tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
7412
7413 if (timer_min_count != 0xFFFFFFFF)
7414 {
7415
7416 /* Change the timer ticks with minimum timer count.*/
7417 tx_timer_change(&(mdns_ptr -> nx_mdns_timer),
7418 mdns_ptr -> nx_mdns_timer_min_count,
7419 mdns_ptr -> nx_mdns_timer_min_count);
7420 tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
7421 }
7422 }
7423
7424 /* Set the event to send mDNS query. */
7425 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), event_flags, TX_OR);
7426 }
7427
7428
7429 /**************************************************************************/
7430 /* */
7431 /* FUNCTION RELEASE */
7432 /* */
7433 /* _nx_mdns_udp_receive_notify PORTABLE C */
7434 /* 6.1 */
7435 /* AUTHOR */
7436 /* */
7437 /* Yuxin Zhou, Microsoft Corporation */
7438 /* */
7439 /* DESCRIPTION */
7440 /* */
7441 /* This function is the mDNS UDP receive notify callback. */
7442 /* */
7443 /* INPUT */
7444 /* */
7445 /* socket_ptr Pointer to udp socket */
7446 /* */
7447 /* OUTPUT */
7448 /* */
7449 /* None */
7450 /* */
7451 /* CALLS */
7452 /* */
7453 /* tx_event_flags_set Set event flags */
7454 /* */
7455 /* CALLED BY */
7456 /* */
7457 /* UDP receive callback */
7458 /* */
7459 /* RELEASE HISTORY */
7460 /* */
7461 /* DATE NAME DESCRIPTION */
7462 /* */
7463 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7464 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7465 /* resulting in version 6.1 */
7466 /* */
7467 /**************************************************************************/
_nx_mdns_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)7468 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
7469 {
7470
7471
7472 NX_PARAMETER_NOT_USED(socket_ptr);
7473
7474 /* Check the mDNS. */
7475 if(_nx_mdns_created_ptr)
7476 {
7477
7478 /* Set the receive UDP packet notify. */
7479 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_PKT_RX_EVENT, TX_OR);
7480 }
7481
7482 return;
7483 }
7484
7485 #ifndef NX_MDNS_DISABLE_SERVER
7486 #ifndef NX_DISABLE_IPV4
7487 /**************************************************************************/
7488 /* */
7489 /* FUNCTION RELEASE */
7490 /* */
7491 /* _nx_mdns_ip_address_change_notify PORTABLE C */
7492 /* 6.1 */
7493 /* AUTHOR */
7494 /* */
7495 /* Yuxin Zhou, Microsoft Corporation */
7496 /* */
7497 /* DESCRIPTION */
7498 /* */
7499 /* This function is the mDNS UDP receive notify callback. */
7500 /* */
7501 /* INPUT */
7502 /* */
7503 /* socket_ptr Pointer to udp socket */
7504 /* */
7505 /* OUTPUT */
7506 /* */
7507 /* None */
7508 /* */
7509 /* CALLS */
7510 /* */
7511 /* tx_event_flags_set Set event flags */
7512 /* */
7513 /* CALLED BY */
7514 /* */
7515 /* UDP receive callback */
7516 /* */
7517 /* RELEASE HISTORY */
7518 /* */
7519 /* DATE NAME DESCRIPTION */
7520 /* */
7521 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7522 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7523 /* resulting in version 6.1 */
7524 /* */
7525 /**************************************************************************/
_nx_mdns_ip_address_change_notify(NX_IP * ip_ptr,VOID * additional_info)7526 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info)
7527 {
7528
7529
7530 NX_PARAMETER_NOT_USED(ip_ptr);
7531 NX_PARAMETER_NOT_USED(additional_info);
7532
7533 /* Check the mDNS. */
7534 if(_nx_mdns_created_ptr)
7535 {
7536
7537 /* Set the address change event event. */
7538 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7539 }
7540
7541 return;
7542 }
7543 #endif /* NX_DISABLE_IPV4 */
7544
7545
7546 /**************************************************************************/
7547 /* */
7548 /* FUNCTION RELEASE */
7549 /* */
7550 /* _nx_mdns_ipv6_address_change_notify PORTABLE C */
7551 /* 6.1 */
7552 /* AUTHOR */
7553 /* */
7554 /* Yuxin Zhou, Microsoft Corporation */
7555 /* */
7556 /* DESCRIPTION */
7557 /* */
7558 /* This function is the mDNS UDP receive notify callback. */
7559 /* */
7560 /* INPUT */
7561 /* */
7562 /* socket_ptr Pointer to udp socket */
7563 /* */
7564 /* OUTPUT */
7565 /* */
7566 /* None */
7567 /* */
7568 /* CALLS */
7569 /* */
7570 /* tx_event_flags_set Set event flags */
7571 /* */
7572 /* CALLED BY */
7573 /* */
7574 /* UDP receive callback */
7575 /* */
7576 /* RELEASE HISTORY */
7577 /* */
7578 /* DATE NAME DESCRIPTION */
7579 /* */
7580 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7581 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7582 /* resulting in version 6.1 */
7583 /* */
7584 /**************************************************************************/
7585 #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)7586 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address)
7587 {
7588
7589 NX_PARAMETER_NOT_USED(ip_ptr);
7590 NX_PARAMETER_NOT_USED(method);
7591 NX_PARAMETER_NOT_USED(interface_index);
7592 NX_PARAMETER_NOT_USED(index);
7593 NX_PARAMETER_NOT_USED(ipv6_address);
7594
7595 /* Check the mDNS. */
7596 if(_nx_mdns_created_ptr)
7597 {
7598
7599 /* Set the address change event. */
7600 tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7601 }
7602 return;
7603 }
7604 #endif /* NX_MDNS_ENABLE_IPV6 */
7605 #endif /* NX_MDNS_DISABLE_SERVER */
7606
7607
7608 /**************************************************************************/
7609 /* */
7610 /* FUNCTION RELEASE */
7611 /* */
7612 /* _nx_mdns_thread_entry PORTABLE C */
7613 /* 6.1 */
7614 /* AUTHOR */
7615 /* */
7616 /* Yuxin Zhou, Microsoft Corporation */
7617 /* */
7618 /* DESCRIPTION */
7619 /* */
7620 /* This function is the entry point for the mDNS helper thread. */
7621 /* mDNS helper thread is responsible for processing mDNS events. */
7622 /* Receive and send the mDNS packet. */
7623 /* */
7624 /* INPUT */
7625 /* */
7626 /* mdns_value Pointer to mDNS instance */
7627 /* */
7628 /* OUTPUT */
7629 /* */
7630 /* None */
7631 /* */
7632 /* CALLS */
7633 /* */
7634 /* tx_mutex_get Get the mDNS mutex */
7635 /* tx_mutex_put Put the mDNS mutex */
7636 /* tx_event_flags_get Get the mDNS events */
7637 /* nx_udp_socket_receive Receive the mDNS packet */
7638 /* nx_packet_release Release the mDNS packet */
7639 /* _nx_mdns_packet_process Process mDNS packet */
7640 /* _nx_mdns_announcing_send Send announcing message */
7641 /* _nx_mdns_probing_send Send probing message */
7642 /* _nx_mdns_query_send Send query message */
7643 /* _nx_mdns_response_send Send response message */
7644 /* _nx_mdns_timer_event_process Process the mDNS timer event */
7645 /* _nx_mdns_address_change_process Process the address change */
7646 /* */
7647 /* CALLED BY */
7648 /* */
7649 /* ThreadX Scheduler */
7650 /* */
7651 /* RELEASE HISTORY */
7652 /* */
7653 /* DATE NAME DESCRIPTION */
7654 /* */
7655 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7656 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7657 /* resulting in version 6.1 */
7658 /* */
7659 /**************************************************************************/
_nx_mdns_thread_entry(ULONG mdns_value)7660 static VOID _nx_mdns_thread_entry(ULONG mdns_value)
7661 {
7662
7663 NX_MDNS *mdns_ptr;
7664 NX_PACKET *packet_ptr;
7665 ULONG mdns_events;
7666 UINT status;
7667 UINT interface_index;
7668
7669
7670 /* Setup mDNS pointer from the input value. */
7671 mdns_ptr = (NX_MDNS *) mdns_value;
7672
7673 /* Get the mDNS mutex. */
7674 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7675
7676 /* Loop to process events for this mDNS instance. */
7677 while(1)
7678 {
7679
7680 /* Release the mDNS mutex. */
7681 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
7682
7683 /* Pickup mDNS event flags. */
7684 tx_event_flags_get(&mdns_ptr -> nx_mdns_events,
7685 NX_MDNS_ALL_EVENTS, TX_OR_CLEAR,
7686 &mdns_events, TX_WAIT_FOREVER);
7687
7688 /* Get the mDNS mutex. */
7689 tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7690
7691 /* Check for an UDP packet receive event. */
7692 if (mdns_events & NX_MDNS_PKT_RX_EVENT)
7693 {
7694 while (1)
7695 {
7696
7697 /* Receive a UDP packet. */
7698 status = _nx_udp_socket_receive(&mdns_ptr -> nx_mdns_socket,
7699 &packet_ptr, TX_NO_WAIT);
7700
7701 /* Check status. */
7702 if (status != NX_SUCCESS)
7703 break;
7704
7705 #ifndef NX_DISABLE_PACKET_CHAIN
7706
7707 /* Discard the chained packets. */
7708 if (packet_ptr -> nx_packet_next)
7709 {
7710 nx_packet_release(packet_ptr);
7711 continue;
7712 }
7713 #endif
7714
7715 /* Get the interface. */
7716 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
7717 {
7718 interface_index = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
7719 }
7720 else
7721 {
7722 interface_index = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_index;
7723 }
7724
7725 /* Check the interface. */
7726 if (!mdns_ptr -> nx_mdns_interface_enabled[interface_index])
7727 {
7728 /* Release the packet since mDNS is not enabled on this interface. */
7729 nx_packet_release(packet_ptr);
7730 continue;
7731 }
7732
7733 /* Yes, Get the mDNS packet, process it. */
7734 _nx_mdns_packet_process(mdns_ptr, packet_ptr, interface_index);
7735
7736 /* Release the packet. */
7737 nx_packet_release(packet_ptr);
7738 }
7739 }
7740
7741 /* Loop to send mDNS message for each interface. */
7742 for (interface_index = 0; interface_index < NX_MAX_PHYSICAL_INTERFACES; interface_index++)
7743 {
7744
7745 /* Check if this interface is enabled.
7746 Exception: Goodbye message can be sent out after disable. */
7747 if ((!mdns_ptr -> nx_mdns_interface_enabled[interface_index]) &&
7748 (!(mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)))
7749 continue;
7750
7751 #ifndef NX_MDNS_DISABLE_SERVER
7752
7753 /* Check for an mDNS probing send event. */
7754 if (mdns_events & NX_MDNS_PROBING_SEND_EVENT)
7755 {
7756
7757 /* Send probing. */
7758 _nx_mdns_probing_send(mdns_ptr, interface_index);
7759 }
7760
7761 /* Check for an mDNS announcing send event. */
7762 if (mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)
7763 {
7764
7765 /* Send announcing. */
7766 _nx_mdns_announcing_send(mdns_ptr, interface_index);
7767 }
7768
7769 /* Check for an mDNS response send event. */
7770 if (mdns_events & NX_MDNS_RESPONSE_SEND_EVENT)
7771 {
7772
7773 /* Send response. */
7774 _nx_mdns_response_send(mdns_ptr, interface_index);
7775 }
7776 #endif /* NX_MDNS_DISABLE_SERVER */
7777
7778 #ifndef NX_MDNS_DISABLE_CLIENT
7779 /* Check for an mDNS query send event. */
7780 if (mdns_events & NX_MDNS_QUERY_SEND_EVENT)
7781 {
7782
7783 /* Send query. */
7784 _nx_mdns_query_send(mdns_ptr, interface_index);
7785 }
7786 #endif /* NX_MDNS_DISABLE_CLIENT */
7787 }
7788
7789 #ifndef NX_MDNS_DISABLE_SERVER
7790
7791 /* Check for an mDNS address change event. */
7792 if (mdns_events & NX_MDNS_ADDRESS_CHANGE_EVENT)
7793 {
7794
7795 /* Process the address change event. */
7796 _nx_mdns_address_change_process(mdns_ptr);
7797 }
7798 #endif /* NX_MDNS_DISABLE_SERVER */
7799
7800 /* Check for an mDNS timer process event. */
7801 if (mdns_events & NX_MDNS_TIMER_EVENT)
7802 {
7803
7804 /* Process the timer event. */
7805 _nx_mdns_timer_event_process(mdns_ptr);
7806 }
7807 }
7808 }
7809
7810
7811 /**************************************************************************/
7812 /* */
7813 /* FUNCTION RELEASE */
7814 /* */
7815 /* _nx_mdns_packet_process PORTABLE C */
7816 /* 6.1.11 */
7817 /* AUTHOR */
7818 /* */
7819 /* Yuxin Zhou, Microsoft Corporation */
7820 /* */
7821 /* DESCRIPTION */
7822 /* */
7823 /* This function checks the interface and the IP address of received */
7824 /* packet, then preocesses the packet. */
7825 /* */
7826 /* INPUT */
7827 /* */
7828 /* mdns_ptr Pointer to mDNS instance */
7829 /* packet_ptr Pointer to mDNS packet */
7830 /* */
7831 /* OUTPUT */
7832 /* */
7833 /* status Completion status */
7834 /* */
7835 /* CALLS */
7836 /* */
7837 /* nx_packet_release Release the mDNS packet */
7838 /* _tx_thread_system_resume Resume thread service */
7839 /* _nx_mdns_timer_set Set the mDNS timer */
7840 /* _nx_mdns_name_string_decode Decode the name size */
7841 /* _nx_mdns_name_size_calculate Calculate the name size */
7842 /* _nx_mdns_rr_size_get Get the resource record size */
7843 /* _nx_mdns_conflict_process Process the mDNS conflict */
7844 /* _nx_mdns_cache_find_resource_record Find the mDNS resource record */
7845 /* _nx_mdns_packet_address_check Check the address and port */
7846 /* _nx_mdns_packet_rr_process Process resource record */
7847 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
7848 /* from cache */
7849 /* nxd_udp_packet_info_extract Extract the packet info */
7850 /* */
7851 /* CALLED BY */
7852 /* */
7853 /* _nx_mdns_thread_entry Processing thread for mDNS */
7854 /* */
7855 /* RELEASE HISTORY */
7856 /* */
7857 /* DATE NAME DESCRIPTION */
7858 /* */
7859 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7860 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7861 /* resulting in version 6.1 */
7862 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
7863 /* packet length verification, */
7864 /* resulting in version 6.1.4 */
7865 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
7866 /* corrected the random value, */
7867 /* fixed the issue of timer, */
7868 /* resulting in version 6.1.11 */
7869 /* */
7870 /**************************************************************************/
_nx_mdns_packet_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)7871 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
7872 {
7873
7874 USHORT mdns_flags;
7875 UCHAR *data_ptr;
7876 USHORT question_count;
7877 USHORT authority_count;
7878 USHORT answer_count;
7879 UINT index;
7880 NX_MDNS_RR *rr_search;
7881 NX_MDNS_RR temp_resource_record;
7882
7883 #ifndef NX_MDNS_DISABLE_SERVER
7884 ULONG *head;
7885 NX_MDNS_RR *p;
7886 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7887 ULONG match_count;
7888 NX_MDNS_RR *nsec_rr;
7889 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
7890 #endif /* NX_MDNS_DISABLE_SERVER */
7891
7892
7893 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
7894 /* Check the address and port. */
7895 if (_nx_mdns_packet_address_check(packet_ptr))
7896 {
7897 return(NX_MDNS_ERROR);
7898 }
7899 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
7900
7901 /* Check the packet length. */
7902 if (packet_ptr -> nx_packet_length < NX_MDNS_QDSECT_OFFSET)
7903 {
7904 return(NX_MDNS_ERROR);
7905 }
7906
7907 /* Extract the message type which should be the first byte. */
7908 mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
7909
7910 /* Get the question count. */
7911 question_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET);
7912
7913 /* Determine if we have any 'answers' to our DNS query. */
7914 answer_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET);
7915
7916 /* Also check if there are any 'hints' from the Authoritative nameserver. */
7917 authority_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET);
7918
7919 /* Update the answer count. Ignore the authority count and additional count for query message. */
7920 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7921 {
7922 answer_count = (USHORT)(answer_count + authority_count);
7923
7924 /* Include Additional section as well */
7925 answer_count = (USHORT)(answer_count + NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET));
7926 }
7927
7928 /* Skip the Header. Point at the start of the question. */
7929 data_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
7930
7931 /* Process all the Question Section. */
7932 for (index = 0; index < question_count; index++)
7933 {
7934
7935 /* Check for data_ptr. */
7936 if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
7937 break;
7938
7939 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7940 {
7941
7942 /* Multicast DNS responses MUST NOT contain any question in the Question Section,
7943 Any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. RFC6762, Section6, Page14. */
7944 data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
7945 }
7946 else
7947 {
7948
7949 #ifndef NX_MDNS_DISABLE_CLIENT
7950
7951 /* Step1, mDNS Client process the Duplicate Question Suppression, RFC6762, Section7.3, Page24. */
7952 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)
7953 {
7954
7955 /* Check the class top bit "QM". */
7956 if ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_RR_CLASS_TOP_BIT) != NX_MDNS_RR_CLASS_TOP_BIT)
7957 {
7958
7959 /* Find the same resource record in remote buffer. */
7960 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)
7961 {
7962
7963 /* Duplicate Question Suppression. */
7964 if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
7965 {
7966
7967 if (_nx_mdns_known_answer_find(mdns_ptr, rr_search) == NX_MDNS_NO_KNOWN_ANSWER)
7968 {
7969
7970 /* Yes, set the duplicate flag. process this flag in timer event process function. */
7971 rr_search -> nx_mdns_rr_word = rr_search -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DUPLICATE_QUERY;
7972 }
7973 }
7974
7975 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
7976 /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
7977 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
7978 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
7979 {
7980 rr_search -> nx_mdns_rr_poof_count ++;
7981
7982 /* 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. */
7983 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
7984 (rr_search -> nx_mdns_rr_poof_count >= NX_MDNS_POOF_MIN_COUNT))
7985 {
7986 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_POOF_DELETE;
7987 rr_search -> nx_mdns_rr_timer_count = NX_MDNS_POOF_TIMER_COUNT;
7988
7989 /* Set the mDNS timer. */
7990 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
7991 }
7992 }
7993 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
7994 }
7995 }
7996 }
7997 #endif /* NX_MDNS_DISABLE_CLIENT */
7998
7999 #ifndef NX_MDNS_DISABLE_SERVER
8000
8001 /* Step2, mDNS Server process the normal query. */
8002 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)
8003 {
8004
8005 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8006 /* Set the match count. */
8007 match_count = 0;
8008 nsec_rr = NX_NULL;
8009 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8010
8011 /* Get head. */
8012 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8013 head = (ULONG*)(*head);
8014
8015 /* Find the same record. */
8016 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
8017 {
8018
8019 /* Check the interface index. */
8020 if (p -> nx_mdns_rr_interface_index != interface_index)
8021 continue;
8022
8023 /* Check whether the resource record is valid. */
8024 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
8025 continue;
8026
8027 /* Check whether the same record it is. RFC6762, Section6, Page13. */
8028 /* The rules: rrname must match the question name.
8029 rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
8030 rrclass must match the question qclass unless the qclass is "ANY". */
8031 if (p -> nx_mdns_rr_name != temp_resource_record.nx_mdns_rr_name)
8032 continue;
8033
8034 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8035
8036 /* Check the NSEC type. */
8037 if (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
8038 nsec_rr = p;
8039 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8040
8041 if ((p -> nx_mdns_rr_type != temp_resource_record.nx_mdns_rr_type) &&
8042 (temp_resource_record.nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
8043 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
8044 continue;
8045
8046 /* Check the RR class, Ignore the top bit. */
8047 if ((p -> nx_mdns_rr_class != (temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
8048 ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)!= NX_MDNS_RR_CLASS_ALL))
8049 continue;
8050
8051 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8052
8053 /* Update the match count. */
8054 match_count ++;
8055 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8056
8057 /* Check the state. */
8058 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8059 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
8060 {
8061
8062 /* Check the send flag, Flag is set indicate this resource record shoud be sent. */
8063 if (p -> nx_mdns_rr_send_flag)
8064 {
8065
8066 /* Set the flag to send this Resource records via multicast.
8067 Store the old flag into the top bits.
8068 Store the new flag into the low bits.
8069 Format: 0001 0001 */
8070 p -> nx_mdns_rr_send_flag = ((NX_MDNS_RR_SEND_MULTICAST << 4) | NX_MDNS_RR_SEND_MULTICAST);
8071 }
8072 else
8073 {
8074
8075 /* Set the flag to send this Resource records via multicast.*/
8076 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8077 }
8078
8079 /* In the case where the query has the TC (truncated) bit set, indicating that subsequent Known-Answer packets will follow,
8080 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. */
8081 if (mdns_flags & NX_MDNS_TC_FLAG)
8082 {
8083 p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_TC_DELAY_RANGE));
8084 }
8085 else
8086 {
8087
8088 /* A mDNS responder is only required to delay its transmission as necessary to ensure an interval of at least 250ms
8089 since the last time the record was multicast on that interface. RFC6762, Section6, Page16 */
8090 if (authority_count)
8091 {
8092 if (p -> nx_mdns_rr_response_interval > (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT))
8093 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT));
8094 else
8095 p -> nx_mdns_rr_response_interval = 0;
8096 }
8097
8098 /* Check the response interval. */
8099 if (p -> nx_mdns_rr_response_interval <= NX_MDNS_TIMER_COUNT_RANGE)
8100 {
8101
8102 /* Set the timer count according to the resource record set.RFC6762, Section6, Page14. */
8103 if ((p ->nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) == NX_MDNS_RR_FLAG_UNIQUE)
8104 {
8105 p -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8106 }
8107 else
8108 {
8109 /* Set the timer count, delay 20-120ms. */
8110 p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8111 }
8112 }
8113 else
8114 {
8115 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_response_interval;
8116 }
8117 }
8118
8119 /* Set the mDNS timer. */
8120 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
8121 }
8122 }
8123
8124 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8125 /* Send this NSEC response as additional answer. */
8126 if ((match_count == 0) && (nsec_rr))
8127 {
8128 nsec_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_TRUE;
8129 nsec_rr -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8130 _nx_mdns_timer_set(mdns_ptr, nsec_rr, nsec_rr -> nx_mdns_rr_timer_count);
8131 }
8132 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
8133 }
8134 #endif /* NX_MDNS_DISABLE_SERVER */
8135
8136 /* Update the data_ptr. */
8137 data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
8138 }
8139 }
8140
8141 /* Process all the Known-Answer records. */
8142 for (index = 0; index < answer_count; index++)
8143 {
8144
8145 /* Check for data_ptr. */
8146 if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
8147 break;
8148
8149 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
8150 {
8151
8152 #ifndef NX_MDNS_DISABLE_SERVER
8153 /* Step1, Cooperating Multicast DNS Responders, RFC6762, Section6.6, Page21. */
8154 /* Does the same rname and rdata name of resource record exist in the local buffer. */
8155 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)
8156 {
8157
8158 /* Find the same rname, rrtype, rrclass of resource record in local buffer. */
8159 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)
8160 {
8161
8162 /* Probing state, conflict Resolution. */
8163 if ((rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) &&
8164 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING))
8165 {
8166 _nx_mdns_conflict_process(mdns_ptr, rr_search);
8167
8168 /* Update the data_ptr. */
8169 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8170
8171 continue;
8172 }
8173 }
8174
8175 /* Find the same rname, rrtype, rrclass and identical rdata of resource record in local buffer. */
8176 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)
8177 {
8178
8179 /* 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. */
8180 if ((temp_resource_record.nx_mdns_rr_ttl << 1) < rr_search -> nx_mdns_rr_ttl)
8181 {
8182
8183 /* Set the flag. */
8184 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8185
8186 /* Set the timer count, delay 20-120ms. */
8187 rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8188
8189 /* Set the mDNS timer. */
8190 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
8191 }
8192
8193 /* Duplicate Answer Suppression, RFC6762, Section7.4,Page24.
8194 The TTL in that record is not less than the TTL this host would have given. Host should not send this response again. */
8195 if (temp_resource_record.nx_mdns_rr_ttl >= rr_search -> nx_mdns_rr_ttl)
8196 {
8197
8198 if (rr_search -> nx_mdns_rr_send_flag)
8199 {
8200
8201 /* Clear the flag. */
8202 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8203 }
8204 }
8205
8206 /* Check the resource records set. */
8207 if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8208 {
8209
8210 /* Update the data_ptr. */
8211 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8212
8213 continue;
8214 }
8215 }
8216 }
8217
8218 /* Did the same name of resource record have existed in local buffer. */
8219 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)
8220 {
8221
8222 /* Find the same name, rrtype, rrclass and different rdata of resource record in local buffer. */
8223 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)
8224 {
8225
8226 /* Check the resource records set. RFC6762, Section6.6, Page21. */
8227 if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8228 {
8229 _nx_mdns_conflict_process(mdns_ptr, rr_search);
8230
8231 /* Update the data_ptr. */
8232 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8233
8234 continue;
8235 }
8236 }
8237 }
8238 #endif /* NX_MDNS_DISABLE_SERVER */
8239
8240 #ifndef NX_MDNS_DISABLE_CLIENT
8241 /* Step2. Add the response resource records in remote buffer. */
8242 _nx_mdns_packet_rr_process(mdns_ptr, packet_ptr, data_ptr, interface_index);
8243 #endif /* NX_MDNS_DISABLE_CLIENT */
8244 }
8245 else
8246 {
8247 #ifndef NX_MDNS_DISABLE_CLIENT
8248 /* Clear the record. */
8249
8250 /* Step1, mDNS Client process the Known-Answer about Duplicate Question Suppression. */
8251 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)
8252 {
8253
8254 /* Find the same resource record in remote buffer. */
8255 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)
8256 {
8257
8258 /* Duplicate Question Suppression. */
8259 if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
8260 {
8261
8262 /* Yes, the query includes the Known-Answer Section, clear the duplicate flag. */
8263 rr_search -> nx_mdns_rr_word = (USHORT)(rr_search -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
8264 }
8265
8266 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
8267 /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
8268 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8269 (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
8270 {
8271 rr_search -> nx_mdns_rr_poof_count --;
8272
8273 /* Check the count. */
8274 if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE) &&
8275 (rr_search -> nx_mdns_rr_poof_count < NX_MDNS_POOF_MIN_COUNT))
8276 {
8277 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
8278 rr_search -> nx_mdns_rr_timer_count = 0;
8279 }
8280 }
8281 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
8282 }
8283 }
8284 #endif /* NX_MDNS_DISABLE_CLIENT */
8285
8286 #ifndef NX_MDNS_DISABLE_SERVER
8287
8288 /* Step2. mDNS Server process the Known-Answer of normal query. */
8289 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)
8290 {
8291
8292 /* Find the same resource record. */
8293 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)
8294 {
8295
8296 /* 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. */
8297 if ((!(rr_search -> nx_mdns_rr_send_flag & NX_MDNS_RR_SEND_FLAG_MASK)) &&
8298 ((temp_resource_record.nx_mdns_rr_ttl << 1) >= rr_search -> nx_mdns_rr_ttl))
8299 {
8300
8301 /* Top four bit is zero and this resource reocrd is Known answer.
8302 Clear the send flag. */
8303 rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8304 }
8305 }
8306 }
8307 #endif /* NX_MDNS_DISABLE_SERVER */
8308 }
8309
8310 /* Update the data_ptr. */
8311 data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8312 }
8313
8314 return(NX_MDNS_SUCCESS);
8315 }
8316
8317
8318 #ifndef NX_MDNS_DISABLE_SERVER
8319 /**************************************************************************/
8320 /* */
8321 /* FUNCTION RELEASE */
8322 /* */
8323 /* _nx_mdns_probing_send PORTABLE C */
8324 /* 6.1 */
8325 /* AUTHOR */
8326 /* */
8327 /* Yuxin Zhou, Microsoft Corporation */
8328 /* */
8329 /* DESCRIPTION */
8330 /* */
8331 /* This function sends mDNS probing message. */
8332 /* */
8333 /* INPUT */
8334 /* */
8335 /* mdns_ptr Pointer to mDNS instance */
8336 /* */
8337 /* OUTPUT */
8338 /* */
8339 /* none */
8340 /* */
8341 /* CALLS */
8342 /* */
8343 /* */
8344 /* CALLED BY */
8345 /* */
8346 /* */
8347 /* RELEASE HISTORY */
8348 /* */
8349 /* DATE NAME DESCRIPTION */
8350 /* */
8351 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8352 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8353 /* resulting in version 6.1 */
8354 /* */
8355 /**************************************************************************/
_nx_mdns_probing_send(NX_MDNS * mdns_ptr,UINT interface_index)8356 static VOID _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8357 {
8358
8359 UINT status;
8360 NX_PACKET *packet_ptr;
8361 ULONG *head;
8362 NX_MDNS_RR *p;
8363 USHORT question_count = 0;
8364 USHORT answer_count = 0;
8365 USHORT authority_count = 0;
8366 USHORT additional_count = 0;
8367 UCHAR resend_flag = NX_FALSE;
8368 USHORT total_size;
8369 USHORT rr_size;
8370 UINT name_size;
8371 NX_MDNS_RR *p1;
8372 UINT rr_name_length;
8373
8374
8375 /* Create the mdns packet and add the mDNS header. */
8376 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8377
8378 /* Check for errors. */
8379 if (status != NX_SUCCESS)
8380 {
8381 return;
8382 }
8383
8384 /* Set the total size. */
8385 total_size = (USHORT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
8386
8387 /* Set the head pointer. */
8388 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8389
8390 /* Add the answer resource record. */
8391 for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8392 {
8393
8394 /* Check the interface index. */
8395 if (p -> nx_mdns_rr_interface_index != interface_index)
8396 continue;
8397
8398 /* Check the send flag. */
8399 if (p -> nx_mdns_rr_send_flag == 0)
8400 continue;
8401
8402 /* Check the state. */
8403 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8404 continue;
8405
8406 /* Add the resource record into packet. */
8407
8408 /* Calculate the question and answer size before sending the probing message, make sure the question and authority in one packet. */
8409
8410 /* Check string length. */
8411 if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
8412 {
8413 continue;
8414 }
8415
8416 /* Calculate the name size. The name should plus the '.' and '\0'. */
8417 name_size = rr_name_length + 2;
8418
8419 /* Calculate the resource record size for question. QNAME, QTYPE, QCLASS. */
8420 rr_size = (USHORT)(name_size + 4);
8421
8422 /* Calcuate the resource record size for authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
8423 rr_size = (USHORT)(rr_size + (name_size + 10 + p -> nx_mdns_rr_rdata_length));
8424
8425 /* Check if need add other authority answers for this same question. */
8426 for(p1 = (NX_MDNS_RR*)(head + 1); (ULONG)p1 < *head; p1++)
8427 {
8428
8429 /* Check the interface index. */
8430 if (p1 -> nx_mdns_rr_interface_index != interface_index)
8431 continue;
8432
8433 /* Check the state. */
8434 if (p1 -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8435 continue;
8436
8437 /* Check the name and flag. */
8438 if ((p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name) &&
8439 (p1 -> nx_mdns_rr_send_flag) &&
8440 (p1 != p))
8441 {
8442
8443 /* Calculate the resource record size for other authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
8444 rr_size = (USHORT)(rr_size + (name_size + 10 + p1 -> nx_mdns_rr_rdata_length));
8445
8446 /* Check the packet size. */
8447 if (rr_size <= total_size)
8448 {
8449
8450 /* Set the authority answer flag. */
8451 p1 -> nx_mdns_rr_word = p1 -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8452
8453 /* Clear the send flag. */
8454 p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8455 }
8456 else
8457 {
8458 resend_flag = NX_TRUE;
8459 break;
8460 }
8461 }
8462 }
8463
8464 /* Check the packet size. */
8465 if (rr_size > total_size)
8466 {
8467 resend_flag = NX_TRUE;
8468 continue;
8469 }
8470 else
8471 total_size = (USHORT)(total_size - rr_size);
8472
8473 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_PROBING);
8474
8475 if (status)
8476 {
8477 resend_flag = NX_TRUE;
8478 }
8479 else
8480 {
8481
8482 /* Set the authority answer flag. */
8483 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8484
8485 /* Update the question count. */
8486 question_count ++;
8487
8488 /* Clear the flag. */
8489 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8490 }
8491 }
8492
8493 /* Add the authority answer resource record. */
8494 for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8495 {
8496
8497 /* Check the interface index. */
8498 if (p -> nx_mdns_rr_interface_index != interface_index)
8499 continue;
8500
8501 /* Check whether set the resource record send flag. */
8502 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING) &&
8503 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_AUTHORIY_ANSWER))
8504 {
8505
8506 /* Add the resource record into packet. */
8507 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_PROBING);
8508 if (status)
8509 resend_flag = NX_TRUE;
8510 else
8511 {
8512
8513 /* Update the retransmit count. */
8514 p -> nx_mdns_rr_retransmit_count --;
8515
8516 /* Update the authority count. */
8517 authority_count ++;
8518
8519 /* Clear the additional flag. */
8520 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_AUTHORIY_ANSWER));
8521 }
8522 }
8523
8524 /* Clear the answer flag. */
8525 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8526 }
8527
8528 if (!question_count &&
8529 !answer_count &&
8530 !authority_count &&
8531 !additional_count)
8532 {
8533
8534 /* Release the packet. */
8535 nx_packet_release(packet_ptr);
8536 return;
8537 }
8538
8539 /* Update the question count in header. */
8540 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8541
8542 /* Update the answer count in header. */
8543 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8544 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8545 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8546
8547 /* Send the mDNS packet. */
8548 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8549
8550 /* Resend the packet. */
8551 if (resend_flag)
8552 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_PROBING_SEND_EVENT, TX_OR);
8553 }
8554
8555
8556 /**************************************************************************/
8557 /* */
8558 /* FUNCTION RELEASE */
8559 /* */
8560 /* _nx_mdns_announcing_send PORTABLE C */
8561 /* 6.1 */
8562 /* AUTHOR */
8563 /* */
8564 /* Yuxin Zhou, Microsoft Corporation */
8565 /* */
8566 /* DESCRIPTION */
8567 /* */
8568 /* This function sends mDNS announcing message. */
8569 /* */
8570 /* INPUT */
8571 /* */
8572 /* mdns_ptr Pointer to mDNS instance */
8573 /* */
8574 /* OUTPUT */
8575 /* */
8576 /* status Completion status */
8577 /* */
8578 /* CALLS */
8579 /* */
8580 /* */
8581 /* CALLED BY */
8582 /* */
8583 /* */
8584 /* RELEASE HISTORY */
8585 /* */
8586 /* DATE NAME DESCRIPTION */
8587 /* */
8588 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8589 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8590 /* resulting in version 6.1 */
8591 /* */
8592 /**************************************************************************/
_nx_mdns_announcing_send(NX_MDNS * mdns_ptr,UINT interface_index)8593 static VOID _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8594 {
8595
8596 UINT status;
8597 NX_PACKET *packet_ptr;
8598 NX_PACKET *new_packet_ptr;
8599 ULONG *head;
8600 NX_MDNS_RR *p;
8601 USHORT question_count = 0;
8602 USHORT answer_count = 0;
8603 USHORT authority_count = 0;
8604 USHORT additional_count = 0;
8605 UINT i;
8606 UCHAR resend_flag = NX_FALSE;
8607
8608
8609 /* Create the mdns packet and add the mDNS header. */
8610 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8611
8612 /* Check for errors. */
8613 if (status != NX_SUCCESS)
8614 {
8615 return;
8616 }
8617
8618 /* Set the head pointer. */
8619 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8620
8621 /* Add the answer resource record. */
8622 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8623 {
8624
8625 /* Check the interface index. */
8626 if (p -> nx_mdns_rr_interface_index != interface_index)
8627 continue;
8628
8629 if(p -> nx_mdns_rr_send_flag == 0)
8630 continue;
8631
8632 /* Check valid state. */
8633 if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) ||
8634 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8635 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID))))
8636 continue;
8637
8638 /* Add the resource record into packet. */
8639 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8640
8641 if (status)
8642 {
8643 resend_flag = NX_TRUE;
8644 }
8645 else
8646 {
8647
8648 /* Update the retransmit count. */
8649 p -> nx_mdns_rr_retransmit_count --;
8650
8651 /* Update the count. */
8652 answer_count++;
8653
8654 /* Clear the flag. */
8655 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8656 }
8657 }
8658
8659 if (!question_count &&
8660 !answer_count &&
8661 !authority_count &&
8662 !additional_count)
8663 {
8664
8665 /* Release the packet. */
8666 nx_packet_release(packet_ptr);
8667 return;
8668 }
8669
8670 /* Update the question count in header. */
8671 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8672
8673 /* Update the answer count in header. */
8674 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8675 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8676 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8677
8678 /* If the interval time is 0, repeat advertise. */
8679 if (!mdns_ptr -> nx_mdns_announcing_retrans_interval)
8680 {
8681 for (i = 1; i < mdns_ptr -> nx_mdns_announcing_count; i ++)
8682 {
8683
8684 /* Allocate new packet. */
8685 status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
8686
8687 /* Check for errors. */
8688 if (status)
8689 {
8690 break;
8691 }
8692
8693 /* Send the mDNS packet. */
8694 _nx_mdns_packet_send(mdns_ptr, new_packet_ptr, interface_index);
8695 }
8696 }
8697
8698 /* Send the mDNS packet. */
8699 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8700
8701 /* Resend the packet. */
8702 if (resend_flag)
8703 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_ANNOUNCING_SEND_EVENT, TX_OR);
8704
8705 return;
8706 }
8707
8708
8709 /**************************************************************************/
8710 /* */
8711 /* FUNCTION RELEASE */
8712 /* */
8713 /* _nx_mdns_response_send PORTABLE C */
8714 /* 6.1 */
8715 /* AUTHOR */
8716 /* */
8717 /* Yuxin Zhou, Microsoft Corporation */
8718 /* */
8719 /* DESCRIPTION */
8720 /* */
8721 /* This function sends mDNS response. */
8722 /* */
8723 /* INPUT */
8724 /* */
8725 /* mdns_ptr Pointer to mDNS instance */
8726 /* */
8727 /* OUTPUT */
8728 /* */
8729 /* none */
8730 /* */
8731 /* CALLS */
8732 /* */
8733 /* */
8734 /* CALLED BY */
8735 /* */
8736 /* */
8737 /* RELEASE HISTORY */
8738 /* */
8739 /* DATE NAME DESCRIPTION */
8740 /* */
8741 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8742 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8743 /* resulting in version 6.1 */
8744 /* */
8745 /**************************************************************************/
_nx_mdns_response_send(NX_MDNS * mdns_ptr,UINT interface_index)8746 static VOID _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index)
8747 {
8748
8749 UINT status;
8750 NX_PACKET *packet_ptr;
8751 ULONG *head;
8752 NX_MDNS_RR *p;
8753 USHORT question_count = 0;
8754 USHORT answer_count = 0;
8755 USHORT authority_count = 0;
8756 USHORT additional_count = 0;
8757 UCHAR resend_flag = NX_FALSE;
8758
8759
8760 /* Create the mdns packet and add the mDNS header. */
8761 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8762
8763 /* Check for errors. */
8764 if (status != NX_SUCCESS)
8765 {
8766 return;
8767 }
8768
8769 /* Set the head pointer. */
8770 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8771
8772 /* Add the answer resource record. */
8773 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8774 {
8775
8776 /* Check the interface index. */
8777 if (p -> nx_mdns_rr_interface_index != interface_index)
8778 continue;
8779
8780 if(p -> nx_mdns_rr_send_flag == 0)
8781 continue;
8782
8783 /* Check valid state. */
8784 if ((p -> nx_mdns_rr_timer_count != 0) ||
8785 !((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8786 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)))
8787 continue;
8788
8789 /* Add the resource record into packet. */
8790 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8791
8792 if (status)
8793 {
8794 resend_flag = NX_TRUE;
8795 }
8796 else
8797 {
8798
8799 /* Set the answer flag to skip the resource record which has been added in answer section when find the additional records. */
8800 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ANSWER;
8801
8802 /* When including a DNS-SD Service Instance Enumeration or Selective Instance Enumeration PTR record in a response packet,
8803 the server/responder SHOULD include the folowing additional records, SRV,TXT, A and AAAA.RFC3763, Section12.1, Page30. */
8804 _nx_mdns_additional_resource_record_find(mdns_ptr, p);
8805
8806 /* Update the count. */
8807 answer_count++;
8808
8809 /* Clear the flag. */
8810 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8811 }
8812 }
8813
8814 /* Add the additional answer resource record. */
8815 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8816 {
8817
8818 /* Check the interface index. */
8819 if (p -> nx_mdns_rr_interface_index != interface_index)
8820 continue;
8821
8822 /* Check whether set the resource record send flag. */
8823 if ((p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ADDITIONAL) &&
8824 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8825 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)))
8826 {
8827
8828 /* Add the resource record into packet. */
8829 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8830 if (status)
8831 {
8832 resend_flag = NX_TRUE;
8833 }
8834 else
8835 {
8836
8837 /* Update the additional count. */
8838 additional_count++;
8839
8840 /* Clear the additional flag. */
8841 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ADDITIONAL));
8842 }
8843 }
8844
8845 /* Clear the answer flag. */
8846 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8847 }
8848
8849 if (!question_count &&
8850 !answer_count &&
8851 !authority_count &&
8852 !additional_count)
8853 {
8854
8855 /* Release the packet. */
8856 nx_packet_release(packet_ptr);
8857 return;
8858 }
8859
8860 /* Update the question count in header. */
8861 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8862
8863 /* Update the answer count in header. */
8864 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8865 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8866 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8867
8868 /* Send the mDNS packet. */
8869 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8870
8871 /* Resend the packet. */
8872 if (resend_flag)
8873 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_RESPONSE_SEND_EVENT, TX_OR);
8874 }
8875 #endif /* NX_MDNS_DISABLE_SERVER */
8876
8877
8878 #ifndef NX_MDNS_DISABLE_CLIENT
8879 /**************************************************************************/
8880 /* */
8881 /* FUNCTION RELEASE */
8882 /* */
8883 /* _nx_mdns_query_send PORTABLE C */
8884 /* 6.1 */
8885 /* AUTHOR */
8886 /* */
8887 /* Yuxin Zhou, Microsoft Corporation */
8888 /* */
8889 /* DESCRIPTION */
8890 /* */
8891 /* This function sends mDNS query message. */
8892 /* */
8893 /* INPUT */
8894 /* */
8895 /* mdns_ptr Pointer to mDNS instance */
8896 /* */
8897 /* OUTPUT */
8898 /* */
8899 /* none */
8900 /* */
8901 /* CALLS */
8902 /* */
8903 /* */
8904 /* CALLED BY */
8905 /* */
8906 /* */
8907 /* RELEASE HISTORY */
8908 /* */
8909 /* DATE NAME DESCRIPTION */
8910 /* */
8911 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8912 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8913 /* resulting in version 6.1 */
8914 /* */
8915 /**************************************************************************/
_nx_mdns_query_send(NX_MDNS * mdns_ptr,UINT interface_index)8916 static VOID _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index)
8917 {
8918
8919 UINT status;
8920 NX_PACKET *packet_ptr;
8921 ULONG *head;
8922 NX_MDNS_RR *p;
8923 USHORT question_count = 0;
8924 USHORT answer_count = 0;
8925 USHORT authority_count = 0;
8926 USHORT additional_count = 0;
8927 UCHAR resend_flag = NX_FALSE;
8928 USHORT tc_bit;
8929 UCHAR more_known_answer = NX_FALSE;
8930 UINT i;
8931
8932
8933 /* Create the mdns packet and add the mDNS header. */
8934 status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8935
8936 /* Check for errors. */
8937 if (status != NX_SUCCESS)
8938 {
8939 return;
8940 }
8941
8942 /* Set the head pointer. */
8943 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8944
8945 /* Add the query resource record. */
8946 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8947 {
8948
8949 /* Check the interface index. */
8950 if (p -> nx_mdns_rr_interface_index != interface_index)
8951 continue;
8952
8953 if(p -> nx_mdns_rr_send_flag == 0)
8954 continue;
8955
8956 /* Check valid state. */
8957 if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY) ||
8958 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING))))
8959 continue;
8960
8961 /* Add the resource record into packet. */
8962 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_QUERY);
8963
8964 if (status)
8965 {
8966 resend_flag = NX_TRUE;
8967 }
8968 else
8969 {
8970
8971 /* Update the retransmit count for UPDATING state. */
8972 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
8973 p -> nx_mdns_rr_retransmit_count --;
8974
8975 /* Update the count. */
8976 question_count++;
8977
8978 /* Find the known answer resource records. */
8979 _nx_mdns_known_answer_find(mdns_ptr, p);
8980
8981 /* Clear the flag. */
8982 p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8983 }
8984 }
8985
8986 /* Add the known answer resource record. */
8987 for (i = 0; i < 2; i++)
8988 {
8989 if (i == 0)
8990 {
8991 #ifndef NX_MDNS_DISABLE_SERVER
8992 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8993 #else
8994 continue;
8995 #endif /* NX_MDNS_DISABLE_SERVER */
8996 }
8997 else
8998 {
8999 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
9000 }
9001
9002 /* Add the peer resource code as known answer for query. */
9003 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
9004 {
9005
9006 /* Check the interface index. */
9007 if (p -> nx_mdns_rr_interface_index != interface_index)
9008 continue;
9009
9010 /* Check whether set the resource record send flag. */
9011 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
9012 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_KNOWN_ANSWER))
9013 {
9014
9015 /* Add the resource record into packet. */
9016 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_QUERY);
9017 if (status)
9018 {
9019 more_known_answer = NX_TRUE;
9020 resend_flag = NX_TRUE;
9021 }
9022 else
9023 {
9024 /* Update the count. */
9025 answer_count ++;
9026
9027 /* Clear the additional flag. */
9028 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_KNOWN_ANSWER));
9029 }
9030 }
9031
9032 /* Clear the answer flag. */
9033 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
9034 }
9035 }
9036
9037 if (!question_count &&
9038 !answer_count &&
9039 !authority_count &&
9040 !additional_count)
9041 {
9042
9043 /* Release the packet. */
9044 nx_packet_release(packet_ptr);
9045 return;
9046 }
9047
9048 /* Set the TC bit. */
9049 if (more_known_answer)
9050 {
9051 tc_bit = NX_MDNS_TC_FLAG;
9052 *(USHORT *)(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) |= NX_CHANGE_USHORT_ENDIAN(tc_bit);
9053 }
9054
9055 /* Update the question count in header. */
9056 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
9057
9058 /* Update the answer count in header. */
9059 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
9060 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
9061 _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
9062
9063 /* Send the mDNS packet. */
9064 _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
9065
9066 /* Resend the packet. */
9067 if (resend_flag)
9068 tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_QUERY_SEND_EVENT, TX_OR);
9069 }
9070 #endif /* NX_MDNS_DISABLE_CLIENT */
9071
9072
9073 /**************************************************************************/
9074 /* */
9075 /* FUNCTION RELEASE */
9076 /* */
9077 /* _nx_mdns_packet_create PORTABLE C */
9078 /* 6.1 */
9079 /* AUTHOR */
9080 /* */
9081 /* Yuxin Zhou, Microsoft Corporation */
9082 /* */
9083 /* DESCRIPTION */
9084 /* */
9085 /* This function creates the mDNS packet and add the mDNS header data. */
9086 /* */
9087 /* INPUT */
9088 /* */
9089 /* mdns_ptr Pointer to mDNS instance */
9090 /* packet_ptr Pointer to mDNS packet */
9091 /* is_query Query flag */
9092 /* */
9093 /* OUTPUT */
9094 /* */
9095 /* status Completion status */
9096 /* */
9097 /* CALLS */
9098 /* */
9099 /* nx_packet_allocate Allocate the mDNS packet */
9100 /* nx_packet_release Release the mDNS packet */
9101 /* _nx_mdns_short_to_network_convert Add the data into the packet */
9102 /* */
9103 /* CALLED BY */
9104 /* */
9105 /* _nx_mdns_announcing_send Send announcing message */
9106 /* _nx_mdns_probing_send Send probing message */
9107 /* _nx_mdns_query_send Send query message */
9108 /* _nx_mdns_response_send Send response message */
9109 /* */
9110 /* RELEASE HISTORY */
9111 /* */
9112 /* DATE NAME DESCRIPTION */
9113 /* */
9114 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9115 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9116 /* resulting in version 6.1 */
9117 /* */
9118 /**************************************************************************/
_nx_mdns_packet_create(NX_MDNS * mdns_ptr,NX_PACKET ** packet_ptr,UCHAR is_query)9119 static UINT _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR is_query)
9120 {
9121
9122 UINT status;
9123 USHORT flags;
9124
9125
9126 /* Allocate the mDNS packet. */
9127 #ifdef NX_MDNS_ENABLE_IPV6
9128 status = nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv6_UDP_PACKET, NX_NO_WAIT);
9129 #else
9130 status = nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
9131 #endif /* NX_MDNS_ENABLE_IPV6 */
9132
9133 /* Check for errors. */
9134 if (status)
9135 {
9136
9137 /* Return error. */
9138 return(status);
9139 }
9140
9141 /* Check if there is enough room to fill with mDNS header. */
9142 if ((UINT)((*packet_ptr) -> nx_packet_data_end - (*packet_ptr) -> nx_packet_append_ptr) < NX_MDNS_QDSECT_OFFSET)
9143 {
9144
9145 /* Release the packet. */
9146 nx_packet_release(*packet_ptr);
9147 return(NX_MDNS_PACKET_ERROR);
9148 }
9149
9150 /* Add the mDNS header. */
9151
9152 /* Set the transaction ID. */
9153 *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_ID_OFFSET) = 0;
9154
9155 /* Set the flags and Command. */
9156 if (is_query == NX_TRUE)
9157 {
9158 flags = NX_MDNS_QUERY_FLAG;
9159 }
9160 else
9161 {
9162 flags = (NX_MDNS_RESPONSE_FLAG | NX_MDNS_AA_FLAG);
9163 }
9164
9165 /* Adjust for endianness. */
9166 NX_CHANGE_USHORT_ENDIAN(flags);
9167
9168 /* Set the flags and Command. */
9169 *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) = flags;
9170
9171 /* Initialize counts to 0. */
9172 *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET) = 0;
9173 *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET) = 0;
9174
9175 /* Set the pointer. */
9176 (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
9177 (*packet_ptr) -> nx_packet_length = NX_MDNS_QDSECT_OFFSET;
9178
9179 return(NX_MDNS_SUCCESS);
9180 }
9181
9182
9183 /**************************************************************************/
9184 /* */
9185 /* FUNCTION RELEASE */
9186 /* */
9187 /* _nx_mdns_packet_send PORTABLE C */
9188 /* 6.1 */
9189 /* AUTHOR */
9190 /* */
9191 /* Yuxin Zhou, Microsoft Corporation */
9192 /* */
9193 /* DESCRIPTION */
9194 /* */
9195 /* This function sends the mDNS packet. */
9196 /* */
9197 /* INPUT */
9198 /* */
9199 /* mdns_ptr Pointer to mDNS instance */
9200 /* packet_ptr Pointer to mDNS packet */
9201 /* */
9202 /* OUTPUT */
9203 /* */
9204 /* status Completion status */
9205 /* */
9206 /* CALLS */
9207 /* */
9208 /* nx_packet_copy Copy the mDNS packet */
9209 /* nx_packet_release Release the mDNS packet */
9210 /* nx_udp_socket_send Send the udp packet */
9211 /* nxd_udp_socket_send Send the udp packet */
9212 /* */
9213 /* CALLED BY */
9214 /* */
9215 /* _nx_mdns_announcing_send Send announcing message */
9216 /* _nx_mdns_probing_send Send probing message */
9217 /* _nx_mdns_query_send Send query message */
9218 /* _nx_mdns_response_send Send response message */
9219 /* */
9220 /* RELEASE HISTORY */
9221 /* */
9222 /* DATE NAME DESCRIPTION */
9223 /* */
9224 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9225 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9226 /* resulting in version 6.1 */
9227 /* */
9228 /**************************************************************************/
_nx_mdns_packet_send(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)9229 static VOID _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
9230 {
9231
9232 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
9233 UINT status;
9234 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
9235 #ifdef NX_MDNS_ENABLE_IPV6
9236 UINT ipv6_packet = NX_FALSE;
9237 NX_PACKET *new_packet_ptr;
9238 UINT address_index = mdns_ptr -> nx_mdns_ipv6_address_index[interface_index];
9239 #endif /* NX_MDNS_ENABLE_IPV6 */
9240
9241
9242 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
9243 NX_PARAMETER_NOT_USED(mdns_ptr);
9244 NX_PARAMETER_NOT_USED(interface_index);
9245 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6 */
9246
9247 #ifdef NX_MDNS_ENABLE_IPV6
9248 if (address_index != 0xFFFFFFFF)
9249 {
9250
9251 /* Allocate new IPv6 packet. */
9252 status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
9253
9254 /* Check for errors. */
9255 if (!status)
9256 {
9257 ipv6_packet = NX_TRUE;
9258 }
9259 }
9260 #endif /* NX_MDNS_ENABLE_IPV6 */
9261
9262 #ifndef NX_DISABLE_IPV4
9263 /* Send the IPv4 mDNS message. */
9264 status = nx_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, packet_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, interface_index);
9265
9266 /* If an error is detected, the packet was not sent and we have to release the packet. */
9267 if (status != NX_SUCCESS)
9268 {
9269
9270 /* Release the packet. */
9271 nx_packet_release(packet_ptr);
9272 }
9273 #else
9274
9275 /* Release the packet. */
9276 nx_packet_release(packet_ptr);
9277 #endif /* NX_DISABLE_IPV4 */
9278
9279 #ifdef NX_MDNS_ENABLE_IPV6
9280
9281 /* Check if send IPv6 packet. */
9282 if (ipv6_packet == NX_TRUE)
9283 {
9284
9285 /* Send the IPv6 mDNS message. */
9286 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);
9287
9288 /* If an error is detected, the packet was not sent and we have to release the packet. */
9289 if (status != NX_SUCCESS)
9290 {
9291
9292 /* Release the packet. */
9293 nx_packet_release(new_packet_ptr);
9294 }
9295 }
9296 #endif /* NX_MDNS_ENABLE_IPV6 */
9297 }
9298
9299
9300 /**************************************************************************/
9301 /* */
9302 /* FUNCTION RELEASE */
9303 /* */
9304 /* _nx_mdns_packet_rr_add PORTABLE C */
9305 /* 6.1 */
9306 /* AUTHOR */
9307 /* */
9308 /* Yuxin Zhou, Microsoft Corporation */
9309 /* */
9310 /* DESCRIPTION */
9311 /* */
9312 /* This function adds the mDNS resource record into the packet. */
9313 /* */
9314 /* INPUT */
9315 /* */
9316 /* mdns_ptr Pointer to mDNS instance */
9317 /* packet_ptr Pointer to mDNS packet */
9318 /* rr Pointer to mDNS record */
9319 /* op RR adding Operation */
9320 /* packet_type Packet type */
9321 /* */
9322 /* OUTPUT */
9323 /* */
9324 /* status Completion status */
9325 /* */
9326 /* CALLS */
9327 /* */
9328 /* _nx_mdns_name_string_encode Encode the name string */
9329 /* _nx_mdns_short_to_network_convert Convert and add the data */
9330 /* _nx_mdns_txt_string_encode Encode the txt string */
9331 /* */
9332 /* CALLED BY */
9333 /* */
9334 /* _nx_mdns_announcing_send Send announcing message */
9335 /* _nx_mdns_probing_send Send probing message */
9336 /* _nx_mdns_query_send Send query message */
9337 /* _nx_mdns_response_send Send response message */
9338 /* */
9339 /* RELEASE HISTORY */
9340 /* */
9341 /* DATE NAME DESCRIPTION */
9342 /* */
9343 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9344 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9345 /* verified memcpy use cases, */
9346 /* resulting in version 6.1 */
9347 /* */
9348 /**************************************************************************/
_nx_mdns_packet_rr_add(NX_PACKET * packet_ptr,NX_MDNS_RR * rr,UINT op,UINT packet_type)9349 static UINT _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type)
9350 {
9351
9352 USHORT size = 0;
9353 USHORT index = 0;
9354 USHORT rr_size = 0;
9355 USHORT rdata_length_index = 0;
9356 UCHAR *data_ptr = packet_ptr -> nx_packet_append_ptr;
9357 UINT rr_name_length;
9358
9359
9360 /* Check string length. */
9361 if (_nx_utility_string_length_check((CHAR *)rr -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9362 {
9363 return (NX_MDNS_DATA_SIZE_ERROR);
9364 }
9365
9366 /* Check whether set the resource record send flag. */
9367 if(op == NX_MDNS_PACKET_ADD_RR_QUESTION)
9368 {
9369
9370 /* The name size is should add the '.' and '\0', Calcuate the resource record size. QNAME, QTYPE, QCLASS. */
9371 rr_size = (USHORT)(rr_name_length + 2 + 4);
9372
9373 if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9374 {
9375 return(NX_MDNS_PACKET_ERROR);
9376 }
9377
9378 /* Encode and add the name. */
9379 size = (USHORT)_nx_mdns_name_string_encode(data_ptr, rr -> nx_mdns_rr_name);
9380
9381 /* Updat the index. */
9382 index = (USHORT)(index + size);
9383
9384 /* Add the type. */
9385 if(packet_type == NX_MDNS_PACKET_PROBING)
9386 {
9387 _nx_mdns_short_to_network_convert(data_ptr + index, NX_MDNS_RR_TYPE_ALL);
9388 }
9389 else
9390 {
9391 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9392 }
9393 index = (USHORT)(index + 2);
9394
9395 /* Add the class. */
9396 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9397 index = (USHORT)(index + 2);
9398 }
9399
9400 /* Check whether set the resource record send flag. */
9401 else
9402 {
9403
9404 /* Calcuate the resource record size. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. */
9405 rr_size = (USHORT)(rr_name_length + 2 + 10 + rr -> nx_mdns_rr_rdata_length);
9406
9407 if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9408 {
9409 return(NX_MDNS_PACKET_ERROR);
9410 }
9411
9412 /* Encode and add the name. */
9413 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_name);
9414
9415 /* Updat the index. */
9416 index = (USHORT)(index + size);
9417
9418 /* Add the type and class. */
9419 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9420 index = (USHORT)(index + 2);
9421
9422 /* Add the class. */
9423 if ((!(rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)) &&
9424 (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE))
9425 {
9426 _nx_mdns_short_to_network_convert(data_ptr + index, ((rr -> nx_mdns_rr_class) | NX_MDNS_RR_CLASS_TOP_BIT));
9427 }
9428 else
9429 {
9430
9431 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9432 }
9433 index = (USHORT)(index + 2);
9434
9435 /* Add the ttl. */
9436 /* Check the resource record owner. */
9437 if (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)
9438 {
9439 /* Add the remaining ttl of peer resource reocrd. */
9440 _nx_mdns_long_to_network_convert(data_ptr + index, (rr -> nx_mdns_rr_remaining_ticks / NX_IP_PERIODIC_RATE));
9441 }
9442 else
9443 {
9444 if (rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE)
9445 {
9446 _nx_mdns_long_to_network_convert(data_ptr + index, 0);
9447 }
9448 else
9449 {
9450 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_ttl);
9451 }
9452 }
9453 index = (USHORT)(index + 4);
9454
9455 /* Compare the RDATA. */
9456 switch (rr -> nx_mdns_rr_type)
9457 {
9458
9459 case NX_MDNS_RR_TYPE_A:
9460 {
9461
9462 /* Add the rdata length. */
9463 _nx_mdns_short_to_network_convert(data_ptr + index, 4);
9464 index = (USHORT)(index + 2);
9465
9466 /* Add the rdata. */
9467 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address);
9468 index = (USHORT)(index + 4);
9469
9470 break;
9471 }
9472 case NX_MDNS_RR_TYPE_AAAA:
9473 {
9474
9475 /* Add the rdata length. */
9476 _nx_mdns_short_to_network_convert(data_ptr + index, 16);
9477 index = (USHORT)(index + 2);
9478
9479 /* Add the rdata. */
9480 _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]);
9481 index = (USHORT)(index + 4);
9482 _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]);
9483 index = (USHORT)(index + 4);
9484 _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]);
9485 index = (USHORT)(index + 4);
9486 _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]);
9487 index = (USHORT)(index + 4);
9488
9489 break;
9490 }
9491 case NX_MDNS_RR_TYPE_PTR:
9492 {
9493
9494 /* Record the rdata length index then skip the rdata length. */
9495 rdata_length_index = index;
9496 index = (USHORT)(index + 2);
9497
9498 /* Encode and add the name. */
9499 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);
9500 index = (USHORT)(index + size);
9501
9502 /* Add the rdata length. */
9503 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9504
9505 break;
9506 }
9507 case NX_MDNS_RR_TYPE_SRV:
9508 {
9509
9510 /* Record the rdata length index then skip the rdata length. */
9511 rdata_length_index = index;
9512 index = (USHORT)(index + 2);
9513
9514 /* Add the prority. */
9515 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority);
9516 index = (USHORT)(index + 2);
9517
9518 /* Add the weights. */
9519 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights);
9520 index = (USHORT)(index + 2);
9521
9522 /* Add the port. */
9523 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port);
9524 index = (USHORT)(index + 2);
9525
9526 /* Encode and add the name. */
9527 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);
9528 index = (USHORT)(index + size);
9529
9530 /* Add the rdata length. */
9531 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 6));
9532
9533 break;
9534 }
9535 case NX_MDNS_RR_TYPE_TXT:
9536 {
9537
9538 /* Record the rdata length index then skip the rdata length. */
9539 rdata_length_index = index;
9540 index = (USHORT)(index + 2);
9541
9542 if (rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
9543 {
9544
9545 /* Encode and add the text. */
9546 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);
9547 }
9548 else
9549 {
9550
9551 /* Encode the null. */
9552 *(data_ptr + index) = 0;
9553 size = 1;
9554 }
9555 index = (USHORT)(index + size);
9556
9557 /* Add the rdata length. */
9558 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9559
9560 break;
9561 }
9562
9563 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
9564 case NX_MDNS_RR_TYPE_CNAME:
9565 {
9566
9567 /* Record the rdata length index then skip the rdata length. */
9568 rdata_length_index = index;
9569 index = (USHORT)(index + 2);
9570
9571 /* Encode and add the name. */
9572 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);
9573 index = (USHORT)(index + size);
9574
9575 /* Add the rdata length. */
9576 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9577
9578 break;
9579 }
9580 case NX_MDNS_RR_TYPE_NS:
9581 {
9582
9583 /* Record the rdata length index then skip the rdata length. */
9584 rdata_length_index = index;
9585 index = (USHORT)(index + 2);
9586
9587 /* Encode and add the name. */
9588 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);
9589 index = (USHORT)(index + size);
9590
9591 /* Add the rdata length. */
9592 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9593
9594 break;
9595 }
9596 case NX_MDNS_RR_TYPE_MX:
9597 {
9598
9599 /* Record the rdata length index then skip the rdata length. */
9600 rdata_length_index = index;
9601 index = (USHORT)(index + 2);
9602
9603 /* Add the preference. */
9604 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference);
9605 index = (USHORT)(index + 2);
9606
9607 /* Encode and add the name. */
9608 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);
9609 index = (USHORT)(index + size);
9610
9611 /* Add the rdata length. */
9612 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2));
9613
9614 break;
9615 }
9616 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
9617
9618 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
9619 case NX_MDNS_RR_TYPE_NSEC:
9620 {
9621
9622 /* Record the rdata length index then skip the rdata length. */
9623 rdata_length_index = index;
9624 index = (USHORT)(index + 2);
9625
9626 /* Encode and add the next domain name. */
9627 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);
9628 index = (USHORT)(index + size);
9629
9630 /* Add the window block. */
9631 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block;
9632 index++;
9633
9634 /* Add the bitmap length. */
9635 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length;
9636 index++;
9637
9638 /* Add the type bit maps. */
9639 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. */
9640 index = (USHORT)(index + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length);
9641
9642 /* Add the rdata length. */
9643 _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));
9644
9645 break;
9646 }
9647 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
9648 }
9649 }
9650
9651 /* Update the append pointer and packet length. */
9652 packet_ptr -> nx_packet_append_ptr += index;
9653 packet_ptr -> nx_packet_length += index;
9654
9655 return(NX_MDNS_SUCCESS);
9656 }
9657
9658
9659 /**************************************************************************/
9660 /* */
9661 /* FUNCTION RELEASE */
9662 /* */
9663 /* _nx_mdns_packet_rr_set PORTABLE C */
9664 /* 6.1.11 */
9665 /* AUTHOR */
9666 /* */
9667 /* Yuxin Zhou, Microsoft Corporation */
9668 /* */
9669 /* DESCRIPTION */
9670 /* */
9671 /* This function sets the resource record info from packet. */
9672 /* */
9673 /* INPUT */
9674 /* */
9675 /* mdns_ptr Pointer to mDNS instance. */
9676 /* packet_ptr Pointer to the packet. */
9677 /* data_ptr Pointer to the data. */
9678 /* rr_ptr Pointer to the record */
9679 /* op Operation: */
9680 /* set question or set answer. */
9681 /* */
9682 /* OUTPUT */
9683 /* */
9684 /* status Completion status */
9685 /* */
9686 /* CALLS */
9687 /* */
9688 /* _nx_mdns_name_string_decode Decode the name string */
9689 /* _nx_mdns_cache_add_string Add the name string */
9690 /* _nx_mdns_cache_add_resource_record Add the resource record */
9691 /* */
9692 /* CALLED BY */
9693 /* */
9694 /* _nx_mdns_packet_process Process mDNS packet */
9695 /* */
9696 /* RELEASE HISTORY */
9697 /* */
9698 /* DATE NAME DESCRIPTION */
9699 /* */
9700 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9701 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9702 /* resulting in version 6.1 */
9703 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
9704 /* buffer length verification, */
9705 /* resulting in version 6.1.3 */
9706 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
9707 /* packet length verification, */
9708 /* resulting in version 6.1.4 */
9709 /* 04-25-2022 Yuxin Zhou Modified comment(s), improved */
9710 /* fixed the issue of timer, */
9711 /* resulting in version 6.1.11 */
9712 /* */
9713 /**************************************************************************/
_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 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)
9715 {
9716
9717 UCHAR *cache_ptr;
9718 UINT cache_size;
9719 UINT cache_type;
9720 USHORT record_class;
9721 UINT status;
9722 UINT temp_string_length;
9723
9724
9725 /* Initialize. */
9726 memset(rr_ptr, 0, sizeof(NX_MDNS_RR));
9727
9728 /* Get cache type and size. */
9729 if ((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) ||
9730 (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER))
9731 {
9732 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
9733 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
9734 cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
9735 }
9736 else
9737 {
9738 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
9739 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
9740 cache_type = NX_MDNS_CACHE_TYPE_PEER;
9741 }
9742
9743 /* Check cache pointer and cache size. */
9744 if ((cache_ptr == NX_NULL) || (cache_size == 0))
9745 {
9746 return(NX_MDNS_ERROR);
9747 }
9748
9749 /* Set the interface. */
9750 rr_ptr -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
9751
9752 /* Process the name string. */
9753 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9754 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9755 packet_ptr -> nx_packet_length,
9756 temp_string_buffer, NX_MDNS_NAME_MAX))
9757 {
9758
9759 /* Check string length. */
9760 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9761 {
9762 return(NX_MDNS_DATA_SIZE_ERROR);
9763 }
9764
9765 /* Add the string . */
9766 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
9767 (VOID **)(&rr_ptr -> nx_mdns_rr_name), NX_TRUE, NX_TRUE) != NX_MDNS_SUCCESS)
9768 {
9769 return(NX_MDNS_ERROR);
9770 }
9771 }
9772 else
9773 {
9774 return(NX_MDNS_ERROR);
9775 }
9776
9777 /* Plus 4 for 2 bytes type and 2 bytes class. */
9778 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9779 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9780 {
9781 return(NX_MDNS_ERROR);
9782 }
9783
9784 /* Set the resource record type. */
9785 rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9786
9787 /* Get the resource record class.*/
9788 record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9789
9790 /* Remote RR, set the RR owner flag.*/
9791 if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
9792 rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9793
9794 /* Unique RR, Set the RR set flag. */
9795 if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9796 {
9797 rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9798 }
9799
9800 /* Check the operation and update the record class. */
9801 if((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) || (op == NX_MDNS_RR_OP_PEER_SET_QUESTION))
9802 {
9803 rr_ptr -> nx_mdns_rr_class = record_class;
9804 return(NX_MDNS_SUCCESS);
9805 }
9806 else
9807 {
9808 rr_ptr -> nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9809 }
9810
9811 /* Set the rdata information for answer record. */
9812 status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, rr_ptr, op);
9813
9814 /* Return success. */
9815 return (status);
9816 }
9817
9818
9819 #ifndef NX_MDNS_DISABLE_CLIENT
9820 /**************************************************************************/
9821 /* */
9822 /* FUNCTION RELEASE */
9823 /* */
9824 /* _nx_mdns_packet_rr_process PORTABLE C */
9825 /* 6.1.11 */
9826 /* AUTHOR */
9827 /* */
9828 /* Yuxin Zhou, Microsoft Corporation */
9829 /* */
9830 /* DESCRIPTION */
9831 /* */
9832 /* This function processes the resource record of packet, and add the */
9833 /* record into peer cache. */
9834 /* */
9835 /* INPUT */
9836 /* */
9837 /* mdns_ptr Pointer to mDNS instance. */
9838 /* packet_ptr Pointer to the packet. */
9839 /* data_ptr Pointer to the data. */
9840 /* insert_ptr Pointer to the insert record */
9841 /* op Operation: add answer, set */
9842 /* question or set answer. */
9843 /* cache_ptr The record buffer. */
9844 /* */
9845 /* OUTPUT */
9846 /* */
9847 /* status Completion status */
9848 /* */
9849 /* CALLS */
9850 /* */
9851 /* _nx_mdns_name_string_decode Decode the name string */
9852 /* _nx_mdns_cache_add_string Add the name string */
9853 /* _nx_mdns_cache_add_resource_record Add the resource record */
9854 /* */
9855 /* CALLED BY */
9856 /* */
9857 /* _nx_mdns_packet_process Process mDNS packet */
9858 /* */
9859 /* RELEASE HISTORY */
9860 /* */
9861 /* DATE NAME DESCRIPTION */
9862 /* */
9863 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9864 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9865 /* verified memcpy use cases, */
9866 /* resulting in version 6.1 */
9867 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
9868 /* buffer length verification, */
9869 /* resulting in version 6.1.3 */
9870 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
9871 /* packet length verification, */
9872 /* resulting in version 6.1.4 */
9873 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
9874 /* corrected the random value, */
9875 /* fixed the issue of timer, */
9876 /* resulting in version 6.1.11 */
9877 /* */
9878 /**************************************************************************/
_nx_mdns_packet_rr_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,UINT interface_index)9879 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index)
9880 {
9881
9882 UINT status;
9883 USHORT record_class;
9884 UCHAR is_present;
9885 NX_MDNS_RR rr_ptr;
9886 NX_MDNS_RR *insert_ptr;
9887 NX_MDNS_RR *p;
9888 ULONG *head;
9889 UCHAR *service_name,*service_type,*service_domain;
9890 UINT temp_string_length;
9891 UINT rr_name_length;
9892
9893
9894 /* Check the peer cache. */
9895 if ((mdns_ptr -> nx_mdns_peer_service_cache == NX_NULL) ||
9896 (mdns_ptr -> nx_mdns_peer_service_cache_size == 0))
9897 {
9898 return(NX_MDNS_ERROR);
9899 }
9900
9901 /* Initialize. */
9902 memset(&rr_ptr, 0, sizeof(NX_MDNS_RR));
9903
9904 /* Process the name string. */
9905 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9906 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9907 packet_ptr -> nx_packet_length,
9908 temp_string_buffer, NX_MDNS_NAME_MAX))
9909 {
9910
9911 /* Check string length. */
9912 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9913 {
9914 return(NX_MDNS_DATA_SIZE_ERROR);
9915 }
9916
9917 /* Add the string . */
9918 if(_nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_string_buffer, temp_string_length,
9919 (VOID **)(&rr_ptr.nx_mdns_rr_name), NX_FALSE, NX_TRUE))
9920 {
9921 return(NX_MDNS_ERROR);
9922 }
9923 }
9924 else
9925 {
9926 return(NX_MDNS_ERROR);
9927 }
9928
9929 /* Plus 4 for 2 bytes type and 2 bytes class. */
9930 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9931 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9932 {
9933 return(NX_MDNS_ERROR);
9934 }
9935
9936 /* Set the resource record type. */
9937 rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9938
9939 /* Get the resource record class.*/
9940 record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9941
9942 /* Set the resource record class. */
9943 rr_ptr.nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9944
9945 /* Remote RR, set the RR owner flag.*/
9946 rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9947
9948 /* Unique RR, Set the RR set flag. */
9949 if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9950 {
9951 rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9952 }
9953
9954 /* Set the interface index. */
9955 rr_ptr.nx_mdns_rr_interface_index = (UCHAR)interface_index;
9956
9957 /* Set the rdata information for answer record. */
9958 status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, &rr_ptr, NX_MDNS_RR_OP_PEER_ADD_ANSWER);
9959
9960 /* Check status. */
9961 if(status)
9962 {
9963
9964 /* Delete the name strings. */
9965 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, rr_ptr.nx_mdns_rr_name, 0);
9966 return (NX_MDNS_ERROR);
9967 }
9968
9969 /* Check if need to ignore this source reocrd. */
9970 if ((mdns_ptr -> nx_mdns_service_ignore_mask) &&
9971 ((rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
9972 (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
9973 (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)))
9974 {
9975
9976 /* Get the service. */
9977 if (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
9978 {
9979
9980 /* Check string length. */
9981 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))
9982 {
9983 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
9984 return(NX_MDNS_DATA_SIZE_ERROR);
9985 }
9986 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. */
9987 }
9988 else
9989 {
9990
9991 /* Check string length. */
9992 if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9993 {
9994 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
9995 return(NX_MDNS_DATA_SIZE_ERROR);
9996 }
9997 memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9998 }
9999
10000 /* Resolve the service type. */
10001 if (_nx_mdns_service_name_resolve(temp_string_buffer, &service_name, &service_type, &service_domain))
10002 {
10003 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10004 return (status);
10005 }
10006
10007 /* Check if this service type should be ignored. */
10008 if (_nx_mdns_service_mask_match(mdns_ptr, service_type, mdns_ptr -> nx_mdns_service_ignore_mask) == NX_MDNS_SUCCESS)
10009 {
10010 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10011 return (NX_MDNS_ERROR);
10012 }
10013 }
10014
10015 /* Add the resource record into remote buffer. */
10016 if (_nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr, &insert_ptr, &is_present))
10017 {
10018
10019 /* Delete the name strings. */
10020 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10021 return (NX_MDNS_ERROR);
10022 }
10023
10024 /* Check the ttl. */
10025 if (insert_ptr -> nx_mdns_rr_ttl)
10026 {
10027
10028 /* Step1. Process answer record. */
10029 /* Update the state. */
10030 insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
10031
10032 /* 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. */
10033 insert_ptr -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
10034
10035 /* Record the remaining ticks of resource record. */
10036 if (insert_ptr -> nx_mdns_rr_ttl >= NX_MDNS_RR_MAX_TTL)
10037 {
10038 /* If the ttl of resource resource record is outside the range, set as 0xFFFFFFFF. */
10039 insert_ptr -> nx_mdns_rr_remaining_ticks = 0xFFFFFFFF;
10040 }
10041 else
10042 {
10043 /* Convert units(seconds to ticks). */
10044 insert_ptr -> nx_mdns_rr_remaining_ticks = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE;
10045 }
10046
10047 /* Step2. Process query record. */
10048 /* Set the pointer. */
10049 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
10050 head = (ULONG*)(*head);
10051
10052 /* Check the remote resource record state. */
10053 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10054 {
10055
10056 /* Check the state. */
10057 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
10058 continue;
10059
10060 /* Check the interface index. */
10061 if (p -> nx_mdns_rr_interface_index != insert_ptr -> nx_mdns_rr_interface_index)
10062 continue;
10063
10064 /* Check the name. */
10065 if (p -> nx_mdns_rr_name != insert_ptr -> nx_mdns_rr_name)
10066 continue;
10067
10068 /* Check the type. */
10069 if ((p -> nx_mdns_rr_type != insert_ptr -> nx_mdns_rr_type) &&
10070 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL))
10071 continue;
10072
10073 /* Check the class. */
10074 if (p -> nx_mdns_rr_class != insert_ptr -> nx_mdns_rr_class)
10075 continue;
10076
10077 /* Check the query type. */
10078 if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_CONTINUOUS_QUERY))
10079 {
10080
10081 /* Determine if we need to wake a thread suspended. */
10082 if (mdns_ptr -> nx_mdns_rr_receive_suspension_list)
10083 {
10084
10085 /* Resume suspended thread. */
10086 _nx_mdns_query_thread_resume(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), mdns_ptr, insert_ptr);
10087 }
10088
10089 /* Get the answer, we need not send the question again. Delete the resource record. */
10090 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
10091
10092 }
10093 else
10094 {
10095
10096 /* There is no need for the querier to continue issuing a stream of queries when a mDNS response
10097 is received containing a unique answer. mDNS querier should send the next query at 80%-82% of the
10098 record's TTL. RFC6762, Section5.2,Page11. */
10099 if ((insert_ptr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) && (insert_ptr -> nx_mdns_rr_ttl))
10100 {
10101
10102 /* Set the timer count. */
10103 p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (((ULONG)NX_RAND()) % 3)) / 100;
10104
10105 /* Set the mDNS timer. */
10106 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10107 }
10108
10109 /* Set the updating flag to update the resource record at 80% of the record's TTL. */
10110 insert_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UPDATING;
10111 }
10112 }
10113 }
10114 else
10115 {
10116
10117 /* Update the state to delete this record from peer cache. . */
10118 insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_DELETE;
10119
10120 /* Delete the resource record one second later. */
10121 insert_ptr -> nx_mdns_rr_timer_count = NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT;
10122 }
10123
10124 /* Set the mDNS timer for insert RR. */
10125 _nx_mdns_timer_set(mdns_ptr, insert_ptr, insert_ptr -> nx_mdns_rr_timer_count);
10126
10127 /* Service name registered success, invoke the notify function. */
10128 if (mdns_ptr -> nx_mdns_service_change_notify)
10129 {
10130
10131 /* Process the service notify function. */
10132 _nx_mdns_service_change_notify_process(mdns_ptr, insert_ptr, is_present);
10133 }
10134
10135 /* Return success. */
10136 return (NX_MDNS_SUCCESS);
10137 }
10138 #endif /* NX_MDNS_DISABLE_CLIENT */
10139
10140
10141 /**************************************************************************/
10142 /* */
10143 /* FUNCTION RELEASE */
10144 /* */
10145 /* _nx_mdns_packet_rr_data_set PORTABLE C */
10146 /* 6.1.4 */
10147 /* AUTHOR */
10148 /* */
10149 /* Yuxin Zhou, Microsoft Corporation */
10150 /* */
10151 /* DESCRIPTION */
10152 /* */
10153 /* This function processes the packet, and sets the data of */
10154 /* resource record. */
10155 /* */
10156 /* INPUT */
10157 /* */
10158 /* mdns_ptr Pointer to mDNS instance. */
10159 /* packet_ptr Pointer to the packet. */
10160 /* data_ptr Pointer to the data. */
10161 /* rr_ptr Pointer to the record */
10162 /* op Operation: */
10163 /* set answer in local cache. */
10164 /* or add answer in peer cache.*/
10165 /* cache_ptr The record buffer. */
10166 /* */
10167 /* OUTPUT */
10168 /* */
10169 /* status Completion status */
10170 /* */
10171 /* CALLS */
10172 /* */
10173 /* _nx_mdns_name_string_decode Decode the name string */
10174 /* _nx_mdns_cache_add_string Add the name string */
10175 /* _nx_mdns_cache_add_resource_record Add the resource record */
10176 /* */
10177 /* CALLED BY */
10178 /* */
10179 /* _nx_mdns_packet_process Process mDNS packet */
10180 /* */
10181 /* RELEASE HISTORY */
10182 /* */
10183 /* DATE NAME DESCRIPTION */
10184 /* */
10185 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10186 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10187 /* resulting in version 6.1 */
10188 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
10189 /* buffer length verification, */
10190 /* resulting in version 6.1.3 */
10191 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
10192 /* packet length verification, */
10193 /* resulting in version 6.1.4 */
10194 /* */
10195 /**************************************************************************/
_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 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)
10197 {
10198
10199 UCHAR *string_search = NX_NULL;
10200 UINT cache_type;
10201 UCHAR find_string;
10202 UCHAR continue_process = NX_FALSE;
10203 UINT status = NX_MDNS_UNSUPPORTED_TYPE;
10204 UINT temp_string_length;
10205
10206
10207 /* Get cache type and size. */
10208 if (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER)
10209 {
10210 cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
10211 find_string = NX_TRUE;
10212 }
10213 else
10214 {
10215 cache_type = NX_MDNS_CACHE_TYPE_PEER;
10216 find_string = NX_FALSE;
10217 }
10218
10219 /* Plus 10 for 2 bytes type, 2 bytes class, 4 bytes ttl and 2 bytes rdata length. */
10220 temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
10221 if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 10) > packet_ptr -> nx_packet_append_ptr))
10222 {
10223 return(NX_MDNS_ERROR);
10224 }
10225
10226 /* Set the resource record time to live.*/
10227 rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + temp_string_length + 4);
10228
10229 /* Set the resource record rdata length. */
10230 rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 8);;
10231
10232 /* Update the pointer to point at the resource data. */
10233 data_ptr = data_ptr + temp_string_length + 10;
10234
10235 /* Check the type. */
10236 switch (rr_ptr -> nx_mdns_rr_type)
10237 {
10238 case NX_MDNS_RR_TYPE_A:
10239 {
10240
10241 /* 4 bytes IP address. */
10242 if (data_ptr + 4 > packet_ptr -> nx_packet_append_ptr)
10243 {
10244 return(NX_MDNS_ERROR);
10245 }
10246
10247 /* Get the rdata. */
10248 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = NX_MDNS_GET_ULONG_DATA(data_ptr);
10249 rr_ptr -> nx_mdns_rr_rdata_length = 4;
10250
10251 /* Update the status. */
10252 status = NX_MDNS_SUCCESS;
10253 break;
10254 }
10255 case NX_MDNS_RR_TYPE_AAAA:
10256 {
10257
10258 /* 16 bytes IPv6 address. */
10259 if (data_ptr + 16 > packet_ptr -> nx_packet_append_ptr)
10260 {
10261 return(NX_MDNS_ERROR);
10262 }
10263
10264 /* Get the rdata. */
10265 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = NX_MDNS_GET_ULONG_DATA(data_ptr);
10266 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);
10267 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);
10268 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);
10269 rr_ptr -> nx_mdns_rr_rdata_length = 16;
10270
10271 /* Update the status. */
10272 status = NX_MDNS_SUCCESS;
10273 break;
10274 }
10275 case NX_MDNS_RR_TYPE_TXT:
10276 {
10277
10278 /* Process the txt string. An empty TXT record contaning zero strings is not allowed. RFC6763, Page12. */
10279 if (rr_ptr -> nx_mdns_rr_rdata_length == 1)
10280 {
10281
10282 /* Update the status. */
10283 status = NX_MDNS_SUCCESS;
10284 }
10285 else if (rr_ptr -> nx_mdns_rr_rdata_length > 1)
10286 {
10287
10288 if (data_ptr + rr_ptr -> nx_mdns_rr_rdata_length > packet_ptr -> nx_packet_append_ptr)
10289 {
10290 return(NX_MDNS_ERROR);
10291 }
10292
10293 /* Add the txt string. */
10294 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)
10295 {
10296
10297 /* Check string length. */
10298 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10299 {
10300 return(NX_MDNS_DATA_SIZE_ERROR);
10301 }
10302
10303 /* Find the same string . */
10304 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10305 (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10306 {
10307
10308 /* Update the name pointer. */
10309 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = string_search;
10310
10311 /* Calculate the text string.inlcude the one byte label. */
10312 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(temp_string_length + 1);
10313
10314 /* Update the status. */
10315 status = NX_MDNS_SUCCESS;
10316 }
10317 }
10318 }
10319
10320 break;
10321 }
10322 case NX_MDNS_RR_TYPE_SRV:
10323 {
10324
10325 /* Plus 6 bytes for 2 bytes priority, 2 bytes weights and 2 bytes port. */
10326 if (data_ptr + 6 > packet_ptr -> nx_packet_append_ptr)
10327 {
10328 return(NX_MDNS_ERROR);
10329 }
10330
10331 /* Get the priority. */
10332 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = NX_MDNS_GET_USHORT_DATA(data_ptr);
10333 data_ptr += 2;
10334
10335 /* Get the weights. */
10336 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = NX_MDNS_GET_USHORT_DATA(data_ptr);
10337 data_ptr += 2;
10338
10339 /* Get the port. */
10340 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = NX_MDNS_GET_USHORT_DATA(data_ptr);
10341 data_ptr += 2;
10342
10343 /* Update the rdata length. */
10344 rr_ptr -> nx_mdns_rr_rdata_length = 6;
10345
10346 /* Continue to process target name. */
10347 continue_process = NX_TRUE;
10348 break;
10349 }
10350 case NX_MDNS_RR_TYPE_PTR:
10351 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10352 case NX_MDNS_RR_TYPE_CNAME:
10353 case NX_MDNS_RR_TYPE_NS:
10354 #endif
10355 {
10356
10357 /* Update the rdata length. */
10358 rr_ptr -> nx_mdns_rr_rdata_length = 0;
10359
10360 /* Continue to process the domain name. */
10361 continue_process = NX_TRUE;
10362 break;
10363 }
10364 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10365 case NX_MDNS_RR_TYPE_MX:
10366 {
10367
10368 /* Plus 2 bytes for preference. */
10369 if (data_ptr + 2 > packet_ptr -> nx_packet_append_ptr)
10370 {
10371 return(NX_MDNS_ERROR);
10372 }
10373
10374 /* Set the preference. */
10375 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference = NX_MDNS_GET_USHORT_DATA(data_ptr);
10376 data_ptr += 2;
10377
10378 /* Update the rdata length. */
10379 rr_ptr -> nx_mdns_rr_rdata_length = 2;
10380
10381 /* Continue to process the domain name. */
10382 continue_process = NX_TRUE;
10383 break;
10384 }
10385 #endif
10386 }
10387
10388 /* Check if need to continue process rdata. */
10389 if(continue_process == NX_TRUE)
10390 {
10391
10392 /* Process the target/domain name string. */
10393 if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
10394 (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
10395 packet_ptr -> nx_packet_length,
10396 temp_string_buffer, NX_MDNS_NAME_MAX))
10397 {
10398
10399 /* Check string length. */
10400 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10401 {
10402 return(NX_MDNS_DATA_SIZE_ERROR);
10403 }
10404
10405 /* Add the string. */
10406 if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10407 (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10408 {
10409
10410 /* Update the name pointer for SRV, PTR, etc. */
10411 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target = string_search;
10412
10413 /* Calculate the text string. Inlcude the one byte label '.' and null '\0'. */
10414 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(rr_ptr -> nx_mdns_rr_rdata_length + (temp_string_length + 2));
10415
10416 /* Update the status. */
10417 status = NX_MDNS_SUCCESS;
10418 }
10419 }
10420 }
10421
10422 /* Return success. */
10423 return (status);
10424 }
10425
10426
10427 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
10428 /**************************************************************************/
10429 /* */
10430 /* FUNCTION RELEASE */
10431 /* */
10432 /* _nx_mdns_packet_address_check PORTABLE C */
10433 /* 6.1.4 */
10434 /* AUTHOR */
10435 /* */
10436 /* Yuxin Zhou, Microsoft Corporation */
10437 /* */
10438 /* DESCRIPTION */
10439 /* */
10440 /* This function checks the IP address and port of received packet. */
10441 /* */
10442 /* INPUT */
10443 /* */
10444 /* packet_ptr Pointer to mDNS packet */
10445 /* */
10446 /* OUTPUT */
10447 /* */
10448 /* status Completion status */
10449 /* */
10450 /* CALLS */
10451 /* */
10452 /* none */
10453 /* */
10454 /* CALLED BY */
10455 /* */
10456 /* _nx_mdns_packet_process Process mDNS packet */
10457 /* */
10458 /* RELEASE HISTORY */
10459 /* */
10460 /* DATE NAME DESCRIPTION */
10461 /* */
10462 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10463 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10464 /* resulting in version 6.1 */
10465 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
10466 /* packet length verification, */
10467 /* resulting in version 6.1.4 */
10468 /* */
10469 /**************************************************************************/
_nx_mdns_packet_address_check(NX_PACKET * packet_ptr)10470 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr)
10471 {
10472
10473 USHORT mdns_flags;
10474 UINT src_port;
10475 ULONG *udp_header;
10476
10477 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
10478 NXD_ADDRESS src_address;
10479 NXD_ADDRESS des_address;
10480 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
10481
10482 #ifndef NX_DISABLE_IPV4
10483 NX_IPV4_HEADER *ipv4_header;
10484 #endif /* NX_DISABLE_IPV4 */
10485
10486 #ifdef NX_MDNS_ENABLE_IPV6
10487 NX_IPV6_HEADER *ipv6_header;
10488 #endif /* NX_MDNS_ENABLE_IPV6 */
10489
10490
10491 /* 2 bytes ID and 2 bytes flags. */
10492 if (packet_ptr -> nx_packet_length < 4)
10493 {
10494 return(NX_MDNS_ERROR);
10495 }
10496
10497 /* Extract the message type which should be the first byte. */
10498 mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
10499
10500 #ifndef NX_DISABLE_IPV4
10501 /* Get the ip address. */
10502 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10503 {
10504
10505 /* Set the IPv4 header. */
10506 ipv4_header = (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
10507
10508 /* Set the source address. */
10509 src_address.nxd_ip_version = NX_IP_VERSION_V4;
10510 src_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_source_ip;
10511
10512 /* Set the destination address. */
10513 des_address.nxd_ip_version = NX_IP_VERSION_V4;
10514 des_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_destination_ip;
10515 }
10516 else
10517 #endif /* NX_DISABLE_IPV4 */
10518
10519 #ifdef NX_MDNS_ENABLE_IPV6
10520 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10521 {
10522
10523 /* Set the IPv6 header. */
10524 ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
10525
10526 /* Set the source address. */
10527 src_address.nxd_ip_version = NX_IP_VERSION_V6;
10528 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_address.nxd_ip_address.v6);
10529
10530 /* Set the destination address. */
10531 des_address.nxd_ip_version = NX_IP_VERSION_V6;
10532 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, des_address.nxd_ip_address.v6);
10533 }
10534 else
10535 #endif /* NX_MDNS_ENABLE_IPV6 */
10536 {
10537
10538 /* Invalid IP version . */
10539 return(NX_MDNS_ERROR);
10540 }
10541
10542 /* Pickup the pointer to the head of the UDP packet. */
10543 udp_header = (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 8);
10544
10545 /* Get the source port and destination port. */
10546 src_port = (UINT) ((*udp_header) >> NX_SHIFT_BY_16);
10547
10548 /* Check the source UDP port. RFC6762, Section6, Page15. */
10549 if (src_port != NX_MDNS_UDP_PORT)
10550 {
10551 return(NX_MDNS_UDP_PORT_ERROR);
10552 }
10553
10554 /* Check the QR bit. */
10555 if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
10556 {
10557
10558 /* Check the response code. */
10559 if (mdns_flags & NX_MDNS_ERROR_MASK)
10560 {
10561
10562 /* Release the source packet. */
10563 return(NX_MDNS_AUTH_ERROR);
10564 }
10565
10566 /* In response messages for Multicast domains, the AA bit Must be set to one, RFC6762, Page48. */
10567 if ((mdns_flags & NX_MDNS_AA_FLAG) != NX_MDNS_AA_FLAG)
10568 {
10569 return (NX_MDNS_ERROR);
10570 }
10571
10572 #ifndef NX_DISABLE_IPV4
10573 /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10574 if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10575 {
10576
10577 /* Local link check, Multicast Address or (I & M) == (P & M). */
10578 if ((des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS) &&
10579 (packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address & packet_ptr ->nx_packet_ip_interface -> nx_interface_ip_network_mask) !=
10580 (src_address.nxd_ip_address.v4 & packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_network_mask))
10581 {
10582 return (NX_MDNS_NOT_LOCAL_LINK);
10583 }
10584 }
10585 else
10586 #endif /* NX_DISABLE_IPV4 */
10587
10588 #ifdef NX_MDNS_ENABLE_IPV6
10589 if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10590 {
10591
10592 /* Destination address is not FF02::FB address or source address not on link, RFC6762, Section 11, Page39. */
10593 /* Not check the source address. */
10594 if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10595 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10596 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10597 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10598 {
10599 return (NX_MDNS_DEST_ADDRESS_ERROR);
10600 }
10601 }
10602 else
10603 #endif /* NX_MDNS_ENABLE_IPV6 */
10604 {
10605
10606 /* Invalid IP version. */
10607 return(NX_MDNS_ERROR);
10608 }
10609 }
10610 else
10611 {
10612
10613 #ifndef NX_DISABLE_IPV4
10614 /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10615 if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10616 {
10617 if (des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS)
10618 {
10619 return (NX_MDNS_DEST_ADDRESS_ERROR);
10620 }
10621 }
10622 else
10623 #endif /* NX_DISABLE_IPV4 */
10624
10625 #ifdef NX_MDNS_ENABLE_IPV6
10626 if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10627 {
10628 if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10629 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10630 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10631 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10632 {
10633 return (NX_MDNS_DEST_ADDRESS_ERROR);
10634 }
10635 }
10636 else
10637 #endif /* NX_MDNS_ENABLE_IPV6 */
10638 {
10639
10640 /* Invalid IP version . */
10641 return(NX_MDNS_ERROR);
10642 }
10643 }
10644
10645 return(NX_MDNS_SUCCESS);
10646 }
10647 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK */
10648
10649
10650 #ifndef NX_MDNS_DISABLE_SERVER
10651 /**************************************************************************/
10652 /* */
10653 /* FUNCTION RELEASE */
10654 /* */
10655 /* _nx_mdns_address_change_process PORTABLE C */
10656 /* 6.1 */
10657 /* AUTHOR */
10658 /* */
10659 /* Yuxin Zhou, Microsoft Corporation */
10660 /* */
10661 /* DESCRIPTION */
10662 /* */
10663 /* This function process the address change event. */
10664 /* */
10665 /* INPUT */
10666 /* */
10667 /* mdns_ptr Pointer to mDNS instance */
10668 /* */
10669 /* OUTPUT */
10670 /* */
10671 /* status Completion status */
10672 /* */
10673 /* CALLS */
10674 /* */
10675 /* nx_packet_copy Copy the mDNS packet */
10676 /* nx_packet_release Release the mDNS packet */
10677 /* nx_udp_socket_send Send the udp packet */
10678 /* nxd_udp_socket_send Send the udp packet */
10679 /* */
10680 /* CALLED BY */
10681 /* */
10682 /* _nx_mdns_thread_entry Processing thread for mDNS */
10683 /* */
10684 /* RELEASE HISTORY */
10685 /* */
10686 /* DATE NAME DESCRIPTION */
10687 /* */
10688 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10689 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10690 /* resulting in version 6.1 */
10691 /* */
10692 /**************************************************************************/
_nx_mdns_address_change_process(NX_MDNS * mdns_ptr)10693 static VOID _nx_mdns_address_change_process(NX_MDNS *mdns_ptr)
10694 {
10695
10696 ULONG *head;
10697 NX_MDNS_RR *p;
10698 UINT i;
10699
10700
10701 /* Register the host name. */
10702 for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
10703 {
10704
10705 /* Check if the interface is enabled. */
10706 if (!mdns_ptr -> nx_mdns_interface_enabled[i])
10707 continue;
10708
10709 /* Get the local buffer head. */
10710 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10711
10712 if (head)
10713 {
10714
10715 /* Set the pointer. */
10716 head = (ULONG*)(*head);
10717
10718 /* Check the resource record. */
10719 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10720 {
10721
10722 /* Check whether the resource record is valid. */
10723 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
10724 continue;
10725
10726 /* Check the interface index. */
10727 if (p -> nx_mdns_rr_interface_index != i)
10728 continue;
10729
10730 /* If any of a host's IP addresses change, it MUST re-announce those address records. RFC6762, Section8.4, Page31. */
10731 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10732 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10733 {
10734
10735 /* Send the "goodbye " announcement with RR TTL zero. RFC6762, Section8.4, Page31. */
10736 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
10737
10738 /* Clear the retransmit count. */
10739 p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
10740
10741 /* Set the timer count. 250ms. */
10742 p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
10743
10744 /* Set the delete flag. */
10745 p -> nx_mdns_rr_word = (p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
10746
10747 /* Set the mDNS timer. */
10748 _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10749 }
10750
10751 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
10752 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
10753 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
10754 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
10755 }
10756 }
10757
10758 /* Second register the host name, the host does not need to repeat the Probing step, Only Announcing the A/AAAA. */
10759 _nx_mdns_host_name_register(mdns_ptr, NX_FALSE, i);
10760 }
10761 }
10762
10763
10764 /**************************************************************************/
10765 /* */
10766 /* FUNCTION RELEASE */
10767 /* */
10768 /* _nx_mdns_conflict_process PORTABLE C */
10769 /* 6.1 */
10770 /* AUTHOR */
10771 /* */
10772 /* Yuxin Zhou, Microsoft Corporation */
10773 /* */
10774 /* DESCRIPTION */
10775 /* */
10776 /* This function process the mDNS conflict. RFC6762, Section9, Page31 */
10777 /* */
10778 /* INPUT */
10779 /* */
10780 /* mdns_ptr Pointer to mDNS instance */
10781 /* record_rr The resource record */
10782 /* */
10783 /* OUTPUT */
10784 /* */
10785 /* status Completion status */
10786 /* */
10787 /* CALLS */
10788 /* */
10789 /* _nx_mdns_cache_add_string Add the string */
10790 /* _nx_mdns_cache_delete_string Delete the string */
10791 /* _nx_mdns_srv_name_resolve Reslove the service name */
10792 /* nx_mdns_rr_change_notify Resource record notify */
10793 /* */
10794 /* CALLED BY */
10795 /* */
10796 /* _nx_mdns_packet_process Process mDNS packet */
10797 /* */
10798 /* RELEASE HISTORY */
10799 /* */
10800 /* DATE NAME DESCRIPTION */
10801 /* */
10802 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10803 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
10804 /* buffer length verification, */
10805 /* verified memcpy use cases, */
10806 /* resulting in version 6.1 */
10807 /* */
10808 /**************************************************************************/
_nx_mdns_conflict_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)10809 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
10810 {
10811
10812 UINT status;
10813 UCHAR *old_name;
10814 UCHAR *name;
10815 UCHAR *type = NX_NULL;
10816 UCHAR *domain = NX_NULL;
10817 UINT i;
10818 ULONG *head;
10819 NX_MDNS_RR *p;
10820 UCHAR is_host_type;
10821 UINT temp_string_length;
10822 UINT rr_name_length;
10823
10824
10825 /* Initialize the value. */
10826 i = 0;
10827 memset(&temp_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10828 memset(&target_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10829
10830 /* Get rr type. */
10831 if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10832 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT))
10833 {
10834 is_host_type = NX_FALSE;
10835
10836 /* Check string length. */
10837 if (_nx_utility_string_length_check((CHAR *)(record_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
10838 {
10839 return(NX_MDNS_DATA_SIZE_ERROR);
10840 }
10841
10842 /* Store the service name. */
10843 memcpy((CHAR *)&target_string_buffer[0], (const char*)(record_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
10844
10845 /* Get Name, Type, Domain. */
10846 _nx_mdns_service_name_resolve(&target_string_buffer[0], &name, &type, &domain);
10847 }
10848 else if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10849 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10850 {
10851 is_host_type = NX_TRUE;
10852 name = mdns_ptr -> nx_mdns_host_name;
10853 }
10854 else
10855 {
10856
10857 /* This is an unsupported or unknown type. */
10858 return(NX_MDNS_UNSUPPORTED_TYPE);
10859 }
10860
10861 /* Check the conflict count. */
10862 if (record_rr -> nx_mdns_rr_conflict_count >= NX_MDNS_CONFLICT_COUNT)
10863 {
10864
10865 /* Yes, Receive the confilictiong mDNS, Probing failure. */
10866 if ((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10867 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A))
10868 {
10869
10870 /* Service name has been registered , invoke the notify function. */
10871 if (mdns_ptr -> nx_mdns_probing_notify)
10872 {
10873 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, name, NX_MDNS_LOCAL_SERVICE_REGISTERED_FAILURE);
10874 }
10875 }
10876
10877 /* Return. */
10878 return (NX_MDNS_ERROR);
10879 }
10880
10881 /* Record the old name. */
10882 old_name = record_rr -> nx_mdns_rr_name;
10883
10884 /* Set the new name and probing it. */
10885 while ((*name) != '\0')
10886 {
10887 temp_string_buffer[i++] = *name++;
10888 }
10889
10890 /* The first conflict, only add the " (2)". */
10891 if (record_rr -> nx_mdns_rr_conflict_count == 0)
10892 {
10893 temp_string_buffer[i++] = ' ';
10894 temp_string_buffer[i++] = '(';
10895 temp_string_buffer[i++] = '2';
10896 temp_string_buffer[i++] = ')';
10897 }
10898
10899 /* Modify the count, eg: " (2)" change to " (3)". */
10900 else
10901 {
10902 temp_string_buffer[i-2] = (UCHAR)(temp_string_buffer[i-2] + 1);
10903 }
10904
10905
10906 if(is_host_type == NX_TRUE)
10907 {
10908
10909 /* Check string length. */
10910 if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_HOST_NAME_MAX))
10911 {
10912 return(NX_MDNS_DATA_SIZE_ERROR);
10913 }
10914
10915 /* Construct the target host. */
10916 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. */
10917
10918 temp_string_buffer[i++] = '.';
10919
10920 /* Check string length. */
10921 if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &temp_string_length, NX_MDNS_DOMAIN_NAME_MAX))
10922 {
10923 return(NX_MDNS_DATA_SIZE_ERROR);
10924 }
10925
10926 /* Add the domain. */
10927 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. */
10928 }
10929 else
10930 {
10931 temp_string_buffer[i++] = '.';
10932
10933 /* Set the Type. */
10934 while ((*type) != '\0')
10935 {
10936 temp_string_buffer[i++] = *type++;
10937 }
10938
10939 temp_string_buffer[i++] = '.';
10940
10941 /* Set the Domain. */
10942 while ((*domain) != '\0')
10943 {
10944 temp_string_buffer[i++] = *domain++;
10945 }
10946 }
10947
10948 /* Check string length. */
10949 if (_nx_utility_string_length_check((CHAR *)&temp_string_buffer[0], &temp_string_length, NX_MDNS_NAME_MAX))
10950 {
10951 return(NX_MDNS_DATA_SIZE_ERROR);
10952 }
10953
10954 /* Add the new resource records. */
10955 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL,
10956 &temp_string_buffer[0], temp_string_length,
10957 (VOID **)(&record_rr -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
10958
10959 if (status )
10960 {
10961
10962 /* No, return error status. */
10963 return(status);
10964 }
10965
10966 /* Update the state. */
10967 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
10968 record_rr -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
10969 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
10970 record_rr -> nx_mdns_rr_conflict_count ++;
10971
10972 /* Set the mDNS timer. */
10973 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
10974
10975 /* Update the PTR/SRV data name. */
10976 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10977 head = (ULONG*)(*head);
10978
10979 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10980 {
10981 if ((((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) && (is_host_type == NX_FALSE)) ||
10982 ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) && (is_host_type == NX_TRUE))) &&
10983 (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == old_name))
10984 {
10985
10986 /* Add the new resource records. */
10987 status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_string_buffer[0], temp_string_length,
10988 (VOID **)(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)), NX_FALSE, NX_TRUE);
10989
10990 /* Delete the rdata name. */
10991 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10992 }
10993 }
10994
10995 /* Delete the old name. */
10996 _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10997
10998 return(NX_MDNS_SUCCESS);
10999 }
11000 #endif /* NX_MDNS_DISABLE_SERVER */
11001
11002
11003 #ifndef NX_MDNS_DISABLE_CLIENT
11004 /**************************************************************************/
11005 /* */
11006 /* FUNCTION RELEASE */
11007 /* */
11008 /* _nx_mdns_service_change_notify_process PORTABLE C */
11009 /* 6.1 */
11010 /* AUTHOR */
11011 /* */
11012 /* Yuxin Zhou, Microsoft Corporation */
11013 /* */
11014 /* DESCRIPTION */
11015 /* */
11016 /* This function processes the mDNS service change operation, when the */
11017 /* service information change, notify the application. */
11018 /* */
11019 /* INPUT */
11020 /* */
11021 /* mdns_ptr Pointer to mDNS instance */
11022 /* record_rr The resource record */
11023 /* is_present The service type */
11024 /* */
11025 /* OUTPUT */
11026 /* */
11027 /* status Completion status */
11028 /* */
11029 /* CALLS */
11030 /* */
11031 /* tx_mutex_get Get the mDNS mutex */
11032 /* tx_mutex_put Put the mDNS mutex */
11033 /* */
11034 /* CALLED BY */
11035 /* */
11036 /* Application Code */
11037 /* */
11038 /* RELEASE HISTORY */
11039 /* */
11040 /* DATE NAME DESCRIPTION */
11041 /* */
11042 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11043 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11044 /* verified memcpy use cases, */
11045 /* resulting in version 6.1 */
11046 /* */
11047 /**************************************************************************/
_nx_mdns_service_change_notify_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * new_rr,UCHAR is_present)11048 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present)
11049 {
11050
11051 UINT notify_status = 0;
11052 ULONG *head;
11053 NX_MDNS_RR *p;
11054 NX_MDNS_SERVICE temp_service;
11055 UINT rr_name_length;
11056
11057
11058 /* Initialize the struct. */
11059 memset(&temp_service, 0, sizeof(NX_MDNS_SERVICE));
11060
11061 /* Compare the RDATA. */
11062 switch (new_rr -> nx_mdns_rr_type)
11063 {
11064 case NX_MDNS_RR_TYPE_A:
11065 case NX_MDNS_RR_TYPE_AAAA:
11066 {
11067
11068 /* Get the remote buffer head. */
11069 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11070 head = (ULONG*)(*head);
11071
11072 /* Check the resource record. */
11073 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
11074 {
11075
11076 /* Check whether the resource record is valid. */
11077 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11078 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11079 continue;
11080
11081 /* Check the interface. */
11082 if (p -> nx_mdns_rr_interface_index != new_rr -> nx_mdns_rr_interface_index)
11083 continue;
11084
11085 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
11086 {
11087 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == new_rr -> nx_mdns_rr_name)
11088 {
11089
11090 /* Check string length. */
11091 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11092 {
11093 break;
11094 }
11095
11096 /* Store the Service name. */
11097 memcpy((CHAR *)(&temp_string_buffer[0]), (CHAR *)(p -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11098
11099 /* Check if the address is updated. */
11100 if (((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0)) ||
11101 (((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))))
11102 {
11103 notify_status = NX_MDNS_PEER_SERVICE_UPDATED;
11104 }
11105 break;
11106 }
11107 }
11108 }
11109
11110 break;
11111 }
11112 case NX_MDNS_RR_TYPE_SRV:
11113 {
11114
11115 /* Check string length. */
11116 if (_nx_utility_string_length_check((CHAR *)(new_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11117 {
11118 break;
11119 }
11120
11121 /* Store the Service name. */
11122 memcpy((CHAR *)&temp_string_buffer[0], (CHAR *)(new_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11123
11124 /* Check if the service is new. */
11125 if ((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0))
11126 {
11127 notify_status = NX_MDNS_PEER_SERVICE_RECEIVED;
11128 }
11129 else if ((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))
11130 {
11131 notify_status = NX_MDNS_PEER_SERVICE_DELETED;
11132 }
11133 break;
11134 }
11135 default:
11136 {
11137
11138 /* This is an unsupported or unknown type. */
11139 return;
11140 }
11141 }
11142
11143 /* Check if need to call then notify function. */
11144 if (notify_status == 0)
11145 return;
11146
11147 /* Store the service name. */
11148 memcpy((CHAR *)(&temp_service.buffer[0]), (CHAR *)(&temp_string_buffer[0]), rr_name_length); /* Use case of memcpy is verified. */
11149
11150 /* Reslove the service name. */
11151 if (_nx_mdns_service_name_resolve(&temp_service.buffer[0], &(temp_service.service_name), &(temp_service.service_type), &(temp_service.service_domain)))
11152 return;
11153
11154 /* Compare the service change type. */
11155 if (_nx_mdns_service_mask_match(mdns_ptr, temp_service.service_type, mdns_ptr -> nx_mdns_service_notify_mask))
11156 return;
11157
11158 /* Get the additional information. */
11159 _nx_mdns_service_addition_info_get(mdns_ptr, &temp_string_buffer[0], &temp_service, new_rr -> nx_mdns_rr_interface_index);
11160
11161 /* Call the notify function. */
11162 (mdns_ptr -> nx_mdns_service_change_notify)(mdns_ptr, &temp_service, notify_status);
11163 }
11164
11165
11166 /**************************************************************************/
11167 /* */
11168 /* FUNCTION RELEASE */
11169 /* */
11170 /* _nx_mdns_service_addition_info_get PORTABLE C */
11171 /* 6.1 */
11172 /* AUTHOR */
11173 /* */
11174 /* Yuxin Zhou, Microsoft Corporation */
11175 /* */
11176 /* DESCRIPTION */
11177 /* */
11178 /* This function adds the mDNS resource record into remote buffer, */
11179 /* mDNS thread send the query message using continuous type. */
11180 /* */
11181 /* INPUT */
11182 /* */
11183 /* mdns_ptr Pointer to mDNS instance */
11184 /* name The service instance */
11185 /* type The service type */
11186 /* domain The domain name */
11187 /* */
11188 /* OUTPUT */
11189 /* */
11190 /* status Completion status */
11191 /* */
11192 /* CALLS */
11193 /* */
11194 /* tx_mutex_get Get the mDNS mutex */
11195 /* tx_mutex_put Put the mDNS mutex */
11196 /* _nx_mdns_query_check Check the query RR */
11197 /* _nx_mdns_cache_add_string Add the string into buffer */
11198 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11199 /* _nx_mdns_cache_add_resource_record Add the resource record */
11200 /* into buffer */
11201 /* */
11202 /* CALLED BY */
11203 /* */
11204 /* Application Code */
11205 /* */
11206 /* RELEASE HISTORY */
11207 /* */
11208 /* DATE NAME DESCRIPTION */
11209 /* */
11210 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11211 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11212 /* verified memcpy use cases, */
11213 /* resulting in version 6.1 */
11214 /* */
11215 /**************************************************************************/
_nx_mdns_service_addition_info_get(NX_MDNS * mdns_ptr,UCHAR * srv_name,NX_MDNS_SERVICE * service,UINT interface_index)11216 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index)
11217 {
11218
11219 UINT index = 0;
11220 ULONG current_time;
11221 ULONG *head, *tail;
11222 UCHAR i;
11223 NX_MDNS_RR *p;
11224 NX_MDNS_RR *p1;
11225 UINT srv_name_length;
11226 UINT temp_length;
11227
11228
11229 /* Check string length. */
11230 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
11231 {
11232 return(NX_MDNS_ERROR);
11233 }
11234
11235 /* Get the current time. */
11236 current_time = tx_time_get();
11237
11238 for(i = 0; i < 2; i++)
11239 {
11240
11241 /* Set the pointer. */
11242 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
11243 {
11244 #ifndef NX_MDNS_DISABLE_SERVER
11245 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
11246 #else
11247 continue;
11248 #endif /* NX_MDNS_DISABLE_SERVER */
11249 }
11250 else
11251 {
11252 #ifndef NX_MDNS_DISABLE_CLIENT
11253 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11254 #else
11255 continue;
11256 #endif /* NX_MDNS_DISABLE_CLIENT */
11257 }
11258
11259 if(head == NX_NULL)
11260 continue;
11261
11262 /* Set the pointer. */
11263 tail = (ULONG*)(*head);
11264
11265 /* Check the resource record. */
11266 for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
11267 {
11268
11269 /* Check whether the resource record is valid. */
11270 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11271 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11272 continue;
11273
11274 /* Check the interface index. */
11275 if (p -> nx_mdns_rr_interface_index != interface_index)
11276 continue;
11277
11278 /* Check the type and name. */
11279 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
11280 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11281 {
11282
11283 /* Update the elasped timer. */
11284 p -> nx_mdns_rr_elapsed_time = current_time;
11285
11286 /* Set the service priority, weight, port and target. */
11287 service -> service_priority = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority;
11288 service -> service_weight = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights;
11289 service -> service_port = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port;
11290
11291 /* Check string length. */
11292 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))
11293 {
11294 return(NX_MDNS_ERROR);
11295 }
11296
11297 /* Store the target host. */
11298 memcpy((CHAR *)(service -> service_host), /* Use case of memcpy is verified. */
11299 (CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
11300 temp_length + 1);
11301
11302 /* All address records (type "A" and "AAAA") named in the SRV rdata */
11303 for (p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
11304 {
11305
11306 /* Update the elasped timer. */
11307 p1 -> nx_mdns_rr_elapsed_time = current_time;
11308
11309 /* Check the interface index. */
11310 if (p1 -> nx_mdns_rr_interface_index != interface_index)
11311 continue;
11312
11313 /* Find the "A" records. */
11314 if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) &&
11315 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11316 {
11317
11318 /* Set the IPv4 address. */
11319 service -> service_ipv4 = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
11320 }
11321
11322 /* Find the "AAAA" records. */
11323 if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA) &&
11324 (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11325 {
11326 if (index < NX_MDNS_IPV6_ADDRESS_COUNT)
11327 {
11328
11329 /* Set the IPv6 address. */
11330 service -> service_ipv6[index][0] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0];
11331 service -> service_ipv6[index][1] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1];
11332 service -> service_ipv6[index][2] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2];
11333 service -> service_ipv6[index][3] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3];
11334 index ++;
11335 }
11336 }
11337 }
11338 }
11339
11340 /* Check the type and name. */
11341 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) &&
11342 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11343 {
11344
11345 /* Update the elasped timer. */
11346 p -> nx_mdns_rr_elapsed_time = current_time;
11347
11348 /* Set the text valid flag. */
11349 service -> service_text_valid = 1;
11350
11351 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
11352 {
11353
11354 /* Check string length. */
11355 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))
11356 {
11357 continue;
11358 }
11359
11360 /* Store the txt. */
11361 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. */
11362 }
11363 }
11364 }
11365 }
11366
11367 /* Set the interface index. */
11368 service -> interface_index = (UCHAR)interface_index;
11369
11370 /* Return a error status. */
11371 return(NX_MDNS_SUCCESS);
11372 }
11373 #endif /* NX_MDNS_DISABLE_CLIENT */
11374
11375
11376 /**************************************************************************/
11377 /* */
11378 /* FUNCTION RELEASE */
11379 /* */
11380 /* _nx_mdns_cache_initialize PORTABLE C */
11381 /* 6.1 */
11382 /* AUTHOR */
11383 /* */
11384 /* Yuxin Zhou, Microsoft Corporation */
11385 /* */
11386 /* DESCRIPTION */
11387 /* */
11388 /* This function initializes the mDNS remote buffer and local buffer. */
11389 /* */
11390 /* INPUT */
11391 /* */
11392 /* mdns_ptr Pointer to mDNS instance */
11393 /* local_cache_ptr Pointer to local cache */
11394 /* local_cache_size The size of local cache */
11395 /* peer_cache_ptr Pointer to peer cache */
11396 /* peer_cache_size The size of peer cache */
11397 /* */
11398 /* OUTPUT */
11399 /* */
11400 /* status Completion status */
11401 /* */
11402 /* CALLS */
11403 /* */
11404 /* tx_mutex_get Get the mDNS mutex */
11405 /* tx_mutex_put Put the mDNS mutex */
11406 /* */
11407 /* CALLED BY */
11408 /* */
11409 /* _nx_mdns_create Initialize the mDNS structure */
11410 /* _nx_mdns_disable Disable the mDNS function */
11411 /* _nx_mdns_peer_cache_clear Clear the peer cache */
11412 /* */
11413 /* RELEASE HISTORY */
11414 /* */
11415 /* DATE NAME DESCRIPTION */
11416 /* */
11417 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11418 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11419 /* resulting in version 6.1 */
11420 /* */
11421 /**************************************************************************/
_nx_mdns_cache_initialize(NX_MDNS * mdns_ptr,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size)11422 UINT _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size,
11423 VOID *peer_cache_ptr, UINT peer_cache_size)
11424 {
11425
11426 ULONG *head;
11427 ULONG *tail;
11428
11429
11430 #ifndef NX_MDNS_DISABLE_SERVER
11431 /* Check the cache. */
11432 if (local_cache_ptr)
11433 {
11434
11435 /* Zero out the cache. */
11436 memset(local_cache_ptr, 0, local_cache_size);
11437
11438 /* Set the head. */
11439 head = (ULONG*)local_cache_ptr;
11440 *head = (ULONG)((ULONG*)local_cache_ptr + 1);
11441
11442 /* Set the tail. */
11443 tail = (ULONG*)local_cache_ptr + (local_cache_size >> 2) - 1;
11444 *tail = (ULONG)tail;
11445
11446 /* Record the info. */
11447 mdns_ptr -> nx_mdns_local_service_cache = (UCHAR*)local_cache_ptr;
11448 mdns_ptr -> nx_mdns_local_service_cache_size = local_cache_size;
11449
11450 /* Clear the count. */
11451 mdns_ptr -> nx_mdns_local_rr_count = 0;
11452 mdns_ptr -> nx_mdns_local_string_count = 0;
11453 mdns_ptr -> nx_mdns_local_string_bytes = 0;
11454 }
11455 #else
11456 NX_PARAMETER_NOT_USED(local_cache_ptr);
11457 NX_PARAMETER_NOT_USED(local_cache_size);
11458 #endif /* NX_MDNS_DISABLE_SERVER */
11459
11460 #ifndef NX_MDNS_DISABLE_CLIENT
11461 /* Check the cache. */
11462 if (peer_cache_ptr)
11463 {
11464
11465 /* Zero out the cache. */
11466 memset(peer_cache_ptr, 0, peer_cache_size);
11467
11468 /* Set the head. */
11469 head = (ULONG*)peer_cache_ptr;
11470 *head = (ULONG)((ULONG*)peer_cache_ptr + 1);
11471
11472 /* Set the tail. */
11473 tail = (ULONG*)peer_cache_ptr + (peer_cache_size >> 2) - 1;
11474 *tail = (ULONG)tail;
11475
11476 /* Record the info. */
11477 mdns_ptr -> nx_mdns_peer_service_cache = (UCHAR*)peer_cache_ptr;
11478 mdns_ptr -> nx_mdns_peer_service_cache_size = peer_cache_size;
11479
11480 /* Clear the count. */
11481 mdns_ptr -> nx_mdns_peer_rr_count = 0;
11482 mdns_ptr -> nx_mdns_peer_string_count = 0;
11483 mdns_ptr -> nx_mdns_peer_string_bytes = 0;
11484 }
11485 #else
11486 NX_PARAMETER_NOT_USED(peer_cache_ptr);
11487 NX_PARAMETER_NOT_USED(peer_cache_size);
11488 #endif /* NX_MDNS_DISABLE_CLIENT */
11489
11490 return(NX_SUCCESS);
11491 }
11492
11493
11494 /**************************************************************************/
11495 /* */
11496 /* FUNCTION RELEASE */
11497 /* */
11498 /* _nx_mdns_cache_add_resource_record PORTABLE C */
11499 /* 6.1 */
11500 /* AUTHOR */
11501 /* */
11502 /* Yuxin Zhou, Microsoft Corporation */
11503 /* */
11504 /* DESCRIPTION */
11505 /* */
11506 /* This function adds the mDNS resource record into record buffer. */
11507 /* */
11508 /* INPUT */
11509 /* */
11510 /* mdns_ptr Pointer to mDNS instance */
11511 /* cache_type Cache type: local or peer */
11512 /* record_ptr Pointer to resource record */
11513 /* insert_rr Pointer to insert resource */
11514 /* record */
11515 /* */
11516 /* OUTPUT */
11517 /* */
11518 /* status Completion status */
11519 /* */
11520 /* CALLS */
11521 /* */
11522 /* _nx_mdns_cache_find_resource_record Find the resource record */
11523 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11524 /* */
11525 /* CALLED BY */
11526 /* */
11527 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
11528 /* _nx_mdns_rr_ptr_add Add PTR resource record */
11529 /* _nx_mdns_rr_srv_add Add SRV resource record */
11530 /* _nx_mdns_rr_txt_add Add TXT resource record */
11531 /* _nx_mdns_query Send query */
11532 /* _nx_mdns_cache_delete_rr_string Delete the rr string */
11533 /* _nx_mdns_packet_rr_process Process resource record */
11534 /* */
11535 /* RELEASE HISTORY */
11536 /* */
11537 /* DATE NAME DESCRIPTION */
11538 /* */
11539 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11540 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
11541 /* verified memcpy use cases, */
11542 /* resulting in version 6.1 */
11543 /* */
11544 /**************************************************************************/
_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 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)
11546 {
11547
11548 UCHAR *cache_ptr;
11549 UINT cache_size;
11550 ULONG *tail;
11551 ULONG *head;
11552 NX_MDNS_RR *p;
11553 NX_MDNS_RR *rr;
11554 UINT rr_name_length;
11555
11556 #ifndef NX_MDNS_DISABLE_CLIENT
11557 ULONG elapsed_time;
11558 ULONG current_time;
11559 ULONG min_elapsed_time;
11560 #endif /* NX_MDNS_DISABLE_CLIENT */
11561
11562
11563 #ifndef NX_MDNS_DISABLE_CLIENT
11564 /* Initialize the parameters. */
11565 min_elapsed_time = 0;
11566 current_time = tx_time_get();
11567 #endif /* NX_MDNS_DISABLE_CLIENT */
11568
11569 /* Initialize. */
11570 if (is_present)
11571 *is_present = NX_FALSE;
11572
11573 /* Check the RR with same rname, rtype, rclass and rdata. */
11574 if (_nx_mdns_cache_find_resource_record(mdns_ptr, cache_type, record_ptr, NX_MDNS_RR_MATCH_ALL, &rr) == NX_MDNS_SUCCESS)
11575 {
11576
11577 /* Check string length. */
11578 if (_nx_utility_string_length_check((CHAR *)(rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11579 {
11580 return(NX_MDNS_DATA_SIZE_ERROR);
11581 }
11582
11583 /* Copy other informations of record_ptr into insert_rr resource record. */
11584 memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11585
11586 /* Special process for _services._dns-sd._udp.local which pointer to same service type. */
11587 if ((rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
11588 (!_nx_mdns_name_match(rr -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
11589 {
11590 rr -> nx_mdns_rr_count ++;
11591 }
11592
11593 /* Delete the resource record same strings. */
11594 _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, rr);
11595
11596 /* Set the insert ptr. */
11597 if(insert_ptr != NX_NULL)
11598 *insert_ptr = rr;
11599
11600 /* Set the flag. */
11601 if (is_present)
11602 *is_present = NX_TRUE;
11603
11604 return(NX_MDNS_SUCCESS);
11605 }
11606
11607 /* Check the cache type. */
11608 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11609 {
11610 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11611 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
11612 }
11613 else
11614 {
11615 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11616 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
11617 }
11618
11619 /* Check cache pointer and cache size. */
11620 if ((cache_ptr == NX_NULL) || (cache_size == 0))
11621 {
11622 return(NX_MDNS_ERROR);
11623 }
11624
11625 /* Get head and tail. */
11626 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
11627 tail = (ULONG*)(*tail);
11628 head = (ULONG*)cache_ptr;
11629 head = (ULONG*)(*head);
11630
11631 /* Set the pointer. */
11632 rr = NX_NULL;
11633
11634 /* Find an empty entry before head. */
11635 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11636 {
11637 if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11638 {
11639 rr = p;
11640 break;
11641 }
11642 }
11643
11644 if (!rr)
11645 {
11646
11647 /* Check whether the cache is full. */
11648 if((head + (sizeof(NX_MDNS_RR) >> 2)) > tail)
11649 {
11650 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11651 {
11652 return(NX_MDNS_CACHE_ERROR);
11653 }
11654 else
11655 {
11656
11657 #ifndef NX_MDNS_DISABLE_CLIENT
11658 /* Find an aging resource reocrd and repalce it. */
11659 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11660 {
11661
11662 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11663 continue;
11664
11665 /* Calculate the elapsed time. */
11666 elapsed_time = current_time - p -> nx_mdns_rr_elapsed_time;
11667
11668 /* Check the elapsed time to find the aging resource record. */
11669 if (elapsed_time >= min_elapsed_time)
11670 {
11671 rr = p;
11672 min_elapsed_time = elapsed_time;
11673 }
11674 }
11675
11676 if (rr)
11677 {
11678
11679 /* Delete this record. */
11680 _nx_mdns_cache_delete_resource_record(mdns_ptr, cache_type, rr);
11681
11682 /* Update the head. */
11683 head = (ULONG*)cache_ptr;
11684 head = (ULONG*)(*head);
11685 }
11686 else
11687 {
11688 return(NX_MDNS_CACHE_ERROR);
11689 }
11690 #endif /* NX_MDNS_DISABLE_CLIENT */
11691 }
11692 }
11693 else
11694 {
11695 rr = (NX_MDNS_RR*)head;
11696 }
11697 }
11698
11699 /* Just copy it to cache_ptr. */
11700 memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11701
11702 /* Check the type. */
11703 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11704 {
11705
11706 /* Increase the count. */
11707 mdns_ptr -> nx_mdns_local_rr_count ++;
11708 }
11709 else
11710 {
11711
11712 /* Increase the count. */
11713 mdns_ptr -> nx_mdns_peer_rr_count ++;
11714 }
11715
11716 #ifndef NX_MDNS_DISABLE_CLIENT
11717 /* Update the peer resource record elapsed time. */
11718 if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
11719 {
11720
11721 /* Get the current time to set the elapsed time. */
11722 rr -> nx_mdns_rr_elapsed_time = current_time;
11723 }
11724 #endif /* NX_MDNS_DISABLE_CLIENT */
11725
11726 /* Set the insert ptr. */
11727 if(insert_ptr != NX_NULL)
11728 *insert_ptr = rr;
11729
11730 if((ULONG*)rr >= head)
11731 {
11732
11733 /* Update HEAD when new record is added. */
11734 head = (ULONG*)cache_ptr;
11735 *head = (ULONG)(rr + 1);
11736 }
11737
11738 return(NX_MDNS_SUCCESS);
11739 }
11740
11741
11742 /**************************************************************************/
11743 /* */
11744 /* FUNCTION RELEASE */
11745 /* */
11746 /* _nx_mdns_cache_delete_resource_record PORTABLE C */
11747 /* 6.1 */
11748 /* AUTHOR */
11749 /* */
11750 /* Yuxin Zhou, Microsoft Corporation */
11751 /* */
11752 /* DESCRIPTION */
11753 /* */
11754 /* This function deletes the mDNS resource record from record buffer. */
11755 /* */
11756 /* INPUT */
11757 /* */
11758 /* mdns_ptr Pointer to mDNS instance. */
11759 /* cache_type Cache type: local or peer */
11760 /* record_ptr Pointer to resource record. */
11761 /* */
11762 /* OUTPUT */
11763 /* */
11764 /* status Completion status */
11765 /* */
11766 /* CALLS */
11767 /* */
11768 /* _nx_mdns_cache_delete_string Delete the string from buffer */
11769 /* */
11770 /* CALLED BY */
11771 /* */
11772 /* _nx_mdns_rr_delete Delete the resource record */
11773 /* _nx_mdns_query Send the one-shot query */
11774 /* _nx_mdns_timer_event_process Process the timer event */
11775 /* _nx_mdns_packet_process Process mDNS packet */
11776 /* _nx_mdns_cache_delete_rr_string Delete the rr string */
11777 /* */
11778 /* RELEASE HISTORY */
11779 /* */
11780 /* DATE NAME DESCRIPTION */
11781 /* */
11782 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11783 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11784 /* resulting in version 6.1 */
11785 /* */
11786 /**************************************************************************/
_nx_mdns_cache_delete_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr)11787 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr)
11788 {
11789
11790 UCHAR *cache_ptr;
11791 ULONG *head;
11792
11793
11794 /* Delete the resource record strings. */
11795 _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, record_ptr);
11796
11797 /* Zero out the record. */
11798 memset(record_ptr, 0, sizeof(NX_MDNS_RR));
11799
11800 /* Check the type. */
11801 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11802 {
11803
11804 /* Decrease the count. */
11805 mdns_ptr -> nx_mdns_local_rr_count --;
11806
11807 /* Set the cache. */
11808 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11809 }
11810 else
11811 {
11812
11813 /* Decrease the count. */
11814 mdns_ptr -> nx_mdns_peer_rr_count --;
11815
11816 /* Set the cache. */
11817 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11818 }
11819
11820 if (cache_ptr == NX_NULL)
11821 {
11822 return(NX_MDNS_CACHE_ERROR);
11823 }
11824
11825 /* Get head. */
11826 head = (ULONG*)cache_ptr;
11827 head = (ULONG*)(*head);
11828
11829 /* Move HEAD if the last RR is deleted. */
11830 if(record_ptr == ((NX_MDNS_RR*)head - 1))
11831 {
11832 while(record_ptr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11833 {
11834 record_ptr--;
11835 if(record_ptr < (NX_MDNS_RR*)cache_ptr)
11836 break;
11837 }
11838 *((ULONG*)cache_ptr) = (ULONG)(record_ptr + 1);
11839 }
11840
11841 return(NX_MDNS_SUCCESS);
11842 }
11843
11844
11845 /**************************************************************************/
11846 /* */
11847 /* FUNCTION RELEASE */
11848 /* */
11849 /* _nx_mdns_cache_find_resource_record PORTABLE C */
11850 /* 6.1 */
11851 /* AUTHOR */
11852 /* */
11853 /* Yuxin Zhou, Microsoft Corporation */
11854 /* */
11855 /* DESCRIPTION */
11856 /* */
11857 /* This function finds the mDNS resource record in record buffer. */
11858 /* */
11859 /* INPUT */
11860 /* */
11861 /* mdns_ptr Pointer to mDNS instance. */
11862 /* cache_type Cache type: local or peer */
11863 /* record_ptr Resource record. */
11864 /* match_type Match type. */
11865 /* search_rr The search resource record. */
11866 /* */
11867 /* OUTPUT */
11868 /* */
11869 /* status Completion status */
11870 /* */
11871 /* CALLS */
11872 /* */
11873 /* None */
11874 /* */
11875 /* CALLED BY */
11876 /* */
11877 /* _nx_mdns_packet_process Process mDNS packet */
11878 /* _nx_mdns_cache_add_resource_record Add the resource record */
11879 /* */
11880 /* RELEASE HISTORY */
11881 /* */
11882 /* DATE NAME DESCRIPTION */
11883 /* */
11884 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11885 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11886 /* resulting in version 6.1 */
11887 /* */
11888 /**************************************************************************/
_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 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)
11890 {
11891
11892 UCHAR *cache_ptr;
11893 ULONG *head;
11894 NX_MDNS_RR *p;
11895 UINT same_rdata;
11896
11897
11898 /* Check the cache type. */
11899 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11900 {
11901 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11902 }
11903 else
11904 {
11905 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11906 }
11907
11908 /* Get head. */
11909 head = (ULONG*)cache_ptr;
11910 head = (ULONG*)(*head);
11911
11912 /* Find the same record. */
11913 for(p = (NX_MDNS_RR*)((UCHAR*)cache_ptr + sizeof(ULONG)); (ULONG*)p < head; p++)
11914 {
11915
11916 /* Check the interface index. */
11917 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
11918 continue;
11919
11920 /* Check whether the resource record is valid. */
11921 if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11922 continue;
11923
11924 /* Check whether the same record it is. RFC6762, Section6, Page13. */
11925 /* The rules: rrname must match the question name.
11926 rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
11927 rrclass must match the question qclass unless the qclass is "ANY". */
11928 if (p -> nx_mdns_rr_name != record_ptr -> nx_mdns_rr_name)
11929 continue;
11930
11931 /* In the probing state, we need not match the type. */
11932 if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
11933 {
11934 if ((p -> nx_mdns_rr_type != record_ptr -> nx_mdns_rr_type) &&
11935 (record_ptr -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
11936 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
11937 continue;
11938 }
11939
11940 /* Check the RR class, Ignore the top bit. */
11941 if ((p -> nx_mdns_rr_class != (record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
11942 ((record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK) != NX_MDNS_RR_CLASS_ALL))
11943 continue;
11944
11945 /* Check if just match the basic info. */
11946 if (match_type == NX_MDNS_RR_MATCH_EXCEPT_RDATA)
11947 {
11948
11949 /* Find the same record. */
11950 *search_rr = p;
11951 return(NX_MDNS_SUCCESS);
11952 }
11953 else
11954 {
11955
11956 /* Yes, match all information of resource record. */
11957
11958 /* Check the state. */
11959 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11960 continue;
11961
11962 /* Reset the value. */
11963 same_rdata = NX_FALSE;
11964
11965 /* Compare the RDATA. */
11966 switch (p -> nx_mdns_rr_type)
11967 {
11968 case NX_MDNS_RR_TYPE_A:
11969 {
11970 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)
11971 {
11972 same_rdata = NX_TRUE;
11973 }
11974 break;
11975 }
11976 case NX_MDNS_RR_TYPE_SRV:
11977 {
11978 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) &&
11979 (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) &&
11980 (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) &&
11981 (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))
11982 {
11983 same_rdata = NX_TRUE;
11984 }
11985 break;
11986 }
11987 case NX_MDNS_RR_TYPE_AAAA:
11988 {
11989 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))
11990 {
11991 same_rdata = NX_TRUE;
11992 }
11993 break;
11994 }
11995 case NX_MDNS_RR_TYPE_PTR:
11996 case NX_MDNS_RR_TYPE_TXT:
11997
11998 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
11999 case NX_MDNS_RR_TYPE_CNAME:
12000 case NX_MDNS_RR_TYPE_NS:
12001 #endif
12002 {
12003
12004 /* Check the rdata. */
12005 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)
12006 {
12007 same_rdata = NX_TRUE;
12008 }
12009 break;
12010 }
12011 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12012 case NX_MDNS_RR_TYPE_MX:
12013 {
12014 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) &&
12015 (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))
12016 {
12017 same_rdata = NX_TRUE;
12018 }
12019 break;
12020 }
12021 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
12022
12023 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12024 case NX_MDNS_RR_TYPE_NSEC:
12025 {
12026 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) &&
12027 (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) &&
12028 (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) &&
12029 (!memcmp(&(p -> 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[0]),
12031 record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length)))
12032 {
12033 same_rdata = NX_TRUE;
12034 }
12035 break;
12036 }
12037 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12038 default:
12039 {
12040
12041 /* This is an unsupported or unknown type. */
12042 return(NX_MDNS_UNSUPPORTED_TYPE);
12043 }
12044 }
12045
12046 /* Check the same RR. */
12047 if (same_rdata == NX_TRUE)
12048 {
12049
12050 /* Find the same record. */
12051 *search_rr = p;
12052 return(NX_MDNS_SUCCESS);
12053 }
12054 }
12055 }
12056
12057 return(NX_MDNS_ERROR);
12058 }
12059
12060
12061 /**************************************************************************/
12062 /* */
12063 /* FUNCTION RELEASE */
12064 /* */
12065 /* _nx_mdns_cache_add_string PORTABLE C */
12066 /* 6.1 */
12067 /* AUTHOR */
12068 /* */
12069 /* Yuxin Zhou, Microsoft Corporation */
12070 /* */
12071 /* DESCRIPTION */
12072 /* */
12073 /* This function adds or finds the mDNS string in the record buffer. */
12074 /* */
12075 /* INPUT */
12076 /* */
12077 /* mdns_ptr Pointer to mDNS instance */
12078 /* cache_type Cache type: local or peer */
12079 /* memory_ptr Pointer to the string */
12080 /* memory_size The size of string. */
12081 /* insert_rr Pointer to insert string. */
12082 /* find_string If set, just find the existed */
12083 /* string, otherwise, insert */
12084 /* this string if it does not */
12085 /* exist. */
12086 /* add_name If set, use name match */
12087 /* to check the string, */
12088 /* otherwise, use memcmp. */
12089 /* */
12090 /* OUTPUT */
12091 /* */
12092 /* status Completion status */
12093 /* */
12094 /* CALLS */
12095 /* */
12096 /* none */
12097 /* */
12098 /* CALLED BY */
12099 /* */
12100 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
12101 /* _nx_mdns_rr_ptr_add Add PTR resource record */
12102 /* _nx_mdns_rr_srv_add Add SRV resource record */
12103 /* _nx_mdns_rr_txt_add Add TXT resource record */
12104 /* _nx_mdns_query Send query */
12105 /* _nx_mdns_conflict_process Process the conflict */
12106 /* _nx_mdns_packet_rr_process Process resource record */
12107 /* */
12108 /* RELEASE HISTORY */
12109 /* */
12110 /* DATE NAME DESCRIPTION */
12111 /* */
12112 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12113 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
12114 /* verified memcpy use cases, */
12115 /* resulting in version 6.1 */
12116 /* */
12117 /**************************************************************************/
_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 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)
12119 {
12120
12121 UCHAR *cache_ptr;
12122 UINT cache_size;
12123 ULONG *tail;
12124 ULONG *head;
12125 UINT memory_len;
12126 UINT used_cache_size;
12127 USHORT len, cnt;
12128 USHORT min_len = 0xFFFF;
12129 UCHAR *p, *available, *start;
12130
12131
12132 /* Check the cache type. */
12133 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12134 {
12135 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12136 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12137 }
12138 else
12139 {
12140 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12141 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12142 }
12143
12144 /* Check cache pointer and cache size. */
12145 if ((cache_ptr == NX_NULL) || (cache_size == 0))
12146 {
12147 return(NX_MDNS_ERROR);
12148 }
12149
12150 /* Get head and tail. */
12151 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12152 p = (UCHAR*)tail;
12153 tail = (ULONG*)(*tail);
12154 head = (ULONG*)cache_ptr;
12155 head = (ULONG*)(*head);
12156
12157 /* Calculate the amount of memory needed to store this string, including CNT and LEN fields. */
12158
12159 /* Make the length 4 bytes align. */
12160 memory_len = memory_size;
12161
12162 /* Add the length of CNT and LEN fields. */
12163 memory_len = ((memory_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12164
12165 available = (UCHAR*)tail;
12166 while(p > (UCHAR*)tail)
12167 {
12168
12169 /* Get len and cnt. */
12170 len = *((USHORT*)(p - 2));
12171 cnt = *((USHORT*)(p - 4));
12172 start = p - len;
12173
12174 if((len == memory_len) &&
12175 (((add_name == NX_TRUE) &&
12176 (!_nx_mdns_name_match(start, memory_ptr, memory_size))) ||
12177 ((add_name == NX_FALSE) &&
12178 (!memcmp(start, memory_ptr, memory_size)))))
12179 {
12180
12181 /* The same string exists in the string table. */
12182 if(insert_ptr)
12183 *insert_ptr = start;
12184
12185 if(find_string == NX_FALSE)
12186 {
12187
12188 /* Increase the use count CNT. */
12189 cnt++;
12190 *((USHORT*)(p - 4)) = cnt;
12191 }
12192
12193 return(NX_MDNS_SUCCESS);
12194 }
12195
12196 /* This slot is not being used. The size of the slot is a smaller
12197 fit for this string. */
12198 if((cnt == 0) && (len >= memory_len) && (len < min_len))
12199 {
12200
12201 /* This place is better to insert. */
12202 available = p;
12203 min_len = len;
12204 }
12205
12206 /* Move to the next string. */
12207 p = start;
12208 }
12209
12210 if(find_string == NX_TRUE)
12211 return(NX_MDNS_ERROR);
12212
12213 /* If we reach this point, the string needs to be added to the string table. */
12214 if(available == (UCHAR*)tail)
12215 {
12216
12217 /* Make sure the service cache still has room to add this string
12218 (without overwriting the RR area.) */
12219 if(((UCHAR*)tail - memory_len) < (UCHAR*)head )
12220 {
12221
12222 /* This service cache does not have room for the string table to grow. */
12223 /* Invoke user-installed cache full notify function .*/
12224 if(mdns_ptr -> nx_mdns_cache_full_notify)
12225 {
12226
12227 /* Calculate the fragment size, RR size, string size, Head and Tail. */
12228 if(cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12229 {
12230 used_cache_size = mdns_ptr -> nx_mdns_local_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_local_string_bytes + 2 * sizeof(ULONG);
12231 }
12232 else
12233 {
12234 used_cache_size = mdns_ptr -> nx_mdns_peer_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_peer_string_bytes + 2 * sizeof(ULONG);
12235 }
12236
12237 /* Check the cache. */
12238 if ((used_cache_size + memory_len) <= cache_size)
12239 {
12240 (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FRAGMENTED, cache_type);
12241 }
12242 else
12243 {
12244 (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FULL, cache_type);
12245 }
12246 }
12247
12248 /* The buffer is full. */
12249 return(NX_MDNS_CACHE_ERROR);
12250 }
12251
12252 /* Update TAIL. */
12253 *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)(available - memory_len);
12254
12255 }
12256 else if(memory_len < min_len)
12257 {
12258
12259 /* Set the LEN for remaining space. */
12260 *((USHORT*)(available - 2 - memory_len)) = (USHORT)(min_len - memory_len);
12261 }
12262
12263 /* Set LEN and CNT. */
12264 *((USHORT*)(available - 2)) = (USHORT)memory_len;
12265 *((USHORT*)(available - 4)) = 1;
12266
12267 /* Clear last 4 bytes. */
12268 *((ULONG*)(available - 8)) = 0;
12269
12270 /* Insert string to cache. */
12271 memcpy(available - memory_len, memory_ptr, memory_size); /* Use case of memcpy is verified. */
12272
12273 /* Set end character 0. */
12274 *(available - memory_len + memory_size) = 0;
12275
12276
12277 /* Check the type. */
12278 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12279 {
12280
12281 /* Increase the count and bytes. */
12282 mdns_ptr -> nx_mdns_local_string_count ++;
12283 mdns_ptr -> nx_mdns_local_string_bytes += memory_len;
12284 }
12285 else
12286 {
12287
12288 /* Increase the count and bytes. */
12289 mdns_ptr -> nx_mdns_peer_string_count ++;
12290 mdns_ptr -> nx_mdns_peer_string_bytes += memory_len;
12291 }
12292
12293 if(insert_ptr)
12294 *insert_ptr = available - memory_len;
12295
12296 return(NX_MDNS_SUCCESS);
12297 }
12298
12299
12300 /**************************************************************************/
12301 /* */
12302 /* FUNCTION RELEASE */
12303 /* */
12304 /* _nx_mdns_cache_delete_string PORTABLE C */
12305 /* 6.1 */
12306 /* AUTHOR */
12307 /* */
12308 /* Yuxin Zhou, Microsoft Corporation */
12309 /* */
12310 /* DESCRIPTION */
12311 /* */
12312 /* This function deletes the mDNS string from the record buffer. */
12313 /* */
12314 /* INPUT */
12315 /* */
12316 /* mdns_ptr Pointer to mDNS instance */
12317 /* cache_type Cache type: local or peer */
12318 /* string_ptr Pointer to the string */
12319 /* string_len The length of string */
12320 /* */
12321 /* OUTPUT */
12322 /* */
12323 /* status Completion status */
12324 /* */
12325 /* CALLS */
12326 /* */
12327 /* None */
12328 /* */
12329 /* CALLED BY */
12330 /* */
12331 /* _nx_mdns_rr_a_aaaa_add Add A/AAAA resource record */
12332 /* _nx_mdns_rr_ptr_add Add PTR resource record */
12333 /* _nx_mdns_rr_srv_add Add SRV resource record */
12334 /* _nx_mdns_rr_txt_add Add TXT resource record */
12335 /* _nx_mdns_query Send query */
12336 /* _nx_mdns_conflict_process Process the conflict */
12337 /* _nx_mdns_cache_add_resource_record Add the resource record */
12338 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
12339 /* _nx_mdns_packet_rr_process Process resource record */
12340 /* */
12341 /* RELEASE HISTORY */
12342 /* */
12343 /* DATE NAME DESCRIPTION */
12344 /* */
12345 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12346 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12347 /* resulting in version 6.1 */
12348 /* */
12349 /**************************************************************************/
_nx_mdns_cache_delete_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * string_ptr,UINT string_len)12350 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len)
12351 {
12352
12353 UCHAR *cache_ptr;
12354 UINT cache_size;
12355 ULONG *tail;
12356 ULONG *end;
12357 USHORT cnt;
12358
12359
12360 /* Check the cache type. */
12361 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12362 {
12363 cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12364 cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12365 }
12366 else
12367 {
12368 cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12369 cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12370 }
12371
12372 /* Check cache pointer and cache size. */
12373 if ((cache_ptr == NX_NULL) || (cache_size == 0))
12374 {
12375 return(NX_MDNS_ERROR);
12376 }
12377
12378 /* Validate input parameter. */
12379 if(string_ptr == NX_NULL)
12380 return(NX_MDNS_PARAM_ERROR);
12381
12382 /* Check if input the string length. */
12383 if (string_len == 0)
12384 {
12385
12386 /* Check string length. */
12387 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12388 {
12389 return(NX_MDNS_DATA_SIZE_ERROR);
12390 }
12391 }
12392
12393 /* Add the length of CNT and LEN fields. */
12394 /* Also make the total length 4 bytes align. */
12395 string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12396
12397 end = (ULONG*)((UCHAR*)string_ptr + string_len);
12398
12399 /* Get tail. */
12400
12401 /* Validate the string table. */
12402 tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12403 if(end > tail)
12404 {
12405
12406 /* The end of string exceeds cache_ptr. */
12407 return(NX_MDNS_CACHE_ERROR);
12408 }
12409 tail = (ULONG*)(*tail);
12410 if((UCHAR*)string_ptr < (UCHAR*)tail)
12411 {
12412
12413 /* The end of string exceeds cache_ptr. */
12414 return(NX_MDNS_CACHE_ERROR);
12415 }
12416
12417 /* Decrease the usage counter value. */
12418 cnt = *((USHORT*)((UCHAR*)end - 4));
12419 cnt--;
12420 *((USHORT*)((UCHAR*)end - 4)) = cnt;
12421
12422 /* Clear the memory if cnt is zero. */
12423 if(cnt == 0)
12424 {
12425 memset(string_ptr, 0, string_len - 2);
12426
12427 /* Check the type. */
12428 if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12429 {
12430
12431 /* Increase the count and bytes. */
12432 mdns_ptr -> nx_mdns_local_string_count --;
12433 mdns_ptr -> nx_mdns_local_string_bytes -= string_len;
12434 }
12435 else
12436 {
12437
12438 /* Increase the count and bytes. */
12439 mdns_ptr -> nx_mdns_peer_string_count --;
12440 mdns_ptr -> nx_mdns_peer_string_bytes -= string_len;
12441 }
12442
12443 /* Update the tail pointer if the string at the tail is deleted. */
12444 if(string_ptr == tail)
12445 {
12446 tail = end;
12447
12448 while((end < ((ULONG*)cache_ptr + (cache_size >> 2) - 1)))
12449 {
12450
12451 /* Set the string pt and string length. */
12452 string_ptr = end;
12453
12454 /* Check string length. */
12455 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12456 {
12457 return(NX_MDNS_DATA_SIZE_ERROR);
12458 }
12459
12460 /* Check the string length. */
12461 if(string_len == 0)
12462 {
12463
12464 /* This slot is cleared. */
12465 while(*((ULONG*)string_ptr) == 0)
12466 string_ptr = (UCHAR*)string_ptr + 4;
12467
12468 end = (ULONG*)string_ptr + 1;
12469 cnt = *((USHORT*)string_ptr);
12470 }
12471 else
12472 {
12473
12474 /* Make the length 4 bytes align and add the length of CNT and LEN fields. */
12475 string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12476
12477 end = (ULONG*)((UCHAR*)string_ptr + string_len);
12478 cnt = *((USHORT*)((UCHAR*)end - 4));
12479 }
12480
12481 /* Check whether this slot is never referenced. */
12482 if(cnt == 0)
12483 tail = end;
12484 else
12485 break;
12486 }
12487 *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)tail;
12488 }
12489 }
12490
12491 return(NX_MDNS_SUCCESS);
12492 }
12493
12494
12495 /**************************************************************************/
12496 /* */
12497 /* FUNCTION RELEASE */
12498 /* */
12499 /* _nx_mdns_cache_delete_rr_string PORTABLE C */
12500 /* 6.1 */
12501 /* AUTHOR */
12502 /* */
12503 /* Yuxin Zhou, Microsoft Corporation */
12504 /* */
12505 /* DESCRIPTION */
12506 /* */
12507 /* This function deletes the mDNS string from the record buffer. */
12508 /* */
12509 /* INPUT */
12510 /* */
12511 /* mdns_ptr Pointer to mDNS instance */
12512 /* cache_type Cache type: local or peer */
12513 /* string_ptr Pointer to the string */
12514 /* */
12515 /* OUTPUT */
12516 /* */
12517 /* None */
12518 /* */
12519 /* CALLS */
12520 /* */
12521 /* _nx_mdns_cache_delete_string Delete the string from cache */
12522 /* */
12523 /* CALLED BY */
12524 /* */
12525 /* _nx_mdns_cache_add_resource_record Add the resource record */
12526 /* _nx_mdns_cache_delete_resource_record Delete the resource record */
12527 /* */
12528 /* RELEASE HISTORY */
12529 /* */
12530 /* DATE NAME DESCRIPTION */
12531 /* */
12532 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12533 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12534 /* resulting in version 6.1 */
12535 /* */
12536 /**************************************************************************/
_nx_mdns_cache_delete_rr_string(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_rr)12537 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr)
12538 {
12539
12540 /* Delete the name strings. */
12541 _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_name, 0);
12542
12543 /* Check if need to release the rdata string. */
12544 if (record_rr -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
12545 {
12546
12547 if (((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
12548 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12549 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
12550 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12551 ||
12552 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
12553 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12554 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12555 ||
12556 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_CNAME) ||
12557 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NS) ||
12558 (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_MX)
12559 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES */
12560 ) &&
12561 (record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
12562 {
12563
12564 /* Delete the same strings. */
12565 _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);
12566 }
12567 }
12568 }
12569
12570
12571 #ifndef NX_MDNS_DISABLE_SERVER
12572 /**************************************************************************/
12573 /* */
12574 /* FUNCTION RELEASE */
12575 /* */
12576 /* _nx_mdns_additional_resource_record_find PORTABLE C */
12577 /* 6.1 */
12578 /* AUTHOR */
12579 /* */
12580 /* Yuxin Zhou, Microsoft Corporation */
12581 /* */
12582 /* DESCRIPTION */
12583 /* */
12584 /* This function find the mDNS additional resource record. */
12585 /* */
12586 /* INPUT */
12587 /* */
12588 /* mdns_ptr Pointer to mDNS instance */
12589 /* record_ptr Pointer to record instance */
12590 /* */
12591 /* OUTPUT */
12592 /* */
12593 /* status Completion status */
12594 /* */
12595 /* CALLS */
12596 /* */
12597 /* None */
12598 /* */
12599 /* CALLED BY */
12600 /* */
12601 /* _nx_mdns_response_send Send response message */
12602 /* */
12603 /* RELEASE HISTORY */
12604 /* */
12605 /* DATE NAME DESCRIPTION */
12606 /* */
12607 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12608 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12609 /* resulting in version 6.1 */
12610 /* */
12611 /**************************************************************************/
_nx_mdns_additional_resource_record_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12612 UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12613 {
12614
12615 ULONG *head;
12616 NX_MDNS_RR *p;
12617
12618 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12619 head = (ULONG*)(*head);
12620
12621 /* Find the additional resource records according to the type. */
12622 switch (record_ptr -> nx_mdns_rr_type )
12623 {
12624
12625 case NX_MDNS_RR_TYPE_A:
12626 case NX_MDNS_RR_TYPE_AAAA:
12627 {
12628
12629 /* Recommends AAAA records in the additional section when responding
12630 to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51. */
12631 _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_interface_index);
12632
12633 break;
12634 }
12635
12636 case NX_MDNS_RR_TYPE_PTR:
12637 {
12638
12639 /* Find the additional resource record. */
12640 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12641 {
12642
12643 /* Check the interface. */
12644 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12645 continue;
12646
12647 /* The SRV record(s) named in the PTR rdata.
12648 The TXT record(s) named in the PTR rdata.
12649 All address records (type "A" and "AAAA") named in the SRV rdata. RFC6763, Section12.1, Page30.*/
12650
12651 /* The SRV records named in the PTR rdata */
12652 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
12653 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12654 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12655 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12656 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12657 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12658 {
12659
12660 /* Set the flag to add this resource records into additional records. */
12661 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12662
12663 /* All address records (type "A" and "AAAA") named in the SRV rdata */
12664 _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);
12665 }
12666
12667 /* The TXT records named in the PTR rdata */
12668 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12669 (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)) &&
12670 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12671 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12672 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12673 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12674 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12675 {
12676
12677 /* Set the flag to add this resource records into additional records. */
12678 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12679 }
12680 }
12681
12682 break;
12683 }
12684
12685 case NX_MDNS_RR_TYPE_SRV:
12686 case NX_MDNS_RR_TYPE_TXT:
12687 {
12688
12689 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12690 /* Find the additional resource record. */
12691 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12692 {
12693
12694 /* Check the interface. */
12695 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12696 continue;
12697
12698 /* The NSEC records named same as SRV/TXT name. */
12699 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
12700 (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_name) &&
12701 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12702 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12703 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12704 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12705 {
12706
12707 /* Set the flag to add this resource records into additional records. */
12708 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12709 }
12710 }
12711 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
12712
12713 /* All address records (type "A" and "AAAA") named in the SRV rdata */
12714 if (record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
12715 _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);
12716 break;
12717 }
12718 }
12719
12720 return(NX_MDNS_SUCCESS);
12721 }
12722
12723
12724 /**************************************************************************/
12725 /* */
12726 /* FUNCTION RELEASE */
12727 /* */
12728 /* _nx_mdns_additional_a_aaaa_find PORTABLE C */
12729 /* 6.1 */
12730 /* AUTHOR */
12731 /* */
12732 /* Yuxin Zhou, Microsoft Corporation */
12733 /* */
12734 /* DESCRIPTION */
12735 /* */
12736 /* This function find the mDNS additional A/AAAA resource record. */
12737 /* */
12738 /* INPUT */
12739 /* */
12740 /* mdns_ptr Pointer to mDNS instance */
12741 /* record_ptr Pointer to record instance */
12742 /* */
12743 /* OUTPUT */
12744 /* */
12745 /* status Completion status */
12746 /* */
12747 /* CALLS */
12748 /* */
12749 /* None */
12750 /* */
12751 /* CALLED BY */
12752 /* */
12753 /* _nx_mdns_additional_resource_record_find */
12754 /* Find additional record */
12755 /* */
12756 /* RELEASE HISTORY */
12757 /* */
12758 /* DATE NAME DESCRIPTION */
12759 /* */
12760 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12761 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12762 /* resulting in version 6.1 */
12763 /* */
12764 /**************************************************************************/
_nx_mdns_additional_a_aaaa_find(NX_MDNS * mdns_ptr,UCHAR * name,UINT interface_index)12765 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index)
12766 {
12767
12768 ULONG *head;
12769 NX_MDNS_RR *p;
12770
12771 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12772 head = (ULONG*)(*head);
12773
12774 /* Recommends AAAA records in the additional section when responding
12775 to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51. */
12776 for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12777 {
12778
12779 /* Check the interface index. */
12780 if (p -> nx_mdns_rr_interface_index != interface_index)
12781 continue;
12782
12783 /* Find the "A" records. */
12784 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
12785 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA ||
12786 (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))) &&
12787 (p -> nx_mdns_rr_name == name) &&
12788 ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12789 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12790 (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12791 (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12792 {
12793
12794 /* Set the flag to add this resource records into additional records. */
12795 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12796 }
12797 }
12798 }
12799 #endif /* NX_MDNS_DISABLE_SERVER */
12800
12801
12802 #ifndef NX_MDNS_DISABLE_CLIENT
12803 /**************************************************************************/
12804 /* */
12805 /* FUNCTION RELEASE */
12806 /* */
12807 /* _nx_mdns_known_answer_find PORTABLE C */
12808 /* 6.1 */
12809 /* AUTHOR */
12810 /* */
12811 /* Yuxin Zhou, Microsoft Corporation */
12812 /* */
12813 /* DESCRIPTION */
12814 /* */
12815 /* This function finds the mDNS known answer. */
12816 /* */
12817 /* INPUT */
12818 /* */
12819 /* mdns_ptr Pointer to mDNS instance */
12820 /* record_ptr Pointer to record instance */
12821 /* */
12822 /* OUTPUT */
12823 /* */
12824 /* status Completion status */
12825 /* */
12826 /* CALLS */
12827 /* */
12828 /* None */
12829 /* */
12830 /* CALLED BY */
12831 /* */
12832 /* _nx_mdns_query_send Send query message */
12833 /* _nx_mdns_packet_process Process mDNS packet */
12834 /* */
12835 /* RELEASE HISTORY */
12836 /* */
12837 /* DATE NAME DESCRIPTION */
12838 /* */
12839 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12840 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12841 /* resulting in version 6.1 */
12842 /* */
12843 /**************************************************************************/
_nx_mdns_known_answer_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12844 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12845 {
12846
12847 UINT status = NX_MDNS_NO_KNOWN_ANSWER;
12848 ULONG *head, *tail;
12849 NX_MDNS_RR *p;
12850 UINT i;
12851 UINT name_length;
12852 #ifndef NX_MDNS_DISABLE_SERVER
12853 UINT cache_count = 2;
12854 #else
12855 UINT cache_count = 1;
12856 #endif
12857
12858 /* Check string length. */
12859 if (_nx_utility_string_length_check((CHAR *)(record_ptr -> nx_mdns_rr_name), &name_length, NX_MDNS_NAME_MAX))
12860 {
12861 return(NX_MDNS_DATA_SIZE_ERROR);
12862 }
12863
12864 /* Loop to find the known answer in cache. */
12865 for (i = 0; i < cache_count; i++)
12866 {
12867
12868 /* Set the pointer. */
12869 if (i == 0)
12870 {
12871 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12872 }
12873 #ifndef NX_MDNS_DISABLE_SERVER
12874 else
12875 {
12876 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12877 }
12878 #endif /* NX_MDNS_DISABLE_SERVER */
12879 tail = (ULONG*)(*head);
12880
12881 /* Whether this mDNS message response to query. */
12882 for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
12883 {
12884
12885 /* Check the state. */
12886 if(p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_VALID)
12887 continue;
12888
12889 /* Check the interface index. */
12890 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12891 continue;
12892
12893 /* Check whether the Known Answer record it is. */
12894 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_name, name_length)) &&
12895 (p -> nx_mdns_rr_class == record_ptr -> nx_mdns_rr_class))
12896 {
12897
12898 if ((record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) ||
12899 (p -> nx_mdns_rr_type == record_ptr -> nx_mdns_rr_type))
12900 {
12901
12902 /* Set the additional flag. */
12903 p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_KNOWN_ANSWER;
12904
12905 /* Yes, find the known answer. */
12906 status = NX_MDNS_SUCCESS;
12907 }
12908 }
12909 }
12910 }
12911
12912 return(status);
12913 }
12914 #endif /* NX_MDNS_DISABLE_CLIENT */
12915
12916
12917 #ifndef NX_MDNS_DISABLE_CLIENT
12918 /**************************************************************************/
12919 /* */
12920 /* FUNCTION RELEASE */
12921 /* */
12922 /* _nx_mdns_query_check PORTABLE C */
12923 /* 6.1.11 */
12924 /* AUTHOR */
12925 /* */
12926 /* Yuxin Zhou, Microsoft Corporation */
12927 /* */
12928 /* DESCRIPTION */
12929 /* */
12930 /* This function checks whether mDNS querier already has one Unique */
12931 /* record in the local buffer/remote buffer or one same query in the */
12932 /* remote buffer. */
12933 /* */
12934 /* INPUT */
12935 /* */
12936 /* mdns_ptr Pointer to mDNS instance */
12937 /* name The resource record name */
12938 /* type The resource record type */
12939 /* interface_index The interface index */
12940 /* */
12941 /* OUTPUT */
12942 /* */
12943 /* status Completion status */
12944 /* */
12945 /* CALLS */
12946 /* */
12947 /* None */
12948 /* */
12949 /* CALLED BY */
12950 /* */
12951 /* _nx_mdns_query Send the query */
12952 /* */
12953 /* RELEASE HISTORY */
12954 /* */
12955 /* DATE NAME DESCRIPTION */
12956 /* */
12957 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12958 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12959 /* resulting in version 6.1 */
12960 /* 04-25-2022 Yuxin Zhou Modified comment(s), and */
12961 /* corrected the random value, */
12962 /* resulting in version 6.1.11 */
12963 /* */
12964 /**************************************************************************/
_nx_mdns_query_check(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT one_shot,NX_MDNS_RR ** search_rr,UINT interface_index)12965 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)
12966 {
12967
12968 ULONG *head;
12969 NX_MDNS_RR *p;
12970 UCHAR i;
12971 UCHAR same_query = NX_FALSE;
12972 NX_MDNS_RR *rr = NX_NULL;
12973 UCHAR srv_flag = NX_FALSE;
12974 UCHAR txt_flag = NX_FALSE;
12975 UINT name_length;
12976
12977
12978 /* Check string length. */
12979 if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
12980 {
12981 return(NX_MDNS_DATA_SIZE_ERROR);
12982 }
12983
12984 for(i = 0; i < 2; i++)
12985 {
12986 if(i == NX_MDNS_CACHE_TYPE_LOCAL)
12987 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12988 else
12989 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12990
12991 if(head)
12992 {
12993 for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
12994 {
12995
12996 /* Check whether the resource record is valid. */
12997 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
12998 continue;
12999
13000 /* Check the interface index. */
13001 if (p -> nx_mdns_rr_interface_index != interface_index)
13002 continue;
13003
13004 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, name, name_length))
13005 {
13006 if ((p -> nx_mdns_rr_type == type) && (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
13007 {
13008
13009 /* Set the query. */
13010 same_query = NX_TRUE;
13011
13012 /* Record the RR potiner. */
13013 rr = p;
13014 }
13015
13016 /* Check the rr type. */
13017 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
13018 srv_flag = NX_TRUE;
13019 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT)
13020 txt_flag = NX_TRUE;
13021
13022 if ((p -> nx_mdns_rr_type == type) ||
13023 ((type == NX_MDNS_RR_TYPE_ALL) && (srv_flag == NX_TRUE) && (txt_flag == NX_TRUE)))
13024 {
13025 if (search_rr)
13026 *search_rr = p;
13027
13028 /* Check the query type. */
13029 if (one_shot == NX_TRUE)
13030 return(NX_MDNS_EXIST_SHARED_RR);
13031
13032 if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
13033 return(NX_MDNS_EXIST_UNIQUE_RR);
13034 }
13035 }
13036 }
13037 }
13038 }
13039
13040 /* Check the same query. */
13041 if (same_query == NX_TRUE)
13042 {
13043
13044 /* A multicast DNS querier should also delay the first query of the series by
13045 a randomly chosen amount in the range 20-120ms. */
13046 rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
13047 rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
13048
13049 /* Set the mDNS timer. */
13050 _nx_mdns_timer_set(mdns_ptr, rr, rr -> nx_mdns_rr_timer_count);
13051
13052 return (NX_MDNS_EXIST_SAME_QUERY);
13053 }
13054
13055 /* Return a successful status. */
13056 return(NX_SUCCESS);
13057 }
13058
13059
13060 /**************************************************************************/
13061 /* */
13062 /* FUNCTION RELEASE */
13063 /* */
13064 /* _nx_mdns_query_cleanup PORTABLE C */
13065 /* 6.1 */
13066 /* AUTHOR */
13067 /* */
13068 /* Yuxin Zhou, Microsoft Corporation */
13069 /* */
13070 /* DESCRIPTION */
13071 /* */
13072 /* This function processes mDNS One-shot query timeout and thread */
13073 /* terminate actions that require the mDNS data structures to be */
13074 /* cleaned up. */
13075 /* */
13076 /* INPUT */
13077 /* */
13078 /* thread_ptr Pointer to suspended thread's */
13079 /* control block */
13080 /* */
13081 /* OUTPUT */
13082 /* */
13083 /* None */
13084 /* */
13085 /* CALLS */
13086 /* */
13087 /* _tx_thread_system_resume Resume thread service */
13088 /* */
13089 /* CALLED BY */
13090 /* */
13091 /* _tx_thread_timeout Thread timeout processing */
13092 /* _tx_thread_terminate Thread terminate processing */
13093 /* */
13094 /* RELEASE HISTORY */
13095 /* */
13096 /* DATE NAME DESCRIPTION */
13097 /* */
13098 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13099 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13100 /* resulting in version 6.1 */
13101 /* */
13102 /**************************************************************************/
_nx_mdns_query_cleanup(TX_THREAD * thread_ptr NX_CLEANUP_PARAMETER)13103 VOID _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER)
13104 {
13105
13106 TX_INTERRUPT_SAVE_AREA
13107
13108 NX_MDNS *mdns_ptr;
13109
13110
13111 NX_CLEANUP_EXTENSION
13112
13113 /* Setup pointer to UDP socket control block. */
13114 mdns_ptr = (NX_MDNS *) thread_ptr -> tx_thread_suspend_control_block;
13115
13116 /* Disable interrupts to remove the suspended thread from the UDP socket. */
13117 TX_DISABLE
13118
13119 /* Determine if the cleanup is still required. */
13120 if ((thread_ptr -> tx_thread_suspend_cleanup) && (mdns_ptr) &&
13121 (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
13122 {
13123
13124 /* Yes, we still have thread suspension! */
13125
13126 /* Clear the suspension cleanup flag. */
13127 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
13128
13129 /* Remove the suspended thread from the list. */
13130
13131 /* See if this is the only suspended thread on the list. */
13132 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13133 {
13134
13135 /* Yes, the only suspended thread. */
13136
13137 /* Update the head pointer. */
13138 mdns_ptr -> nx_mdns_rr_receive_suspension_list = NX_NULL;
13139 }
13140 else
13141 {
13142
13143 /* At least one more thread is on the same suspension list. */
13144
13145 /* Update the list head pointer. */
13146 mdns_ptr -> nx_mdns_rr_receive_suspension_list = thread_ptr -> tx_thread_suspended_next;
13147
13148 /* Update the links of the adjacent threads. */
13149 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13150 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13151 }
13152
13153 /* Decrement the suspension count. */
13154 mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13155
13156 /* Now we need to determine if this cleanup is from a terminate, timeout,
13157 or from a wait abort. */
13158 if (thread_ptr -> tx_thread_state == TX_TCP_IP)
13159 {
13160
13161 /* Thread still suspended on the UDP socket. Setup return error status and
13162 resume the thread. */
13163
13164 /* Setup return status. */
13165 thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13166
13167 /* Temporarily disable preemption. */
13168 _tx_thread_preempt_disable++;
13169
13170 /* Restore interrupts. */
13171 TX_RESTORE
13172
13173 /* Resume the thread! Check for preemption even though we are executing
13174 from the system timer thread right now which normally executes at the
13175 highest priority. */
13176 _tx_thread_system_resume(thread_ptr);
13177
13178 /* Finished, just return. */
13179 return;
13180 }
13181 }
13182
13183 /* Restore interrupts. */
13184 TX_RESTORE
13185 }
13186
13187
13188 /**************************************************************************/
13189 /* */
13190 /* FUNCTION RELEASE */
13191 /* */
13192 /* _nx_mdns_query_thread_suspend PORTABLE C */
13193 /* 6.1 */
13194 /* AUTHOR */
13195 /* */
13196 /* Yuxin Zhou, Microsoft Corporation */
13197 /* */
13198 /* DESCRIPTION */
13199 /* */
13200 /* This function suspends a thread on a mDNS client query service */
13201 /* */
13202 /* INPUT */
13203 /* */
13204 /* suspension_list_head Pointer to the suspension list*/
13205 /* mutex_ptr Pointer to mutex to release */
13206 /* suspend_cleanup Suspension cleanup routine */
13207 /* wait_option Optional timeout value */
13208 /* */
13209 /* OUTPUT */
13210 /* */
13211 /* None */
13212 /* */
13213 /* CALLS */
13214 /* */
13215 /* tx_mutex_put Release protection */
13216 /* _tx_thread_system_suspend Suspend thread */
13217 /* */
13218 /* CALLED BY */
13219 /* */
13220 /* */
13221 /* RELEASE HISTORY */
13222 /* */
13223 /* DATE NAME DESCRIPTION */
13224 /* */
13225 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13226 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13227 /* resulting in version 6.1 */
13228 /* */
13229 /**************************************************************************/
_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)13230 VOID _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
13231 NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option)
13232 {
13233
13234 TX_INTERRUPT_SAVE_AREA
13235
13236 TX_THREAD *thread_ptr;
13237
13238
13239 /* Lockout interrupts. */
13240 TX_DISABLE
13241
13242 /* Pickup thread pointer. */
13243 thread_ptr = _tx_thread_current_ptr;
13244
13245 /* Setup suspension list. */
13246 if (*suspension_list_head)
13247 {
13248
13249 /* This list is not NULL, add current thread to the end. */
13250 thread_ptr -> tx_thread_suspended_next = *suspension_list_head;
13251 thread_ptr -> tx_thread_suspended_previous = (*suspension_list_head) -> tx_thread_suspended_previous;
13252 ((*suspension_list_head) -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr;
13253 (*suspension_list_head) -> tx_thread_suspended_previous = thread_ptr;
13254 }
13255 else
13256 {
13257
13258 /* No other threads are suspended. Setup the head pointer and
13259 just setup this threads pointers to itself. */
13260 *suspension_list_head = thread_ptr;
13261 thread_ptr -> tx_thread_suspended_next = thread_ptr;
13262 thread_ptr -> tx_thread_suspended_previous = thread_ptr;
13263 }
13264
13265 /* Setup return status. */
13266 thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13267
13268 /* Setup cleanup routine pointer. */
13269 thread_ptr -> tx_thread_suspend_cleanup = suspend_cleanup;
13270
13271 /* Setup cleanup information, i.e. this pool control block. */
13272 thread_ptr -> tx_thread_suspend_control_block = (void *)mdns_ptr;
13273
13274 /* Save the return RR pointer address as well. */
13275 thread_ptr -> tx_thread_additional_suspend_info = (void *)rr;
13276
13277 /* Increment the suspended thread count. */
13278 mdns_ptr -> nx_mdns_rr_receive_suspended_count++;
13279
13280 /* Set the state to suspended. */
13281 thread_ptr -> tx_thread_state = TX_TCP_IP;
13282
13283 /* Set the suspending flag. */
13284 thread_ptr -> tx_thread_suspending = TX_TRUE;
13285
13286 /* Temporarily disable preemption. */
13287 _tx_thread_preempt_disable++;
13288
13289 /* Save the timeout value. */
13290 thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
13291
13292 /* Restore interrupts. */
13293 TX_RESTORE
13294
13295 /* Call actual thread suspension routine. */
13296 _tx_thread_system_suspend(thread_ptr);
13297 }
13298
13299
13300 /**************************************************************************/
13301 /* */
13302 /* FUNCTION RELEASE */
13303 /* */
13304 /* _nx_mdns_query_thread_resume PORTABLE C */
13305 /* 6.1 */
13306 /* AUTHOR */
13307 /* */
13308 /* Yuxin Zhou, Microsoft Corporation */
13309 /* */
13310 /* DESCRIPTION */
13311 /* */
13312 /* This function resumes a thread suspended on a mDNS Client query */
13313 /* service. */
13314 /* */
13315 /* INPUT */
13316 /* */
13317 /* thread_ptr Pointer to suspended thread's */
13318 /* control block */
13319 /* */
13320 /* OUTPUT */
13321 /* */
13322 /* None */
13323 /* */
13324 /* CALLS */
13325 /* */
13326 /* _tx_thread_system_resume Resume thread service */
13327 /* */
13328 /* CALLED BY */
13329 /* */
13330 /* _tx_thread_timeout Thread timeout processing */
13331 /* _tx_thread_terminate Thread terminate processing */
13332 /* */
13333 /* RELEASE HISTORY */
13334 /* */
13335 /* DATE NAME DESCRIPTION */
13336 /* */
13337 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13338 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13339 /* resulting in version 6.1 */
13340 /* */
13341 /**************************************************************************/
_nx_mdns_query_thread_resume(TX_THREAD ** suspension_list_head,NX_MDNS * mdns_ptr,NX_MDNS_RR * rr)13342 VOID _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr)
13343 {
13344
13345 TX_INTERRUPT_SAVE_AREA
13346
13347 TX_THREAD *thread_ptr;
13348
13349
13350 /* Disable interrupts. */
13351 TX_DISABLE
13352
13353 /* Pickup the thread pointer. */
13354 thread_ptr = *suspension_list_head;
13355
13356 /* Determine if there still is a thread suspended. */
13357 if (thread_ptr)
13358 {
13359
13360 /* Remove the suspended thread from the list. */
13361
13362 /* See if this is the only suspended thread on the list. */
13363 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13364 {
13365
13366 /* Yes, the only suspended thread. */
13367
13368 /* Update the head pointer. */
13369 *suspension_list_head = TX_NULL;
13370 }
13371 else
13372 {
13373
13374 /* At least one more thread is on the same expiration list. */
13375
13376 /* Update the list head pointer. */
13377 *suspension_list_head = thread_ptr -> tx_thread_suspended_next;
13378
13379 /* Update the links of the adjacent threads. */
13380 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13381 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13382 }
13383
13384 /* Decrement the suspension count. */
13385 mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13386
13387 /* Prepare for resumption of the first thread. */
13388
13389 /* Clear cleanup routine to avoid timeout. */
13390 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
13391
13392 /* Temporarily disable preemption. */
13393 _tx_thread_preempt_disable++;
13394
13395 /* Return this block pointer to the suspended thread waiting for
13396 a block. */
13397 *((NX_MDNS_RR **) thread_ptr -> tx_thread_additional_suspend_info) = rr;
13398
13399 /* Restore interrupts. */
13400 TX_RESTORE
13401
13402 /* Put return status into the thread control block. */
13403 thread_ptr -> tx_thread_suspend_status = NX_MDNS_SUCCESS;
13404
13405 /* Resume thread. */
13406 _tx_thread_system_resume(thread_ptr);
13407 }
13408 else
13409 {
13410
13411 /* Restore interrupts. */
13412 TX_RESTORE
13413 }
13414 }
13415
13416
13417 /**************************************************************************/
13418 /* */
13419 /* FUNCTION RELEASE */
13420 /* */
13421 /* _nx_mdns_service_mask_match PORTABLE C */
13422 /* 6.1 */
13423 /* AUTHOR */
13424 /* */
13425 /* Yuxin Zhou, Microsoft Corporation */
13426 /* */
13427 /* DESCRIPTION */
13428 /* */
13429 /* This function matchs the mDNS service mask to listen the service */
13430 /* and notify the application, or ignore the service. */
13431 /* */
13432 /* INPUT */
13433 /* */
13434 /* mdns_ptr Pointer to mDNS instance */
13435 /* service_type Pointer to Service type */
13436 /* service_mask The Service mask */
13437 /* */
13438 /* OUTPUT */
13439 /* */
13440 /* status Completion status */
13441 /* */
13442 /* CALLS */
13443 /* */
13444 /* tx_mutex_get Get the mDNS mutex */
13445 /* tx_mutex_put Put the mDNS mutex */
13446 /* */
13447 /* CALLED BY */
13448 /* */
13449 /* Application Code */
13450 /* */
13451 /* RELEASE HISTORY */
13452 /* */
13453 /* DATE NAME DESCRIPTION */
13454 /* */
13455 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13456 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13457 /* resulting in version 6.1 */
13458 /* */
13459 /**************************************************************************/
_nx_mdns_service_mask_match(NX_MDNS * mdns_ptr,UCHAR * service_type,ULONG service_mask)13460 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask)
13461 {
13462
13463 UINT i;
13464 UINT found;
13465 ULONG mask;
13466 UINT type_length;
13467
13468
13469 NX_PARAMETER_NOT_USED(mdns_ptr);
13470
13471 /* Initialize the parameters. */
13472 i = 0;
13473 found = 0;
13474 mask = 0x00000001;
13475
13476 /* Compare the service type. */
13477 while (nx_mdns_service_types[i])
13478 {
13479
13480 /* Check string length. */
13481 if (_nx_utility_string_length_check((CHAR *)nx_mdns_service_types[i], &type_length, NX_MDNS_TYPE_MAX))
13482 {
13483 return(NX_MDNS_DATA_SIZE_ERROR);
13484 }
13485
13486 /* Find the same service type. */
13487 if (!_nx_mdns_name_match(service_type, (UCHAR *)(nx_mdns_service_types[i]), type_length))
13488 {
13489 found = 1;
13490 break;
13491 }
13492 i ++;
13493 }
13494
13495 /* Check the result. */
13496 if (found)
13497 {
13498
13499 /* Check service mask. */
13500 if (service_mask & (mask << i))
13501 {
13502 return(NX_MDNS_SUCCESS);
13503 }
13504 }
13505
13506 /* Return status. */
13507 return(NX_MDNS_SERVICE_TYPE_MISMATCH);
13508 }
13509 #endif /* NX_MDNS_DISABLE_CLIENT */
13510
13511
13512 /**************************************************************************/
13513 /* */
13514 /* FUNCTION RELEASE */
13515 /* */
13516 /* _nx_mdns_name_match PORTABLE C */
13517 /* 6.1 */
13518 /* AUTHOR */
13519 /* */
13520 /* Yuxin Zhou, Microsoft Corporation */
13521 /* */
13522 /* DESCRIPTION */
13523 /* */
13524 /* This function name string match, the lowercase letters "a" to "z" */
13525 /* match their uppercase equivalents "A" to "Z". */
13526 /* */
13527 /* INPUT */
13528 /* */
13529 /* ptr Pointer to destination */
13530 /* name Source name string */
13531 /* */
13532 /* OUTPUT */
13533 /* */
13534 /* status Completion status */
13535 /* */
13536 /* CALLS */
13537 /* */
13538 /* None */
13539 /* */
13540 /* CALLED BY */
13541 /* */
13542 /* _nx_mdns_packet_rr_add Add the RR into packet */
13543 /* */
13544 /* RELEASE HISTORY */
13545 /* */
13546 /* DATE NAME DESCRIPTION */
13547 /* */
13548 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13549 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13550 /* resulting in version 6.1 */
13551 /* */
13552 /**************************************************************************/
_nx_mdns_name_match(UCHAR * src,UCHAR * dst,UINT length)13553 static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length)
13554 {
13555
13556 UINT index = 0;
13557
13558
13559 /* Check the name. */
13560 while (*dst != '\0')
13561 {
13562 if((*src) != (*dst))
13563 {
13564 if((((*src) | 0x20) >= 'a') && (((*src) | 0x20) <= 'z'))
13565 {
13566 /* Match the characters, case in-sensitive. */
13567 if(((*src) | 0x20) != ((*dst) | 0x20))
13568 return(NX_MDNS_NAME_MISMATCH);
13569 }
13570 else
13571 {
13572 return(NX_MDNS_NAME_MISMATCH);
13573 }
13574 }
13575 src ++;
13576 dst ++;
13577 index ++;
13578 }
13579
13580 /* Check the scan length. */
13581 if (index != length)
13582 {
13583 return (NX_MDNS_NAME_MISMATCH);
13584 }
13585
13586 /* Return success. */
13587 return(NX_MDNS_SUCCESS);
13588 }
13589
13590
13591 /**************************************************************************/
13592 /* */
13593 /* FUNCTION RELEASE */
13594 /* */
13595 /* _nx_mdns_txt_string_encode PORTABLE C */
13596 /* 6.1 */
13597 /* AUTHOR */
13598 /* */
13599 /* Yuxin Zhou, Microsoft Corporation */
13600 /* */
13601 /* DESCRIPTION */
13602 /* */
13603 /* This function encodes the txt string and adds the txt string into */
13604 /* packet.the TXT records are formatted in a "key=value" notation */
13605 /* with ";" acting as separator when more then one key is available. */
13606 /* */
13607 /* INPUT */
13608 /* */
13609 /* ptr Pointer to destination */
13610 /* name Source name string */
13611 /* */
13612 /* OUTPUT */
13613 /* */
13614 /* status Completion status */
13615 /* */
13616 /* CALLS */
13617 /* */
13618 /* None */
13619 /* */
13620 /* CALLED BY */
13621 /* */
13622 /* _nx_mdns_packet_rr_add Add the RR into packet */
13623 /* */
13624 /* RELEASE HISTORY */
13625 /* */
13626 /* DATE NAME DESCRIPTION */
13627 /* */
13628 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13629 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13630 /* resulting in version 6.1 */
13631 /* */
13632 /**************************************************************************/
_nx_mdns_txt_string_encode(UCHAR * ptr,UCHAR * txt)13633 static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *txt)
13634 {
13635
13636 UCHAR *length;
13637 UINT count = 1;
13638
13639
13640 /* Point to the first character position in the buffer. This will point
13641 to the length of the following name. */
13642 length = ptr++;
13643
13644 /* Default the length to zero. */
13645 *length = 0;
13646
13647 /* Move through string, copying bytes and updating length.
13648 Whenever a "." is found, start a new string by updating the
13649 pointer to the length and setting the length to zero. */
13650 while (*txt)
13651 {
13652
13653 /* Is a dot been found? */
13654 if (*txt == ';')
13655 {
13656
13657
13658 /* Yes, setup a new length pointer. */
13659 length = ptr++;
13660
13661 /* Default the length to zero. */
13662 *length = 0;
13663 txt++;
13664 }
13665 else
13666 {
13667
13668 /* Copy a character to the destination. */
13669 *ptr++ = *txt++;
13670
13671 /* Adjust the length of the current segment. */
13672 (*length)++;
13673 }
13674
13675 /* Increment the total count here. */
13676 count++;
13677 }
13678
13679 /* Return the count. */
13680 return(count);
13681 }
13682
13683
13684 /**************************************************************************/
13685 /* */
13686 /* FUNCTION RELEASE */
13687 /* */
13688 /* _nx_mdns_txt_string_decode PORTABLE C */
13689 /* 6.1.3 */
13690 /* AUTHOR */
13691 /* */
13692 /* Yuxin Zhou, Microsoft Corporation */
13693 /* */
13694 /* DESCRIPTION */
13695 /* */
13696 /* This function decode the txt string and adds the txt string into */
13697 /* buffer.the TXT records are formatted in a "key=value" notation */
13698 /* with ";" acting as separator when more then one key is available. */
13699 /* */
13700 /* INPUT */
13701 /* */
13702 /* data Pointer to buffer to decode */
13703 /* data_length The length of data */
13704 /* buffer Pointer to decoded data */
13705 /* size Size of data buffer to decode */
13706 /* */
13707 /* OUTPUT */
13708 /* */
13709 /* status Completion status */
13710 /* */
13711 /* CALLS */
13712 /* */
13713 /* None */
13714 /* */
13715 /* CALLED BY */
13716 /* */
13717 /* _nx_mdns_packet_process Process mDNS packet */
13718 /* _nx_mdns_packet_rr_process Process resource record */
13719 /* */
13720 /* RELEASE HISTORY */
13721 /* */
13722 /* DATE NAME DESCRIPTION */
13723 /* */
13724 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13725 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13726 /* resulting in version 6.1 */
13727 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
13728 /* buffer length verification, */
13729 /* resulting in version 6.1.3 */
13730 /* */
13731 /**************************************************************************/
_nx_mdns_txt_string_decode(UCHAR * data,UINT data_length,UCHAR * buffer,UINT size)13732 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size)
13733 {
13734
13735
13736 /* Check the buffer size. */
13737 if (data_length >= size)
13738 {
13739 return (NX_MDNS_CACHE_ERROR);
13740 }
13741
13742 /* decode the data. */
13743 while (data_length)
13744 {
13745
13746 UINT labelSize = *data++;
13747
13748 /* Is this a compression pointer or a count. */
13749 if (labelSize <= NX_MDNS_LABEL_MAX)
13750 {
13751
13752 /* Simple count, check for space and copy the label. */
13753 while ((labelSize > 0) && (data_length > 1))
13754 {
13755
13756 *buffer++ = *data++;
13757 labelSize--;
13758 data_length--;
13759 }
13760
13761 /* Now add the ';' */
13762 *buffer++ = ';';
13763 data_length--;
13764 }
13765 else
13766 {
13767 return(NX_MDNS_EXCEED_MAX_LABEL);
13768 }
13769 }
13770
13771 /* Done copying the data, set the last . to a trailing null */
13772 if (*(buffer - 1) == ';')
13773 {
13774
13775 buffer--;
13776 }
13777
13778 /* Null terminate name. */
13779 *buffer = '\0';
13780
13781 /* Return name size. */
13782 return(NX_MDNS_SUCCESS);
13783 }
13784
13785
13786 /**************************************************************************/
13787 /* */
13788 /* FUNCTION RELEASE */
13789 /* */
13790 /* _nx_mdns_name_size_calculate PORTABLE C */
13791 /* 6.1.4 */
13792 /* AUTHOR */
13793 /* */
13794 /* Yuxin Zhou, Microsoft Corporation */
13795 /* */
13796 /* DESCRIPTION */
13797 /* */
13798 /* This function calculates the size of the name. */
13799 /* */
13800 /* INPUT */
13801 /* */
13802 /* name Pointer to the name */
13803 /* packet_ptr Pointer to received packet */
13804 /* */
13805 /* OUTPUT */
13806 /* */
13807 /* UINT Size of name */
13808 /* */
13809 /* CALLS */
13810 /* */
13811 /* None */
13812 /* */
13813 /* CALLED BY */
13814 /* */
13815 /* */
13816 /* RELEASE HISTORY */
13817 /* */
13818 /* DATE NAME DESCRIPTION */
13819 /* */
13820 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13821 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13822 /* resulting in version 6.1 */
13823 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
13824 /* packet length verification, */
13825 /* resulting in version 6.1.4 */
13826 /* */
13827 /**************************************************************************/
_nx_mdns_name_size_calculate(UCHAR * name,NX_PACKET * packet_ptr)13828 static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr)
13829 {
13830
13831 UINT size = 0;
13832
13833
13834 /* As long as we haven't found a zero length terminating label */
13835 while (*name != '\0')
13836 {
13837
13838 UINT labelSize = *name++;
13839
13840 /* Is this a compression pointer or a count. */
13841 if (labelSize <= NX_MDNS_LABEL_MAX)
13842 {
13843
13844 if (name + labelSize >= packet_ptr -> nx_packet_append_ptr)
13845 {
13846
13847 /* If name buffer is OOB, just fail. */
13848 return(0);
13849 }
13850
13851 /* Simple count, adjust size and skip the label. */
13852 size += labelSize + 1;
13853 name += labelSize;
13854 }
13855 else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
13856 {
13857
13858 /* This is a pointer size is 2 bytes and this is the end of this name */
13859 return(size + 2);
13860 }
13861 else
13862 {
13863
13864 /* Not defined, just fail */
13865 return(0);
13866 }
13867 }
13868
13869 /* Adjust size for the final NULL. */
13870 return(size + 1);
13871 }
13872
13873
13874 /**************************************************************************/
13875 /* */
13876 /* FUNCTION RELEASE */
13877 /* */
13878 /* _nx_mdns_name_string_encode PORTABLE C */
13879 /* 6.1 */
13880 /* AUTHOR */
13881 /* */
13882 /* Yuxin Zhou, Microsoft Corporation */
13883 /* */
13884 /* DESCRIPTION */
13885 /* */
13886 /* This function converts a string containing the name as a list of */
13887 /* labels separated by dots to the encoded list of labels specified */
13888 /* in RFC1035 for DNS servers. This conversion doesn't handle */
13889 /* compression and doesn't check on the lengths of the labels or the */
13890 /* entire name. */
13891 /* */
13892 /* INPUT */
13893 /* */
13894 /* ptr Pointer to destination */
13895 /* name Source name string */
13896 /* */
13897 /* OUTPUT */
13898 /* */
13899 /* count Count of characters encoded */
13900 /* */
13901 /* CALLS */
13902 /* */
13903 /* None */
13904 /* */
13905 /* CALLED BY */
13906 /* */
13907 /* */
13908 /* RELEASE HISTORY */
13909 /* */
13910 /* DATE NAME DESCRIPTION */
13911 /* */
13912 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13913 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13914 /* resulting in version 6.1 */
13915 /* */
13916 /**************************************************************************/
_nx_mdns_name_string_encode(UCHAR * ptr,UCHAR * name)13917 static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name)
13918 {
13919
13920 UCHAR *length;
13921 UINT count = 1;
13922
13923
13924 /* Point to the first character position in the buffer. This will point
13925 to the length of the following name. */
13926 length = ptr++;
13927
13928 /* Default the length to zero. */
13929 *length = 0;
13930
13931 /* Move through string, copying bytes and updating length.
13932 Whenever a "." is found, start a new string by updating the
13933 pointer to the length and setting the length to zero. */
13934 while (*name)
13935 {
13936
13937 /* Is a dot been found? */
13938 if (*name == '.')
13939 {
13940
13941 /* Yes, setup a new length pointer. */
13942 length = ptr++;
13943
13944 /* Default the length to zero. */
13945 *length = 0;
13946 name++;
13947 }
13948 else
13949 {
13950
13951 /* Copy a character to the destination. */
13952 *ptr++ = *name++;
13953
13954 /* Adjust the length of the current segment. */
13955 (*length)++;
13956 }
13957
13958 /* Increment the total count here. */
13959 count++;
13960 }
13961
13962 /* Add the final zero length, like a NULL terminator. */
13963 *ptr = 0;
13964
13965 /* Increment the total count. */
13966 count++;
13967
13968 /* Return the count. */
13969 return(count);
13970 }
13971
13972
13973 /**************************************************************************/
13974 /* */
13975 /* FUNCTION RELEASE */
13976 /* */
13977 /* _nx_mdns_name_string_decode PORTABLE C */
13978 /* 6.1.4 */
13979 /* AUTHOR */
13980 /* */
13981 /* Yuxin Zhou, Microsoft Corporation */
13982 /* */
13983 /* DESCRIPTION */
13984 /* */
13985 /* This function converts from the encoded list of labels as specified */
13986 /* in RFC 1035 to a string containing the name as a list of labels */
13987 /* separated by dots. */
13988 /* */
13989 /* INPUT */
13990 /* */
13991 /* data Pointer to buffer to decode */
13992 /* start Location of start of data */
13993 /* data_length Length of data buffer */
13994 /* buffer Pointer to decoded data */
13995 /* size Size of data buffer to decode */
13996 /* */
13997 /* OUTPUT */
13998 /* */
13999 /* Size of decoded data */
14000 /* */
14001 /* CALLS */
14002 /* */
14003 /* None */
14004 /* */
14005 /* CALLED BY */
14006 /* */
14007 /* */
14008 /* RELEASE HISTORY */
14009 /* */
14010 /* DATE NAME DESCRIPTION */
14011 /* */
14012 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14013 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14014 /* resulting in version 6.1 */
14015 /* 12-31-2020 Yuxin Zhou Modified comment(s), improved */
14016 /* buffer length verification, */
14017 /* prevented infinite loop in */
14018 /* name compression, */
14019 /* resulting in version 6.1.3 */
14020 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
14021 /* packet length verification, */
14022 /* resulting in version 6.1.4 */
14023 /* */
14024 /**************************************************************************/
_nx_mdns_name_string_decode(UCHAR * data,UINT start,UINT data_length,UCHAR * buffer,UINT size)14025 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size)
14026 {
14027
14028 UCHAR *character = data + start;
14029 UINT length = 0;
14030 UINT offset;
14031 UINT pointer_count = 0;
14032 UINT labelSize;
14033
14034
14035 /* As long as there is space in the buffer and we haven't
14036 found a zero terminating label */
14037 while (1)
14038 {
14039
14040 if (character >= data + data_length)
14041 {
14042 return(0);
14043 }
14044
14045 if ((size <= length) || (*character == '\0'))
14046 {
14047 break;
14048 }
14049
14050 labelSize = *character++;
14051
14052 /* Is this a compression pointer or a count. */
14053 if (labelSize <= NX_MDNS_LABEL_MAX)
14054 {
14055
14056 /* Simple count, check for space and copy the label. */
14057 while ((size > length) && (labelSize > 0))
14058 {
14059 if (character >= data + data_length)
14060 {
14061 return(0);
14062 }
14063
14064 *buffer++ = *character++;
14065 length++;
14066 labelSize--;
14067 }
14068
14069 /* Now add the '.' */
14070 *buffer++ = '.';
14071 length++;
14072 }
14073 else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
14074 {
14075
14076 if (character >= data + data_length)
14077 {
14078 return(0);
14079 }
14080
14081 /* This is a pointer, just adjust the source. */
14082 offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
14083
14084 /* Make sure offset is in the buffer. */
14085 if (offset >= data_length)
14086 {
14087 return(0);
14088 }
14089
14090 /* Pointer must not point back to itself. */
14091 if ((data + offset == character) || (data + offset == character - 1))
14092 {
14093 return(0);
14094 }
14095
14096 /* Prevent infinite loop with compression pointers. */
14097 pointer_count++;
14098 if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS)
14099 {
14100 return(0);
14101 }
14102
14103 character = data + offset;
14104 }
14105 else
14106 {
14107
14108 /* Not defined, just fail */
14109 return(0);
14110 }
14111 }
14112
14113 /* Done copying the data, set the last . to a trailing null */
14114 if ((length > 0) && (*(buffer - 1) == '.'))
14115 {
14116
14117 buffer--;
14118 length --;
14119 }
14120
14121 /* Null terminate name. */
14122 *buffer = '\0';
14123
14124 /* Return name size. */
14125 return(length);
14126 }
14127
14128
14129 /**************************************************************************/
14130 /* */
14131 /* FUNCTION RELEASE */
14132 /* */
14133 /* _nx_mdns_rr_size_get PORTABLE C */
14134 /* 6.1.4 */
14135 /* AUTHOR */
14136 /* */
14137 /* Yuxin Zhou, Microsoft Corporation */
14138 /* */
14139 /* DESCRIPTION */
14140 /* */
14141 /* This function gets the size of resource record. */
14142 /* */
14143 /* INPUT */
14144 /* */
14145 /* resource Pointer to the resource */
14146 /* packet_ptr Pointer to received packet */
14147 /* */
14148 /* OUTPUT */
14149 /* */
14150 /* size of data */
14151 /* */
14152 /* CALLS */
14153 /* */
14154 /* */
14155 /* CALLED BY */
14156 /* */
14157 /* */
14158 /* RELEASE HISTORY */
14159 /* */
14160 /* DATE NAME DESCRIPTION */
14161 /* */
14162 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14163 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14164 /* resulting in version 6.1 */
14165 /* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
14166 /* packet length verification, */
14167 /* resulting in version 6.1.4 */
14168 /* */
14169 /**************************************************************************/
_nx_mdns_rr_size_get(UCHAR * resource,NX_PACKET * packet_ptr)14170 static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr)
14171 {
14172
14173 UINT name_size;
14174 UINT data_size;
14175
14176 /* Resource size is
14177 name size + data size + 2 bytes for type, 2 for class, 4 for time to live and 2 for data length
14178 i.e. name size + data size + 10 bytes overhead.
14179 */
14180 name_size = _nx_mdns_name_size_calculate(resource, packet_ptr);
14181
14182 if (resource + name_size + 8 + 2 > packet_ptr -> nx_packet_append_ptr)
14183 {
14184 return(0);
14185 }
14186 data_size = NX_MDNS_GET_USHORT_DATA(resource + name_size + 8);
14187
14188 /* Return resource size. */
14189 return(name_size + data_size + 10);
14190 }
14191
14192
14193 /**************************************************************************/
14194 /* */
14195 /* FUNCTION RELEASE */
14196 /* */
14197 /* _nx_mdns_short_to_network_convert PORTABLE C */
14198 /* 6.1 */
14199 /* AUTHOR */
14200 /* */
14201 /* Yuxin Zhou, Microsoft Corporation */
14202 /* */
14203 /* DESCRIPTION */
14204 /* */
14205 /* This function converts an unsigned short to network byte order, */
14206 /* which is big endian. */
14207 /* */
14208 /* INPUT */
14209 /* */
14210 /* ptr Pointer to the destination */
14211 /* value Source value */
14212 /* */
14213 /* OUTPUT */
14214 /* */
14215 /* None */
14216 /* */
14217 /* CALLS */
14218 /* */
14219 /* None */
14220 /* */
14221 /* CALLED BY */
14222 /* */
14223 /* DNS component */
14224 /* */
14225 /* RELEASE HISTORY */
14226 /* */
14227 /* DATE NAME DESCRIPTION */
14228 /* */
14229 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14230 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14231 /* resulting in version 6.1 */
14232 /* */
14233 /**************************************************************************/
_nx_mdns_short_to_network_convert(UCHAR * ptr,USHORT value)14234 static void _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value)
14235 {
14236
14237 *ptr++ = (UCHAR)(value >> 8);
14238 *ptr = (UCHAR)value;
14239 }
14240
14241
14242 /**************************************************************************/
14243 /* */
14244 /* FUNCTION RELEASE */
14245 /* */
14246 /* _nx_mdns_long_to_network_convert PORTABLE C */
14247 /* 6.1 */
14248 /* AUTHOR */
14249 /* */
14250 /* Yuxin Zhou, Microsoft Corporation */
14251 /* */
14252 /* DESCRIPTION */
14253 /* */
14254 /* This function converts an unsigned long to network format, which */
14255 /* big endian. */
14256 /* */
14257 /* INPUT */
14258 /* */
14259 /* ptr Pointer to the destination */
14260 /* value Source value */
14261 /* */
14262 /* OUTPUT */
14263 /* */
14264 /* None */
14265 /* */
14266 /* CALLS */
14267 /* */
14268 /* None */
14269 /* */
14270 /* CALLED BY */
14271 /* */
14272 /* DNS component */
14273 /* */
14274 /* RELEASE HISTORY */
14275 /* */
14276 /* DATE NAME DESCRIPTION */
14277 /* */
14278 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14279 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14280 /* resulting in version 6.1 */
14281 /* */
14282 /**************************************************************************/
_nx_mdns_long_to_network_convert(UCHAR * ptr,ULONG value)14283 static void _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value)
14284 {
14285
14286 *ptr++ = (UCHAR)(value >> 24);
14287 *ptr++ = (UCHAR)(value >> 16);
14288 *ptr++ = (UCHAR)(value >> 8);
14289 *ptr = (UCHAR)value;
14290 }
14291