1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Multicast Domain Name System (mDNS)                                 */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 #define NX_MDNS_SOURCE_CODE
24 
25 
26 /* Force error checking to be disabled in this module */
27 #ifndef NX_DISABLE_ERROR_CHECKING
28 #define NX_DISABLE_ERROR_CHECKING
29 #endif /* NX_DISABLE_ERROR_CHECKING  */
30 
31 
32 /* Include necessary system files.  */
33 #include    "nxd_mdns.h"
34 #include    "tx_thread.h"
35 
36 /* Define the application protocol.  */
37 static CHAR         *nx_mdns_app_protocol[]= {"_tcp", "_udp", NX_NULL};
38 
39 /* Define the service type.  */
40 #ifndef NX_MDNS_DISABLE_CLIENT
41 static CHAR         *nx_mdns_service_types[] =
42 {
43     "_device-info",
44     "_http",
45     "_https",
46     "_guid",
47     "_h323",
48     "_ntp",
49     "_objective",
50     "_rdp",
51     "_remote",
52     "_rtsp",
53     "_sip",
54     "_smb",
55     "_soap",
56     "_ssh",
57     "_telnet",
58     "_tftp",
59     "_xmpp-client",
60     NX_NULL
61 };
62 #endif /* NX_MDNS_DISABLE_CLIENT  */
63 
64 
65 /* Define the mDNS internal Function.  */
66 static VOID         _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
67 static VOID         _nx_mdns_timer_entry(ULONG mdns_value);
68 static VOID         _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr, ULONG timer_count);
69 static VOID         _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr);
70 static VOID         _nx_mdns_thread_entry(ULONG mdns_value);
71 static UINT         _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
72 static UINT         _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR type);
73 static VOID         _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
74 static UINT         _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type);
75 static UINT         _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index);
76 static UINT         _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op);
77 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
78 static UINT         _nx_mdns_packet_address_check(NX_PACKET *packet_ptr);
79 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
80 static UINT         _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index);
81 static UINT         _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain);
82 static UINT         _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
83 static UINT         _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr);
84 static UINT         _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length);
85 static UINT         _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr);
86 static UINT         _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name);
87 static UINT         _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size);
88 static UINT         _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name);
89 static UINT         _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size);
90 static VOID         _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value);
91 static VOID         _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value);
92 
93 #ifndef NX_MDNS_DISABLE_SERVER
94 static VOID         _nx_mdns_address_change_process(NX_MDNS *mdns_ptr);
95 static UINT         _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index);
96 static UINT         _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index);
97 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
98 static UINT         _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index);
99 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
100 static UINT         _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority, USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index);
101 static UINT         _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index);
102 static UINT         _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index);
103 
104 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
105 static UINT         _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index);
106 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
107 
108 static UINT         _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length, UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index);
109 static UINT         _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr);
110 static UINT         _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
111 static VOID         _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index);
112 static VOID         _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index);
113 static VOID         _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index);
114 static VOID         _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index);
115 #ifndef NX_DISABLE_IPV4
116 static VOID         _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info);
117 #endif /* NX_DISABLE_IPV4 */
118 #ifdef NX_MDNS_ENABLE_IPV6
119 static VOID         _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address);
120 #endif /* NX_MDNS_ENABLE_IPV6  */
121 #endif /* NX_MDNS_DISABLE_SERVER  */
122 
123 #ifndef NX_MDNS_DISABLE_CLIENT
124 static VOID         _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present);
125 static UINT         _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index);
126 static UINT         _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask);
127 static UINT         _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index);
128 static UINT         _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index);
129 static VOID         _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index);
130 static UINT         _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index);
131 static VOID         _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER);
132 static VOID         _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
133                                                   NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option);
134 static VOID         _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr);
135 static UINT         _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
136 static UINT         _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index);
137 #endif /* NX_MDNS_DISABLE_CLIENT  */
138 
139 UINT         _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size, VOID *peer_cache_ptr, UINT peer_cache_size);
140 UINT         _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present);
141 UINT         _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr);
142 UINT         _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_result);
143 UINT         _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len, VOID **insert_ptr, UCHAR find_string, UCHAR add_name);
144 UINT         _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len);
145 VOID         _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr);
146 
147 
148 /* Define the mDNS STRUCT.  */
149 static struct       NX_MDNS_STRUCT  *_nx_mdns_created_ptr;
150 static CHAR         _nx_mdns_dns_sd[NX_MDNS_DNS_SD_MAX + 1] = "_services._dns-sd._udp.local";
151 static UCHAR        temp_string_buffer[NX_MDNS_NAME_MAX + 1];
152 static UCHAR        target_string_buffer[NX_MDNS_NAME_MAX + 1];
153 
154 #ifdef NX_MDNS_ENABLE_IPV6
155 static NXD_ADDRESS  NX_MDNS_IPV6_MULTICAST_ADDRESS;
156 #endif /* NX_MDNS_ENABLE_IPV6 */
157 
158 /**************************************************************************/
159 /*                                                                        */
160 /*  FUNCTION                                               RELEASE        */
161 /*                                                                        */
162 /*    _nxe_mdns_create                                    PORTABLE C      */
163 /*                                                           6.1          */
164 /*  AUTHOR                                                                */
165 /*                                                                        */
166 /*    Yuxin Zhou, Microsoft Corporation                                   */
167 /*                                                                        */
168 /*  DESCRIPTION                                                           */
169 /*                                                                        */
170 /*    This function checks for errors in the mDNS create function call    */
171 /*                                                                        */
172 /*    Note: the name string is generated by internal logic and it is      */
173 /*    always NULL-terminated.                                             */
174 /*                                                                        */
175 /*  INPUT                                                                 */
176 /*                                                                        */
177 /*    mdns_ptr                              Pointer to mDNS instance      */
178 /*    ip_ptr                                Pointer to IP instance        */
179 /*    priority                              The priority of mDNS Thread   */
180 /*    stack_ptr                             Stack pointer for mDNS Thread */
181 /*    stack_size                            Stack size for mDNS Thread    */
182 /*    host_name                             Pointer to host name          */
183 /*    local_cache_ptr                       Pointer to local cache        */
184 /*    local_cache_size                      The size of local cache       */
185 /*    peer_cache_ptr                        Pointer to peer cache         */
186 /*    peer_cache_size                       The size of peer cache        */
187 /*    probing_notify                        mDNS probing notify           */
188 /*                                                                        */
189 /*  OUTPUT                                                                */
190 /*                                                                        */
191 /*    status                                Completion status             */
192 /*                                                                        */
193 /*  CALLS                                                                 */
194 /*                                                                        */
195 /*    _nx_mdns_create                       Actual mDNS create function   */
196 /*                                                                        */
197 /*  CALLED BY                                                             */
198 /*                                                                        */
199 /*    Application Code                                                    */
200 /*                                                                        */
201 /*  RELEASE HISTORY                                                       */
202 /*                                                                        */
203 /*    DATE              NAME                      DESCRIPTION             */
204 /*                                                                        */
205 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
206 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
207 /*                                            resulting in version 6.1    */
208 /*                                                                        */
209 /**************************************************************************/
_nxe_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))210 UINT  _nxe_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
211                        UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
212                        VOID *local_cache_ptr, UINT local_cache_size,
213                        VOID *peer_cache_ptr, UINT peer_cache_size,
214                        VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
215 {
216 
217 UINT    status;
218 UCHAR   *ptr;
219 
220 
221     /* Check for invalid input pointers.  */
222     if ((!ip_ptr) || (!mdns_ptr) || (!stack_ptr) || (!packet_pool) || (!host_name))
223     {
224         return(NX_PTR_ERROR);
225     }
226 
227     /* Check for invalid non pointer input. */
228     if ((ip_ptr -> nx_ip_id != NX_IP_ID) ||
229         (stack_size < TX_MINIMUM_STACK) ||
230         (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
231     {
232         return(NX_MDNS_PARAM_ERROR);
233     }
234 
235     /* Check the host name format, RFC 1033,1034,1035 recomend that host names contain only letters, digits, and hyphens RFC6763, Appendix E, Page44. */
236     ptr = host_name;
237     while (*ptr != '\0')
238     {
239         if (((*ptr >= 'a') && (*ptr <= 'z')) ||
240             ((*ptr >= 'A') && (*ptr <= 'Z')) ||
241             ((*ptr >= '0') && (*ptr <= '9')) ||
242             ((*ptr == '-')))
243             ptr++;
244         else
245             return(NX_MDNS_HOST_NAME_ERROR);
246     }
247 
248     /* Check the default domain name size.  */
249     if ((sizeof("local") - 1) > NX_MDNS_DOMAIN_NAME_MAX)
250     {
251         return(NX_MDNS_DATA_SIZE_ERROR);
252     }
253 
254 #ifndef NX_MDNS_DISABLE_SERVER
255 
256     /* Check for invalid input pointers, cache header and tail (8 bytes).  */
257     if ((!local_cache_ptr) || (local_cache_size < 8))
258     {
259         return(NX_PTR_ERROR);
260     }
261 
262     /* Make sure record_buffer is 4-byte aligned. */
263     if ((((UINT)local_cache_ptr & 0x3) != 0) ||
264         ((local_cache_size & 0x3) != 0))
265     {
266         return(NX_MDNS_CACHE_ERROR);
267     }
268 #endif /* NX_MDNS_DISABLE_SERVER */
269 
270 #ifndef NX_MDNS_DISABLE_CLIENT
271 
272     /* Check for invalid input pointers, cache header and tail (8 bytes).  */
273     if ((!peer_cache_ptr) || (peer_cache_size < 8))
274     {
275         return(NX_PTR_ERROR);
276     }
277 
278     /* Make sure peer cache is 4-byte aligned. */
279     if ((((UINT)peer_cache_ptr & 0x3) != 0) ||
280         ((peer_cache_size & 0x3) != 0))
281     {
282         return(NX_MDNS_CACHE_ERROR);
283     }
284 #endif /* NX_MDNS_DISABLE_CLIENT */
285 
286     /* Call actual mDNS create service.  */
287     status =  _nx_mdns_create(mdns_ptr, ip_ptr, packet_pool, priority,
288                               stack_ptr, stack_size, host_name,
289                               local_cache_ptr, local_cache_size,
290                               peer_cache_ptr, peer_cache_size,
291                               probing_notify);
292 
293     /* Return status.  */
294     return(status);
295 }
296 
297 
298 /**************************************************************************/
299 /*                                                                        */
300 /*  FUNCTION                                               RELEASE        */
301 /*                                                                        */
302 /*    _nx_mdns_create                                     PORTABLE C      */
303 /*                                                           6.1.11       */
304 /*  AUTHOR                                                                */
305 /*                                                                        */
306 /*    Yuxin Zhou, Microsoft Corporation                                   */
307 /*                                                                        */
308 /*  DESCRIPTION                                                           */
309 /*                                                                        */
310 /*    This function initializes the mDNS structure and associated IP      */
311 /*    instance for mDNS operation. In doing so, it creates a UDP socket   */
312 /*    for communication with the server and a mDNS processing thread      */
313 /*                                                                        */
314 /*    Note: the name string is generated by internal logic and it is      */
315 /*    always NULL-terminated.                                             */
316 /*                                                                        */
317 /*  INPUT                                                                 */
318 /*                                                                        */
319 /*    mdns_ptr                              Pointer to mDNS instance      */
320 /*    ip_ptr                                Pointer to IP instance        */
321 /*    priority                              The priority of mDNS Thread   */
322 /*    stack_ptr                             Stack pointer for mDNS Thread */
323 /*    stack_size                            Stack size for mDNS Thread    */
324 /*    host_name                             Pointer to host name          */
325 /*    local_cache_ptr                       Pointer to local cache        */
326 /*    local_cache_size                      The size of local cache       */
327 /*    peer_cache_ptr                        Pointer to peer cache         */
328 /*    peer_cache_size                       The size of peer cache        */
329 /*    probing_notify                        mDNS probing notify           */
330 /*                                                                        */
331 /*  OUTPUT                                                                */
332 /*                                                                        */
333 /*    status                                Completion status             */
334 /*                                                                        */
335 /*  CALLS                                                                 */
336 /*                                                                        */
337 /*    nx_udp_socket_create                  Create the mDNS UDP socket    */
338 /*    nx_udp_socket_delete                  Delete the mDNS UDP socket    */
339 /*    nx_udp_socket_bind                    Bind the mDNS UDP socket      */
340 /*    nx_udp_socket_unbind                  Unbind the mDNS UDP socket    */
341 /*    nx_udp_socket_receive_notify          Register the mDNS function    */
342 /*    nx_ip_address_change_notify           Register IPv4 address function*/
343 /*    nxd_ipv6_address_change_notify        Register IPv6 address function*/
344 /*    tx_mutex_create                       Create the mDNS mutex         */
345 /*    tx_mutex_delete                       Delete the mDNS mutex         */
346 /*    tx_thread_create                      Create the mDNS thread        */
347 /*    tx_thread_delete                      Delete the mDNS thread        */
348 /*    tx_event_flags_create                 Create the ThreadX flag event */
349 /*    _nx_mdns_cache_initialize             Initialize the mDNS cache     */
350 /*                                                                        */
351 /*  CALLED BY                                                             */
352 /*                                                                        */
353 /*    Application Code                                                    */
354 /*                                                                        */
355 /*  RELEASE HISTORY                                                       */
356 /*                                                                        */
357 /*    DATE              NAME                      DESCRIPTION             */
358 /*                                                                        */
359 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
360 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
361 /*                                            verified memcpy use cases,  */
362 /*                                            resulting in version 6.1    */
363 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
364 /*                                            corrected the random value, */
365 /*                                            used internal ip address    */
366 /*                                            change notification,        */
367 /*                                            resulting in version 6.1.11 */
368 /*                                                                        */
369 /**************************************************************************/
_nx_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))370 UINT  _nx_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
371                       UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
372                       VOID *local_cache_ptr, UINT local_cache_size,
373                       VOID *peer_cache_ptr, UINT peer_cache_size,
374                       VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
375 {
376 
377 UINT    status;
378 UINT    host_name_size;
379 
380 
381     /* Check the size of the host name string. The last four characters in the
382        host_name are reserved so DNS-SD is able to append " (2)" during the conflict
383        resolution process. */
384 #if (NX_MDNS_HOST_NAME_MAX >= NX_MDNS_LABEL_MAX)
385     if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_LABEL_MAX - 4)))
386 #else
387     if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_HOST_NAME_MAX - 4)))
388 #endif
389     {
390         return(NX_MDNS_DATA_SIZE_ERROR);
391     }
392 
393     /* Initialize the mDNS control block to zero.  */
394     memset((void *) mdns_ptr, 0, sizeof(NX_MDNS));
395 
396 #ifdef NX_MDNS_ENABLE_IPV6
397 
398     /* Initialize the IPv6 Multicast address.  */
399     memset(&NX_MDNS_IPV6_MULTICAST_ADDRESS, 0, sizeof(NXD_ADDRESS));
400     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_version = NX_IP_VERSION_V6;
401     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0] = 0xFF020000;
402     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1] = 0x00000000;
403     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2] = 0x00000000;
404     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3] = 0x000000FB;
405 #endif /* NX_MDNS_ENABLE_IPV6 */
406 
407     /* Save the IP pointer.  */
408     mdns_ptr -> nx_mdns_ip_ptr = ip_ptr;
409 
410     /* Save the Packet pool.  */
411     mdns_ptr -> nx_mdns_packet_pool_ptr = packet_pool;
412 
413     /* Save the host name.  */
414     memcpy((char*)mdns_ptr -> nx_mdns_host_name, (const char*)host_name, (host_name_size + 1)); /* Use case of memcpy is verified. */
415 
416     /* Set the domain name as "local" by default.  */
417     memcpy((char*)mdns_ptr -> nx_mdns_domain_name, "local", sizeof("local")); /* Use case of memcpy is verified. */
418 
419     /* Assign the resource record change notify. */
420     mdns_ptr -> nx_mdns_probing_notify = probing_notify;
421 
422     /* Set the mDNS announcing period.  */
423     mdns_ptr -> nx_mdns_announcing_period = (USHORT)NX_MDNS_ANNOUNCING_PERIOD;
424 
425     /* Set the mDNS announcing retransmission interval.  */
426     mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)NX_MDNS_ANNOUNCING_RETRANS_INTERVAL;
427 
428     /* Set the mDNS announcing period interval.  */
429     mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)NX_MDNS_ANNOUNCING_PERIOD_INTERVAL;
430 
431     /* Set the mDNS announcing count between one announcing period.  */
432     mdns_ptr -> nx_mdns_announcing_count = (UCHAR)NX_MDNS_ANNOUNCING_COUNT;
433 
434     /* Set the mDNS announcing factor.  */
435     mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)NX_MDNS_ANNOUNCING_FACTOR;
436 
437     /* Set the mDNS announcing max time.  */
438     mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)NX_MDNS_ANNOUNCING_MAX_TIME;
439 
440     /* Set the pointer of global variable mDNS.  */
441     _nx_mdns_created_ptr = mdns_ptr;
442 
443 #ifndef NX_MDNS_DISABLE_SERVER
444 
445 #ifndef NX_DISABLE_IPV4
446     /* Setup the IP address change callback function. */
447     ip_ptr -> nx_ip_address_change_notify_internal = _nx_mdns_ip_address_change_notify;
448 #endif /* NX_DISABLE_IPV4 */
449 
450 #ifdef NX_MDNS_ENABLE_IPV6
451 
452     /* Setup the IPv6 address change callback function. */
453     ip_ptr -> nx_ipv6_address_change_notify_internal =  _nx_mdns_ipv6_address_change_notify;
454 #endif /* NX_MDNS_ENABLE_IPV6  */
455 #endif /* NX_MDNS_DISABLE_SERVER */
456 
457     /* Create the Socket and check the status */
458     status = nx_udp_socket_create(mdns_ptr -> nx_mdns_ip_ptr, &(mdns_ptr -> nx_mdns_socket), "Multicast DNS",
459                                   NX_MDNS_UDP_TYPE_OF_SERVICE, NX_MDNS_UDP_FRAGMENT_OPTION,
460                                   NX_MDNS_UDP_TIME_TO_LIVE, NX_MDNS_UDP_QUEUE_DEPTH);
461 
462     /* Determine if it was successful.  */
463     if (status != NX_SUCCESS)
464     {
465         return(status);
466     }
467 
468     /* Bind the UDP socket to the mDNS port.  */
469     status =  nx_udp_socket_bind(&(mdns_ptr -> nx_mdns_socket), NX_MDNS_UDP_PORT, TX_NO_WAIT);
470 
471     /* Check for error */
472     if (status)
473     {
474 
475         /* Delete the UDP socket.  */
476         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
477         return(status);
478     }
479 
480     /* Register UDP receive callback. */
481     status = nx_udp_socket_receive_notify(&(mdns_ptr -> nx_mdns_socket), _nx_mdns_udp_receive_notify);
482 
483     /* Check for error */
484     if (status)
485     {
486 
487         /* Delete the UDP socket.  */
488         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
489         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
490         return(status);
491     }
492 
493     /* Create the mDNS mutex.  */
494     status =  tx_mutex_create(&(mdns_ptr -> nx_mdns_mutex),
495                               "mDNS Mutex", TX_NO_INHERIT);
496 
497     /* Determine if the semaphore creation was successful.  */
498     if (status != NX_SUCCESS)
499     {
500 
501         /* Delete the UDP socket.  */
502         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
503         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
504 
505         /* No, return error status.  */
506         return(status);
507     }
508 
509     /* Create the internal mDNS event flag object.  */
510     status = tx_event_flags_create(&mdns_ptr -> nx_mdns_events, "mDNS Thread Events");
511 
512     /* Determine if the event flags creation was successful.  */
513     if (status)
514     {
515 
516         /* Delete the UDP socket.  */
517         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
518         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
519 
520         /* Delete the mDNS mutex.  */
521         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
522 
523         /* No, return error status.  */
524         return(status);
525     }
526 
527     /* Create the mDNS processing thread.  */
528     status =  tx_thread_create(&(mdns_ptr -> nx_mdns_thread), "mDNS Thread",
529                                _nx_mdns_thread_entry, (ULONG) mdns_ptr,
530                                stack_ptr, stack_size, priority, priority,
531                                1, TX_AUTO_START);
532 
533     /* Determine if the thread creation was successful.  */
534     if (status != NX_SUCCESS)
535     {
536 
537         /* Delete the UDP socket.  */
538         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
539         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
540 
541         /* Delete the mDNS mutex.  */
542         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
543 
544         /* Delete the mDNS events.  */
545         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
546 
547         /* No, return error status.  */
548         return(status);
549     }
550 
551     /* Create the timer of Resource record lifetime.  */
552     status =  tx_timer_create(&(mdns_ptr -> nx_mdns_timer), "mDNS Timer",
553                               _nx_mdns_timer_entry, (ULONG) mdns_ptr,
554                               0xFFFFFFFF, 0, TX_NO_ACTIVATE);
555 
556     /* Determine if the thread creation was successful.  */
557     if (status != NX_SUCCESS)
558     {
559 
560         /* Delete the UDP socket.  */
561         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
562         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
563 
564         /* Delete the mDNS mutex.  */
565         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
566 
567         /* Delete the mDNS events.  */
568         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
569 
570         /* Delete the mDNS thread.  */
571         tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
572 
573         /* No, return error status.  */
574         return(status);
575     }
576 
577     /* Initialize the buffer.  */
578     status =  _nx_mdns_cache_initialize(mdns_ptr, local_cache_ptr, local_cache_size,
579                                         peer_cache_ptr, peer_cache_size);
580 
581     /* Determine if the buffer initialize was successful.  */
582     if (status != NX_SUCCESS)
583     {
584 
585         /* Delete the UDP socket.  */
586         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
587         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
588 
589         /* Delete the mDNS timer.  */
590         tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
591 
592         /* Delete the mDNS mutex.  */
593         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
594 
595         /* Delete the mDNS events.  */
596         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
597 
598         /* Delete the mDNS thread.  */
599         tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
600 
601         /* No, return error status.  */
602         return(status);
603     }
604 
605     /* Update the mDNS structure ID.  */
606     mdns_ptr -> nx_mdns_id = NX_MDNS_ID;
607 
608     /* The random delay of first probing for RR. */
609     mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (((ULONG)NX_RAND()) % NX_MDNS_PROBING_TIMER_COUNT));
610 
611     /* Return a successful status.  */
612     return(NX_SUCCESS);
613 }
614 
615 
616 /**************************************************************************/
617 /*                                                                        */
618 /*  FUNCTION                                               RELEASE        */
619 /*                                                                        */
620 /*    _nxe_mdns_delete                                    PORTABLE C      */
621 /*                                                           6.1          */
622 /*  AUTHOR                                                                */
623 /*                                                                        */
624 /*    Yuxin Zhou, Microsoft Corporation                                   */
625 /*                                                                        */
626 /*  DESCRIPTION                                                           */
627 /*                                                                        */
628 /*    This function checks for errors in the mDNS delete function call.   */
629 /*                                                                        */
630 /*  INPUT                                                                 */
631 /*                                                                        */
632 /*    mdns_ptr                              Pointer to mDNS instance      */
633 /*                                                                        */
634 /*  OUTPUT                                                                */
635 /*                                                                        */
636 /*    status                                Completion status             */
637 /*                                                                        */
638 /*  CALLS                                                                 */
639 /*                                                                        */
640 /*    _nx_mdns_delete                       Actual mDNS delete function   */
641 /*                                                                        */
642 /*  CALLED BY                                                             */
643 /*                                                                        */
644 /*    Application Code                                                    */
645 /*                                                                        */
646 /*  RELEASE HISTORY                                                       */
647 /*                                                                        */
648 /*    DATE              NAME                      DESCRIPTION             */
649 /*                                                                        */
650 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
651 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
652 /*                                            resulting in version 6.1    */
653 /*                                                                        */
654 /**************************************************************************/
_nxe_mdns_delete(NX_MDNS * mdns_ptr)655 UINT  _nxe_mdns_delete(NX_MDNS *mdns_ptr)
656 {
657 
658 UINT    status;
659 
660 
661     /* Check for invalid input pointers.  */
662     if (!mdns_ptr)
663     {
664         return(NX_PTR_ERROR);
665     }
666 
667     /* Check for invalid server attributes. */
668     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
669     {
670         return(NX_MDNS_PARAM_ERROR);
671     }
672 
673     /* Call actual mDNS delete service.  */
674     status =  _nx_mdns_delete(mdns_ptr);
675 
676     /* Return status.  */
677     return(status);
678 }
679 
680 
681 /**************************************************************************/
682 /*                                                                        */
683 /*  FUNCTION                                               RELEASE        */
684 /*                                                                        */
685 /*    _nx_mdns_delete                                     PORTABLE C      */
686 /*                                                           6.1          */
687 /*  AUTHOR                                                                */
688 /*                                                                        */
689 /*    Yuxin Zhou, Microsoft Corporation                                   */
690 /*                                                                        */
691 /*  DESCRIPTION                                                           */
692 /*                                                                        */
693 /*    This function deletes the mDNS instance.                            */
694 /*                                                                        */
695 /*  INPUT                                                                 */
696 /*                                                                        */
697 /*    mdns_ptr                              Pointer to mDNS instance      */
698 /*                                                                        */
699 /*  OUTPUT                                                                */
700 /*                                                                        */
701 /*    status                                Completion status             */
702 /*                                                                        */
703 /*  CALLS                                                                 */
704 /*                                                                        */
705 /*    nx_udp_socket_unbind                  Unbind the mDNS UDP socket    */
706 /*    nx_udp_socket_delete                  Delete the mDNS UDP socket    */
707 /*    tx_mutex_get                          Get the mDNS mutex            */
708 /*    tx_mutex_put                          Put the mDNS mutex            */
709 /*    tx_mutex_delete                       Delete the mDNS mutex         */
710 /*    tx_thread_terminate                   Terminate the mDNS thread     */
711 /*    tx_thread_delete                      Delete the mDNS thread        */
712 /*    tx_event_flags_delete                 Delete the mDNS events flag   */
713 /*                                                                        */
714 /*  CALLED BY                                                             */
715 /*                                                                        */
716 /*    Application Code                                                    */
717 /*                                                                        */
718 /*  RELEASE HISTORY                                                       */
719 /*                                                                        */
720 /*    DATE              NAME                      DESCRIPTION             */
721 /*                                                                        */
722 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
723 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
724 /*                                            resulting in version 6.1    */
725 /*                                                                        */
726 /**************************************************************************/
_nx_mdns_delete(NX_MDNS * mdns_ptr)727 UINT  _nx_mdns_delete(NX_MDNS *mdns_ptr)
728 {
729 
730 
731     /* Get the mDNS mutex.  */
732     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
733 
734     /* Clear the mDNS structure ID. */
735     mdns_ptr -> nx_mdns_id =  0;
736 
737     /* Set the pointer of global variable mDNS.  */
738     _nx_mdns_created_ptr = NX_NULL;
739 
740     /* Unbind the port.  */
741     nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
742 
743     /* Delete the UDP socket.  */
744     nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
745 
746     /* Terminate the mDNS processing thread.  */
747     tx_thread_terminate(&(mdns_ptr -> nx_mdns_thread));
748 
749     /* Delete the mDNS processing thread.  */
750     tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
751 
752     /* Delete the event flags.  */
753     tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
754 
755     /* Delete the timer.  */
756     tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
757 
758     /* Release the mDNS mutex.  */
759     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
760 
761     /* Delete the mDNS mutex.  */
762     tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
763 
764     /* Return a successful status.  */
765     return(NX_SUCCESS);
766 }
767 
768 
769 /**************************************************************************/
770 /*                                                                        */
771 /*  FUNCTION                                               RELEASE        */
772 /*                                                                        */
773 /*    _nxe_mdns_cache_notify_set                          PORTABLE C      */
774 /*                                                           6.1          */
775 /*  AUTHOR                                                                */
776 /*                                                                        */
777 /*    Yuxin Zhou, Microsoft Corporation                                   */
778 /*                                                                        */
779 /*  DESCRIPTION                                                           */
780 /*                                                                        */
781 /*    This function checks for errors in the mDNS cache full notify       */
782 /*    function call.                                                      */
783 /*                                                                        */
784 /*  INPUT                                                                 */
785 /*                                                                        */
786 /*    mdns_ptr                              Pointer to mDNS instance      */
787 /*    cache_full_notify                     Cache full notify function    */
788 /*                                                                        */
789 /*  OUTPUT                                                                */
790 /*                                                                        */
791 /*    status                                Completion status             */
792 /*                                                                        */
793 /*  CALLS                                                                 */
794 /*                                                                        */
795 /*    _nx_mdns_cache_notify_set             Actual cache notify           */
796 /*                                            set function                */
797 /*                                                                        */
798 /*  CALLED BY                                                             */
799 /*                                                                        */
800 /*    Application Code                                                    */
801 /*                                                                        */
802 /*  RELEASE HISTORY                                                       */
803 /*                                                                        */
804 /*    DATE              NAME                      DESCRIPTION             */
805 /*                                                                        */
806 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
807 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
808 /*                                            resulting in version 6.1    */
809 /*                                                                        */
810 /**************************************************************************/
_nxe_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))811 UINT _nxe_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
812 {
813 
814 UINT    status;
815 
816 
817     /* Check for invalid input pointers.  */
818     if (!mdns_ptr)
819     {
820         return(NX_PTR_ERROR);
821     }
822 
823     /* Check for invalid non pointer input. */
824     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
825     {
826         return(NX_MDNS_PARAM_ERROR);
827     }
828 
829     /* Call actual mDNS cache notify set function.  */
830     status =  _nx_mdns_cache_notify_set(mdns_ptr, cache_full_notify_cb);
831 
832     /* Return status.  */
833     return(status);
834 }
835 
836 
837 /**************************************************************************/
838 /*                                                                        */
839 /*  FUNCTION                                               RELEASE        */
840 /*                                                                        */
841 /*    _nx_mdns_cache_notify_set                           PORTABLE C      */
842 /*                                                           6.1          */
843 /*  AUTHOR                                                                */
844 /*                                                                        */
845 /*    Yuxin Zhou, Microsoft Corporation                                   */
846 /*                                                                        */
847 /*  DESCRIPTION                                                           */
848 /*                                                                        */
849 /*    This function set the cache full notify function.                   */
850 /*                                                                        */
851 /*  INPUT                                                                 */
852 /*                                                                        */
853 /*    mdns_ptr                              Pointer to mDNS instance      */
854 /*                                                                        */
855 /*  OUTPUT                                                                */
856 /*                                                                        */
857 /*    status                                Completion status             */
858 /*                                                                        */
859 /*  CALLS                                                                 */
860 /*                                                                        */
861 /*    tx_mutex_get                          Get the mDNS mutex            */
862 /*    tx_mutex_put                          Put the mDNS mutex            */
863 /*                                                                        */
864 /*  CALLED BY                                                             */
865 /*                                                                        */
866 /*    Application Code                                                    */
867 /*                                                                        */
868 /*  RELEASE HISTORY                                                       */
869 /*                                                                        */
870 /*    DATE              NAME                      DESCRIPTION             */
871 /*                                                                        */
872 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
873 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
874 /*                                            resulting in version 6.1    */
875 /*                                                                        */
876 /**************************************************************************/
_nx_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))877 UINT _nx_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
878 {
879 
880 
881     /* Get the mDNS mutex.  */
882     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
883 
884     /* Set the cache notify.  */
885     mdns_ptr -> nx_mdns_cache_full_notify = cache_full_notify_cb;
886 
887     /* Release the mDNS mutex.  */
888     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
889 
890     return(NX_MDNS_SUCCESS);
891 }
892 
893 
894 /**************************************************************************/
895 /*                                                                        */
896 /*  FUNCTION                                               RELEASE        */
897 /*                                                                        */
898 /*    _nxe_mdns_cache_notify_clear                        PORTABLE C      */
899 /*                                                           6.1          */
900 /*  AUTHOR                                                                */
901 /*                                                                        */
902 /*    Yuxin Zhou, Microsoft Corporation                                   */
903 /*                                                                        */
904 /*  DESCRIPTION                                                           */
905 /*                                                                        */
906 /*    This function checks for errors in the mDNS cache full notify       */
907 /*    function call.                                                      */
908 /*                                                                        */
909 /*  INPUT                                                                 */
910 /*                                                                        */
911 /*    mdns_ptr                              Pointer to mDNS instance      */
912 /*    cache_full_notify                     Cache full notify function    */
913 /*                                                                        */
914 /*  OUTPUT                                                                */
915 /*                                                                        */
916 /*    status                                Completion status             */
917 /*                                                                        */
918 /*  CALLS                                                                 */
919 /*                                                                        */
920 /*    _nx_mdns_cache_notify_clear           Actual cache notify           */
921 /*                                            clear function              */
922 /*                                                                        */
923 /*  CALLED BY                                                             */
924 /*                                                                        */
925 /*    Application Code                                                    */
926 /*                                                                        */
927 /*  RELEASE HISTORY                                                       */
928 /*                                                                        */
929 /*    DATE              NAME                      DESCRIPTION             */
930 /*                                                                        */
931 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
932 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
933 /*                                            resulting in version 6.1    */
934 /*                                                                        */
935 /**************************************************************************/
_nxe_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)936 UINT _nxe_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
937 {
938 
939 UINT    status;
940 
941 
942     /* Check for invalid input pointers.  */
943     if (!mdns_ptr)
944     {
945         return(NX_PTR_ERROR);
946     }
947 
948     /* Check for invalid non pointer input. */
949     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
950     {
951         return(NX_MDNS_PARAM_ERROR);
952     }
953 
954     /* Call actual mDNS cache notify clear function.  */
955     status =  _nx_mdns_cache_notify_clear(mdns_ptr);
956 
957     /* Return status.  */
958     return(status);
959 }
960 
961 
962 /**************************************************************************/
963 /*                                                                        */
964 /*  FUNCTION                                               RELEASE        */
965 /*                                                                        */
966 /*    _nx_mdns_cache_notify_clear                         PORTABLE C      */
967 /*                                                           6.1          */
968 /*  AUTHOR                                                                */
969 /*                                                                        */
970 /*    Yuxin Zhou, Microsoft Corporation                                   */
971 /*                                                                        */
972 /*  DESCRIPTION                                                           */
973 /*                                                                        */
974 /*    This function set the cache full notify function.                   */
975 /*                                                                        */
976 /*  INPUT                                                                 */
977 /*                                                                        */
978 /*    mdns_ptr                              Pointer to mDNS instance      */
979 /*                                                                        */
980 /*  OUTPUT                                                                */
981 /*                                                                        */
982 /*    status                                Completion status             */
983 /*                                                                        */
984 /*  CALLS                                                                 */
985 /*                                                                        */
986 /*    tx_mutex_get                          Get the mDNS mutex            */
987 /*    tx_mutex_put                          Put the mDNS mutex            */
988 /*                                                                        */
989 /*  CALLED BY                                                             */
990 /*                                                                        */
991 /*    Application Code                                                    */
992 /*                                                                        */
993 /*  RELEASE HISTORY                                                       */
994 /*                                                                        */
995 /*    DATE              NAME                      DESCRIPTION             */
996 /*                                                                        */
997 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
998 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
999 /*                                            resulting in version 6.1    */
1000 /*                                                                        */
1001 /**************************************************************************/
_nx_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)1002 UINT _nx_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
1003 {
1004 
1005 
1006     /* Get the mDNS mutex.  */
1007     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1008 
1009     /* Clear the cache notify.  */
1010     mdns_ptr -> nx_mdns_cache_full_notify = NX_NULL;
1011 
1012     /* Release the mDNS mutex.  */
1013     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1014 
1015     return(NX_MDNS_SUCCESS);
1016 }
1017 
1018 
1019 #ifndef NX_MDNS_DISABLE_CLIENT
1020 /**************************************************************************/
1021 /*                                                                        */
1022 /*  FUNCTION                                               RELEASE        */
1023 /*                                                                        */
1024 /*    _nxe_mdns_service_ignore_set                        PORTABLE C      */
1025 /*                                                           6.1          */
1026 /*  AUTHOR                                                                */
1027 /*                                                                        */
1028 /*    Yuxin Zhou, Microsoft Corporation                                   */
1029 /*                                                                        */
1030 /*  DESCRIPTION                                                           */
1031 /*                                                                        */
1032 /*    This function checks for errors in the mDNS service ignore mask     */
1033 /*    set function call.                                                  */
1034 /*                                                                        */
1035 /*  INPUT                                                                 */
1036 /*                                                                        */
1037 /*    mdns_ptr                              Pointer to mDNS instance      */
1038 /*    service_mask                          The service mask              */
1039 /*                                                                        */
1040 /*  OUTPUT                                                                */
1041 /*                                                                        */
1042 /*    status                                Completion status             */
1043 /*                                                                        */
1044 /*  CALLS                                                                 */
1045 /*                                                                        */
1046 /*    _nx_mdns_service_ignore_set           Actual ignore set function    */
1047 /*                                                                        */
1048 /*  CALLED BY                                                             */
1049 /*                                                                        */
1050 /*    Application Code                                                    */
1051 /*                                                                        */
1052 /*  RELEASE HISTORY                                                       */
1053 /*                                                                        */
1054 /*    DATE              NAME                      DESCRIPTION             */
1055 /*                                                                        */
1056 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1057 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1058 /*                                            resulting in version 6.1    */
1059 /*                                                                        */
1060 /**************************************************************************/
_nxe_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1061 UINT _nxe_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1062 {
1063 
1064 UINT    status;
1065 
1066 
1067     /* Check for invalid input pointers.  */
1068     if (!mdns_ptr)
1069     {
1070         return(NX_PTR_ERROR);
1071     }
1072 
1073     /* Check for invalid non pointer input. */
1074     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1075     {
1076         return(NX_MDNS_PARAM_ERROR);
1077     }
1078 
1079     /* Call actual mDNS service ignore mask set function.  */
1080     status =  _nx_mdns_service_ignore_set(mdns_ptr, service_mask);
1081 
1082     /* Return status.  */
1083     return(status);
1084 }
1085 
1086 
1087 /**************************************************************************/
1088 /*                                                                        */
1089 /*  FUNCTION                                               RELEASE        */
1090 /*                                                                        */
1091 /*    _nx_mdns_service_ignore_set                         PORTABLE C      */
1092 /*                                                           6.1          */
1093 /*  AUTHOR                                                                */
1094 /*                                                                        */
1095 /*    Yuxin Zhou, Microsoft Corporation                                   */
1096 /*                                                                        */
1097 /*  DESCRIPTION                                                           */
1098 /*                                                                        */
1099 /*    This function sets the service mask to ignore the service.          */
1100 /*                                                                        */
1101 /*  INPUT                                                                 */
1102 /*                                                                        */
1103 /*    mdns_ptr                              Pointer to mDNS instance      */
1104 /*    service_mask                          The service mask              */
1105 /*                                                                        */
1106 /*  OUTPUT                                                                */
1107 /*                                                                        */
1108 /*    status                                Completion status             */
1109 /*                                                                        */
1110 /*  CALLS                                                                 */
1111 /*                                                                        */
1112 /*    tx_mutex_get                          Get the MDNS mutex            */
1113 /*    tx_mutex_put                          Put the MDNS mutex            */
1114 /*                                                                        */
1115 /*  CALLED BY                                                             */
1116 /*                                                                        */
1117 /*    Application Code                                                    */
1118 /*                                                                        */
1119 /*  RELEASE HISTORY                                                       */
1120 /*                                                                        */
1121 /*    DATE              NAME                      DESCRIPTION             */
1122 /*                                                                        */
1123 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1124 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1125 /*                                            resulting in version 6.1    */
1126 /*                                                                        */
1127 /**************************************************************************/
_nx_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1128 UINT _nx_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1129 {
1130 
1131 
1132     /* Get the mDNS mutex.  */
1133     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1134 
1135     /* Set the service ignore mask.  */
1136     mdns_ptr -> nx_mdns_service_ignore_mask = service_mask;
1137 
1138     /* Release the mDNS mutex.  */
1139     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1140 
1141     return(NX_MDNS_SUCCESS);
1142 }
1143 
1144 
1145 /**************************************************************************/
1146 /*                                                                        */
1147 /*  FUNCTION                                               RELEASE        */
1148 /*                                                                        */
1149 /*    _nxe_mdns_service_notify_set                        PORTABLE C      */
1150 /*                                                           6.1          */
1151 /*  AUTHOR                                                                */
1152 /*                                                                        */
1153 /*    Yuxin Zhou, Microsoft Corporation                                   */
1154 /*                                                                        */
1155 /*  DESCRIPTION                                                           */
1156 /*                                                                        */
1157 /*    This function checks for errors in the mDNS service notify function */
1158 /*    call.                                                               */
1159 /*                                                                        */
1160 /*  INPUT                                                                 */
1161 /*                                                                        */
1162 /*    mdns_ptr                              Pointer to mDNS instance      */
1163 /*    service_mask                          The service mask              */
1164 /*    service_change_notify                 Service change notify function*/
1165 /*                                                                        */
1166 /*  OUTPUT                                                                */
1167 /*                                                                        */
1168 /*    status                                Completion status             */
1169 /*                                                                        */
1170 /*  CALLS                                                                 */
1171 /*                                                                        */
1172 /*    _nx_mdns_service_notify_set           Actual mDNS service notify    */
1173 /*                                            set function                */
1174 /*                                                                        */
1175 /*  CALLED BY                                                             */
1176 /*                                                                        */
1177 /*    Application Code                                                    */
1178 /*                                                                        */
1179 /*  RELEASE HISTORY                                                       */
1180 /*                                                                        */
1181 /*    DATE              NAME                      DESCRIPTION             */
1182 /*                                                                        */
1183 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1184 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1185 /*                                            resulting in version 6.1    */
1186 /*                                                                        */
1187 /**************************************************************************/
_nxe_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1188 UINT _nxe_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1189                                   VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1190 {
1191 
1192 UINT    status;
1193 
1194 
1195     /* Check for invalid input pointers.  */
1196     if (!mdns_ptr)
1197     {
1198         return(NX_PTR_ERROR);
1199     }
1200 
1201     /* Check for invalid non pointer input. */
1202     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1203     {
1204         return(NX_MDNS_PARAM_ERROR);
1205     }
1206 
1207     /* Call actual mDNS service notify set function.  */
1208     status =  _nx_mdns_service_notify_set(mdns_ptr, service_mask, service_change_notify);
1209 
1210     /* Return status.  */
1211     return(status);
1212 }
1213 
1214 
1215 /**************************************************************************/
1216 /*                                                                        */
1217 /*  FUNCTION                                               RELEASE        */
1218 /*                                                                        */
1219 /*    _nx_mdns_service_notify_set                         PORTABLE C      */
1220 /*                                                           6.1          */
1221 /*  AUTHOR                                                                */
1222 /*                                                                        */
1223 /*    Yuxin Zhou, Microsoft Corporation                                   */
1224 /*                                                                        */
1225 /*  DESCRIPTION                                                           */
1226 /*                                                                        */
1227 /*    This function set the service mask and notify callback function.    */
1228 /*                                                                        */
1229 /*  INPUT                                                                 */
1230 /*                                                                        */
1231 /*    mdns_ptr                              Pointer to mDNS instance      */
1232 /*    service_mask                          The service mask              */
1233 /*    service_change_notify                 Service change notify function*/
1234 /*                                                                        */
1235 /*  OUTPUT                                                                */
1236 /*                                                                        */
1237 /*    status                                Completion status             */
1238 /*                                                                        */
1239 /*  CALLS                                                                 */
1240 /*                                                                        */
1241 /*    tx_mutex_get                          Get the mDNS mutex            */
1242 /*    tx_mutex_put                          Put the mDNS mutex            */
1243 /*                                                                        */
1244 /*  CALLED BY                                                             */
1245 /*                                                                        */
1246 /*    Application Code                                                    */
1247 /*                                                                        */
1248 /*  RELEASE HISTORY                                                       */
1249 /*                                                                        */
1250 /*    DATE              NAME                      DESCRIPTION             */
1251 /*                                                                        */
1252 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1253 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1254 /*                                            resulting in version 6.1    */
1255 /*                                                                        */
1256 /**************************************************************************/
_nx_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1257 UINT _nx_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1258                                  VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1259 {
1260 
1261 
1262     /* Get the mDNS mutex.  */
1263     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1264 
1265     /* Set the service mask.  */
1266     mdns_ptr -> nx_mdns_service_notify_mask = service_mask;
1267 
1268     /* Assign the service change notify. */
1269     mdns_ptr -> nx_mdns_service_change_notify = service_change_notify;
1270 
1271     /* Release the mDNS mutex.  */
1272     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1273 
1274     return(NX_MDNS_SUCCESS);
1275 }
1276 
1277 
1278 /**************************************************************************/
1279 /*                                                                        */
1280 /*  FUNCTION                                               RELEASE        */
1281 /*                                                                        */
1282 /*    _nxe_mdns_service_notify_clear                      PORTABLE C      */
1283 /*                                                           6.1          */
1284 /*  AUTHOR                                                                */
1285 /*                                                                        */
1286 /*    Yuxin Zhou, Microsoft Corporation                                   */
1287 /*                                                                        */
1288 /*  DESCRIPTION                                                           */
1289 /*                                                                        */
1290 /*    This function checks for errors in the mDNS service notify function */
1291 /*    call.                                                               */
1292 /*                                                                        */
1293 /*  INPUT                                                                 */
1294 /*                                                                        */
1295 /*    mdns_ptr                              Pointer to mDNS instance      */
1296 /*                                                                        */
1297 /*  OUTPUT                                                                */
1298 /*                                                                        */
1299 /*    status                                Completion status             */
1300 /*                                                                        */
1301 /*  CALLS                                                                 */
1302 /*                                                                        */
1303 /*    _nx_mdns_service_notify_clear         Actual service notify         */
1304 /*                                            clear function              */
1305 /*                                                                        */
1306 /*  CALLED BY                                                             */
1307 /*                                                                        */
1308 /*    Application Code                                                    */
1309 /*                                                                        */
1310 /*  RELEASE HISTORY                                                       */
1311 /*                                                                        */
1312 /*    DATE              NAME                      DESCRIPTION             */
1313 /*                                                                        */
1314 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1315 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1316 /*                                            resulting in version 6.1    */
1317 /*                                                                        */
1318 /**************************************************************************/
_nxe_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1319 UINT _nxe_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1320 {
1321 
1322 UINT    status;
1323 
1324 
1325     /* Check for invalid input pointers.  */
1326     if (!mdns_ptr)
1327     {
1328 
1329         return(NX_PTR_ERROR);
1330     }
1331 
1332     /* Check for invalid non pointer input. */
1333     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1334     {
1335 
1336         return(NX_MDNS_PARAM_ERROR);
1337     }
1338 
1339     /* Call actual mDNS service notify clear function.  */
1340     status =  _nx_mdns_service_notify_clear(mdns_ptr);
1341 
1342     /* Return status.  */
1343     return(status);
1344 }
1345 
1346 
1347 /**************************************************************************/
1348 /*                                                                        */
1349 /*  FUNCTION                                               RELEASE        */
1350 /*                                                                        */
1351 /*    _nx_mdns_service_notify_clear                       PORTABLE C      */
1352 /*                                                           6.1          */
1353 /*  AUTHOR                                                                */
1354 /*                                                                        */
1355 /*    Yuxin Zhou, Microsoft Corporation                                   */
1356 /*                                                                        */
1357 /*  DESCRIPTION                                                           */
1358 /*                                                                        */
1359 /*    This function clears the service mask and notify callback function. */
1360 /*                                                                        */
1361 /*  INPUT                                                                 */
1362 /*                                                                        */
1363 /*    mdns_ptr                              Pointer to mDNS instance      */
1364 /*                                                                        */
1365 /*  OUTPUT                                                                */
1366 /*                                                                        */
1367 /*    status                                Completion status             */
1368 /*                                                                        */
1369 /*  CALLS                                                                 */
1370 /*                                                                        */
1371 /*    tx_mutex_get                          Get the mDNS mutex            */
1372 /*    tx_mutex_put                          Put the mDNS mutex            */
1373 /*                                                                        */
1374 /*  CALLED BY                                                             */
1375 /*                                                                        */
1376 /*    Application Code                                                    */
1377 /*                                                                        */
1378 /*  RELEASE HISTORY                                                       */
1379 /*                                                                        */
1380 /*    DATE              NAME                      DESCRIPTION             */
1381 /*                                                                        */
1382 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1383 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1384 /*                                            resulting in version 6.1    */
1385 /*                                                                        */
1386 /**************************************************************************/
_nx_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1387 UINT _nx_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1388 {
1389 
1390 
1391     /* Get the mDNS mutex.  */
1392     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1393 
1394     /* Clear the service mask.  */
1395     mdns_ptr -> nx_mdns_service_notify_mask = 0;
1396 
1397     /* Clear the service change notify. */
1398     mdns_ptr -> nx_mdns_service_change_notify = NX_NULL;
1399 
1400     /* Release the mDNS mutex.  */
1401     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1402 
1403     return(NX_MDNS_SUCCESS);
1404 }
1405 #endif /* NX_MDNS_DISABLE_CLIENT  */
1406 
1407 
1408 #ifndef NX_MDNS_DISABLE_SERVER
1409 /**************************************************************************/
1410 /*                                                                        */
1411 /*  FUNCTION                                               RELEASE        */
1412 /*                                                                        */
1413 /*    _nxe_mdns_service_announcement_timing_set           PORTABLE C      */
1414 /*                                                           6.1          */
1415 /*  AUTHOR                                                                */
1416 /*                                                                        */
1417 /*    Yuxin Zhou, Microsoft Corporation                                   */
1418 /*                                                                        */
1419 /*  DESCRIPTION                                                           */
1420 /*                                                                        */
1421 /*    This function checks for errors in the mDNS announcement timing     */
1422 /*    set function call.                                                  */
1423 /*                                                                        */
1424 /*  INPUT                                                                 */
1425 /*                                                                        */
1426 /*    mdns_ptr                              Pointer to mDNS instance      */
1427 /*    t                                     Announcing period             */
1428 /*    p                                     Announcing count              */
1429 /*    k                                     Announcing factor             */
1430 /*    retrans_interval                      Announcing retransmission     */
1431 /*                                            interval                    */
1432 /*    interval                              Announcing period interval    */
1433 /*    max_time                              Announcing max time           */
1434 /*                                                                        */
1435 /*  OUTPUT                                                                */
1436 /*                                                                        */
1437 /*    status                                Completion status             */
1438 /*                                                                        */
1439 /*  CALLS                                                                 */
1440 /*                                                                        */
1441 /*    _nx_mdns_service_announcement_timing_set                            */
1442 /*                                          Actual mDNS announcement      */
1443 /*                                            timing set function         */
1444 /*                                                                        */
1445 /*  CALLED BY                                                             */
1446 /*                                                                        */
1447 /*    Application Code                                                    */
1448 /*                                                                        */
1449 /*  RELEASE HISTORY                                                       */
1450 /*                                                                        */
1451 /*    DATE              NAME                      DESCRIPTION             */
1452 /*                                                                        */
1453 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1454 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1455 /*                                            resulting in version 6.1    */
1456 /*                                                                        */
1457 /**************************************************************************/
_nxe_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1458 UINT _nxe_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1459 {
1460 
1461 UINT    status;
1462 
1463 
1464     /* Check for invalid input pointers.  */
1465     if ((!mdns_ptr) || (!t) || (!p) || (!k) || (!period_interval) || (!max_time))
1466     {
1467         return(NX_PTR_ERROR);
1468     }
1469 
1470     /* Check for invalid non pointer input. */
1471     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1472     {
1473         return(NX_MDNS_PARAM_ERROR);
1474     }
1475 
1476     /* Call actual mDNS delete service.  */
1477     status =  _nx_mdns_service_announcement_timing_set(mdns_ptr, t, p, k, retrans_interval, period_interval, max_time);
1478 
1479     /* Return status.  */
1480     return(status);
1481 }
1482 
1483 
1484 /**************************************************************************/
1485 /*                                                                        */
1486 /*  FUNCTION                                               RELEASE        */
1487 /*                                                                        */
1488 /*    _nx_mdns_service_announcement_timing_set            PORTABLE C      */
1489 /*                                                           6.1          */
1490 /*  AUTHOR                                                                */
1491 /*                                                                        */
1492 /*    Yuxin Zhou, Microsoft Corporation                                   */
1493 /*                                                                        */
1494 /*  DESCRIPTION                                                           */
1495 /*                                                                        */
1496 /*    This function set the service mask and notify callback function.    */
1497 /*                                                                        */
1498 /*  INPUT                                                                 */
1499 /*                                                                        */
1500 /*    mdns_ptr                              Pointer to mDNS instance      */
1501 /*    t                                     Announcing period             */
1502 /*    p                                     Announcing count              */
1503 /*    k                                     Announcing factor             */
1504 /*    retrans_interval                      Announcing retransmission     */
1505 /*                                            interval                    */
1506 /*    interval                              Announcing period interval    */
1507 /*    max_time                              Announcing max time           */
1508 /*                                                                        */
1509 /*  OUTPUT                                                                */
1510 /*                                                                        */
1511 /*    status                                Completion status             */
1512 /*                                                                        */
1513 /*  CALLS                                                                 */
1514 /*                                                                        */
1515 /*    tx_mutex_get                          Get the mDNS mutex            */
1516 /*    tx_mutex_put                          Put the mDNS mutex            */
1517 /*                                                                        */
1518 /*  CALLED BY                                                             */
1519 /*                                                                        */
1520 /*    Application Code                                                    */
1521 /*                                                                        */
1522 /*  RELEASE HISTORY                                                       */
1523 /*                                                                        */
1524 /*    DATE              NAME                      DESCRIPTION             */
1525 /*                                                                        */
1526 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1527 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1528 /*                                            resulting in version 6.1    */
1529 /*                                                                        */
1530 /**************************************************************************/
_nx_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1531 UINT _nx_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1532 {
1533 
1534 
1535     /* Get the mDNS mutex.  */
1536     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1537 
1538     /* Set the mDNS announcing period.  */
1539     mdns_ptr -> nx_mdns_announcing_period = (USHORT)t;
1540 
1541     /* Set the mDNS announcing count between one announcing period.  */
1542     mdns_ptr -> nx_mdns_announcing_count = (UCHAR)p;
1543 
1544     /* Set the mDNS announcing factor.  */
1545     mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)k;
1546 
1547     /* Set the mDNS announcing retransmission interval.  */
1548     mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)retrans_interval;
1549 
1550     /* Set the mDNS announcing period interval.  */
1551     mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)period_interval;
1552 
1553     /* Set the mDNS announcing max time.  */
1554     mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)max_time;
1555 
1556     /* Release the mDNS mutex.  */
1557     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1558 
1559     return(NX_MDNS_SUCCESS);
1560 }
1561 #endif /* NX_MDNS_DISABLE_SERVER  */
1562 
1563 
1564 /**************************************************************************/
1565 /*                                                                        */
1566 /*  FUNCTION                                               RELEASE        */
1567 /*                                                                        */
1568 /*    _nxe_mdns_enable                                    PORTABLE C      */
1569 /*                                                           6.1          */
1570 /*  AUTHOR                                                                */
1571 /*                                                                        */
1572 /*    Yuxin Zhou, Microsoft Corporation                                   */
1573 /*                                                                        */
1574 /*  DESCRIPTION                                                           */
1575 /*                                                                        */
1576 /*    This function checks for errors in the mDNS enable function call.   */
1577 /*                                                                        */
1578 /*  INPUT                                                                 */
1579 /*                                                                        */
1580 /*    mdns_ptr                              Pointer to mDNS instance      */
1581 /*    interface_index                       The interface index           */
1582 /*                                                                        */
1583 /*  OUTPUT                                                                */
1584 /*                                                                        */
1585 /*    status                                Completion status             */
1586 /*                                                                        */
1587 /*  CALLS                                                                 */
1588 /*                                                                        */
1589 /*    _nx_mdns_enable                       Actual mDNS enable function   */
1590 /*                                                                        */
1591 /*  CALLED BY                                                             */
1592 /*                                                                        */
1593 /*    Application Code                                                    */
1594 /*                                                                        */
1595 /*  RELEASE HISTORY                                                       */
1596 /*                                                                        */
1597 /*    DATE              NAME                      DESCRIPTION             */
1598 /*                                                                        */
1599 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1600 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1601 /*                                            resulting in version 6.1    */
1602 /*                                                                        */
1603 /**************************************************************************/
_nxe_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1604 UINT _nxe_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1605 {
1606 
1607 UINT    status;
1608 
1609 
1610     /* Check for invalid input pointers.  */
1611     if (!mdns_ptr)
1612     {
1613         return(NX_PTR_ERROR);
1614     }
1615 
1616     /* Check for invalid non pointer input or invalid server attributes. */
1617     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1618     {
1619         return(NX_MDNS_PARAM_ERROR);
1620     }
1621 
1622     /* Call actual mDNS delete service.  */
1623     status =  _nx_mdns_enable(mdns_ptr, interface_index);
1624 
1625     /* Return status.  */
1626     return(status);
1627 }
1628 
1629 
1630 /**************************************************************************/
1631 /*                                                                        */
1632 /*  FUNCTION                                               RELEASE        */
1633 /*                                                                        */
1634 /*    _nx_mdns_enable                                     PORTABLE C      */
1635 /*                                                           6.1          */
1636 /*  AUTHOR                                                                */
1637 /*                                                                        */
1638 /*    Yuxin Zhou, Microsoft Corporation                                   */
1639 /*                                                                        */
1640 /*  DESCRIPTION                                                           */
1641 /*                                                                        */
1642 /*    This function enables the mDNS of the physical host interface by    */
1643 /*    interface index.                                                    */
1644 /*                                                                        */
1645 /*  INPUT                                                                 */
1646 /*                                                                        */
1647 /*    mdns_ptr                              Pointer to mDNS instance      */
1648 /*    interface_index                       The interface index           */
1649 /*                                                                        */
1650 /*  OUTPUT                                                                */
1651 /*                                                                        */
1652 /*    status                                Completion status             */
1653 /*                                                                        */
1654 /*  CALLS                                                                 */
1655 /*                                                                        */
1656 /*    tx_mutex_get                          Get the mDNS mutex            */
1657 /*    tx_mutex_put                          Put the mDNS mutex            */
1658 /*    nx_ipv4_multicast_interface_join      Join the IPv4 Multicast group */
1659 /*    nxd_ipv6_multicast_interface_join     Join the IPv6 Multicast group */
1660 /*    _nx_mdns_host_name_register           Register the host name        */
1661 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
1662 /*                                                                        */
1663 /*  CALLED BY                                                             */
1664 /*                                                                        */
1665 /*    Application Code                                                    */
1666 /*                                                                        */
1667 /*  RELEASE HISTORY                                                       */
1668 /*                                                                        */
1669 /*    DATE              NAME                      DESCRIPTION             */
1670 /*                                                                        */
1671 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1672 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1673 /*                                            resulting in version 6.1    */
1674 /*                                                                        */
1675 /**************************************************************************/
_nx_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1676 UINT _nx_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1677 {
1678 
1679 UINT        status;
1680 
1681 #ifndef NX_MDNS_DISABLE_SERVER
1682 ULONG       *head;
1683 NX_MDNS_RR  *p;
1684 #endif /* NX_MDNS_DISABLE_SERVER */
1685 
1686 #ifdef NX_MDNS_ENABLE_IPV6
1687 NX_INTERFACE        *interface_ptr;
1688 NXD_IPV6_ADDRESS    *ipv6_address;
1689 #endif /* NX_MDNS_ENABLE_IPV6  */
1690 
1691     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1692     {
1693         return(NX_MDNS_PARAM_ERROR);
1694     }
1695 
1696     /* Check to see if mDNS is already enabled on this interface.  */
1697     if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_TRUE)
1698     {
1699         return(NX_MDNS_ALREADY_ENABLED);
1700     }
1701 
1702     /* Get the mDNS mutex.  */
1703     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1704 
1705     /* Enable the mdns function.  */
1706     mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_TRUE;
1707 
1708 #ifdef NX_MDNS_ENABLE_IPV6
1709     /* Set the interface pointer.  */
1710     interface_ptr = &(mdns_ptr -> nx_mdns_ip_ptr -> nx_ip_interface[interface_index]);
1711 
1712     /* Find the link-local address as source adress. Get first address from interface.  */
1713     ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
1714 
1715     /* Loop to check the address.  */
1716     while (ipv6_address)
1717     {
1718 
1719         /* Check for link-local address. */
1720         if (IPv6_Address_Type(ipv6_address -> nxd_ipv6_address) & IPV6_ADDRESS_LINKLOCAL)
1721         {
1722             break;
1723         }
1724         ipv6_address = ipv6_address -> nxd_ipv6_address_next;
1725     }
1726 
1727     /* Check if found the link-local address.  */
1728     if(ipv6_address)
1729     {
1730 
1731         /* Set the IPv6 link-local address index.  */
1732         mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = ipv6_address -> nxd_ipv6_address_index;
1733     }
1734     else
1735     {
1736 
1737         /* No available address, set the address index as 0xFFFFFFFF.  */
1738         mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = 0xFFFFFFFF;
1739     }
1740 #endif /* NX_MDNS_ENABLE_IPV6  */
1741 
1742     /* Join the group.  */
1743     status = nx_ipv4_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
1744 
1745     /* Check status.  */
1746     if (status)
1747     {
1748 
1749         /* Release the mDNS mutex.  */
1750         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1751         return(status);
1752     }
1753 
1754 #ifdef NX_MDNS_ENABLE_IPV6
1755     status = nxd_ipv6_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
1756 
1757     /* Check status.  */
1758     if (status)
1759     {
1760 
1761         /* Release the mDNS mutex.  */
1762         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1763         return(status);
1764     }
1765 #endif /* NX_MDNS_ENABLE_IPV6  */
1766 
1767 #ifndef NX_MDNS_DISABLE_SERVER
1768 
1769     /* Register the host name.  */
1770     status = _nx_mdns_host_name_register(mdns_ptr, NX_TRUE, interface_index);
1771 
1772     /* Check status.  */
1773     if (status)
1774     {
1775 
1776         /* Release the mDNS mutex.  */
1777         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1778         return(status);
1779     }
1780 
1781     /* Probing the all resource record wheneven a Multicast DNS responder starts up, waks up from sleep, receives an indication of a network interface "Link CHange" event.RFC6762, Section8, Page25.   */
1782 
1783     /* Get the header to the local buffer. */
1784     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
1785 
1786     /* Set the pointer.  */
1787     head = (ULONG*)(*head);
1788 
1789     /* Check the resource record.  */
1790     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
1791     {
1792 
1793         /* Check the interface index.  */
1794         if (p -> nx_mdns_rr_interface_index != interface_index)
1795             continue;
1796 
1797         /* Check whether the resource record is valid. */
1798         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
1799             continue;
1800 
1801         /* Check the state and delete flag, GOODBYE state and DELETE FLAG means this resource record should be deleted.  */
1802         if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) &&
1803             (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE))
1804         {
1805 
1806             /* Delete the resource records.  */
1807             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
1808             continue;
1809         }
1810 
1811         /* Check the resource reocrd type.  */
1812         if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) ||
1813             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))
1814         {
1815             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
1816             continue;
1817         }
1818 
1819         /* Check the unique flag.  */
1820         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
1821         {
1822             /* For a unique type, we need to probe it on the network
1823             to guarantee its uniqueness. */
1824             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
1825             p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
1826             p -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
1827         }
1828         else
1829         {
1830             /* If the record is not marked as unique, start the announcement process. */
1831             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
1832             p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
1833             p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
1834 
1835             /* Check the announcing max time.  */
1836             if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
1837                 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
1838             else
1839                 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
1840 
1841             /* Set the retransmit count.  */
1842             if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
1843                 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
1844             else
1845                 p -> nx_mdns_rr_retransmit_count = 1;
1846         }
1847 
1848         /* Set the mDNS timer.  */
1849         _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
1850     }
1851 #endif /* NX_MDNS_DISABLE_SERVER */
1852 
1853     /* Set the mdns started flag.  */
1854     mdns_ptr -> nx_mdns_started = NX_TRUE;
1855 
1856     /* Release the mDNS mutex.  */
1857     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1858 
1859     /* Return.  */
1860     return(NX_MDNS_SUCCESS);
1861 }
1862 
1863 
1864 /**************************************************************************/
1865 /*                                                                        */
1866 /*  FUNCTION                                               RELEASE        */
1867 /*                                                                        */
1868 /*    _nxe_mdns_disable                                   PORTABLE C      */
1869 /*                                                           6.1          */
1870 /*  AUTHOR                                                                */
1871 /*                                                                        */
1872 /*    Yuxin Zhou, Microsoft Corporation                                   */
1873 /*                                                                        */
1874 /*  DESCRIPTION                                                           */
1875 /*                                                                        */
1876 /*    This function checks for errors in the mDNS disable function call.  */
1877 /*                                                                        */
1878 /*  INPUT                                                                 */
1879 /*                                                                        */
1880 /*    mdns_ptr                              Pointer to mDNS instance      */
1881 /*    interface_index                       The interface index           */
1882 /*                                                                        */
1883 /*  OUTPUT                                                                */
1884 /*                                                                        */
1885 /*    status                                Completion status             */
1886 /*                                                                        */
1887 /*  CALLS                                                                 */
1888 /*                                                                        */
1889 /*    _nx_mdns_disable                      Actual mDNS disable function  */
1890 /*                                                                        */
1891 /*  CALLED BY                                                             */
1892 /*                                                                        */
1893 /*    Application Code                                                    */
1894 /*                                                                        */
1895 /*  RELEASE HISTORY                                                       */
1896 /*                                                                        */
1897 /*    DATE              NAME                      DESCRIPTION             */
1898 /*                                                                        */
1899 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1900 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1901 /*                                            resulting in version 6.1    */
1902 /*                                                                        */
1903 /**************************************************************************/
_nxe_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1904 UINT _nxe_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1905 {
1906 
1907 UINT    status;
1908 
1909 
1910     /* Check for invalid input pointers.  */
1911     if (!mdns_ptr)
1912     {
1913         return(NX_PTR_ERROR);
1914     }
1915 
1916     /* Check for invalid non pointer input or invalid server attributes. */
1917     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1918     {
1919         return(NX_MDNS_PARAM_ERROR);
1920     }
1921 
1922     /* Call actual mDNS delete service.  */
1923     status =  _nx_mdns_disable(mdns_ptr, interface_index);
1924 
1925     /* Return status.  */
1926     return(status);
1927 }
1928 
1929 
1930 /**************************************************************************/
1931 /*                                                                        */
1932 /*  FUNCTION                                               RELEASE        */
1933 /*                                                                        */
1934 /*    _nx_mdns_disable                                    PORTABLE C      */
1935 /*                                                           6.1          */
1936 /*  AUTHOR                                                                */
1937 /*                                                                        */
1938 /*    Yuxin Zhou, Microsoft Corporation                                   */
1939 /*                                                                        */
1940 /*  DESCRIPTION                                                           */
1941 /*                                                                        */
1942 /*    This function disables the mDNS of the physical host interface by   */
1943 /*    interface index.                                                    */
1944 /*                                                                        */
1945 /*  INPUT                                                                 */
1946 /*                                                                        */
1947 /*    mdns_ptr                              Pointer to mDNS instance      */
1948 /*    interface_index                       The interface index           */
1949 /*                                                                        */
1950 /*  OUTPUT                                                                */
1951 /*                                                                        */
1952 /*    status                                Completion status             */
1953 /*                                                                        */
1954 /*  CALLS                                                                 */
1955 /*                                                                        */
1956 /*    tx_mutex_get                          Get the mDNS mutex            */
1957 /*    tx_mutex_put                          Put the mDNS mutex            */
1958 /*    nx_ipv4_multicast_leave               Leave the IPv4 Multicast group*/
1959 /*    nxd_ipv6_multicast_interface_leave    Leave the IPv6 Multicast group*/
1960 /*    _nx_mdns_cache_initialize             Initialize the mDNS peer cache*/
1961 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
1962 /*                                                                        */
1963 /*  CALLED BY                                                             */
1964 /*                                                                        */
1965 /*    Application Code                                                    */
1966 /*                                                                        */
1967 /*  RELEASE HISTORY                                                       */
1968 /*                                                                        */
1969 /*    DATE              NAME                      DESCRIPTION             */
1970 /*                                                                        */
1971 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1972 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1973 /*                                            resulting in version 6.1    */
1974 /*                                                                        */
1975 /**************************************************************************/
_nx_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1976 UINT _nx_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1977 {
1978 
1979 UINT        dns_sd_size;
1980 UINT        i;
1981 ULONG       *head;
1982 NX_MDNS_RR  *p;
1983 
1984 
1985     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1986     {
1987         return(NX_MDNS_PARAM_ERROR);
1988     }
1989 
1990     /* Check to see if mDNS is not enabled on this interface.
1991        Note: Only support one interface yet.  */
1992     if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_FALSE)
1993     {
1994         return(NX_MDNS_NOT_ENABLED);
1995     }
1996 
1997     /* Check the DNS-SD string.  */
1998     if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_size, NX_MDNS_DNS_SD_MAX))
1999     {
2000         return(NX_MDNS_DATA_SIZE_ERROR);
2001     }
2002 
2003     /* Get the mDNS mutex.  */
2004     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2005 
2006     /* Disable the mdns function.  */
2007     mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_FALSE;
2008 
2009     /* Leave the group.  */
2010     nx_ipv4_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
2011 
2012 #ifdef NX_MDNS_ENABLE_IPV6
2013     nxd_ipv6_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
2014 #endif /* NX_MDNS_ENABLE_IPV6  */
2015 
2016 #ifndef NX_MDNS_DISABLE_CLIENT
2017 
2018     /* Get the local buffer head. */
2019     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
2020 
2021     /* Set the pointer.  */
2022     head = (ULONG*)(*head);
2023 
2024     /* Delete all services on this interface.  */
2025     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2026     {
2027 
2028         /* Check whether the resource record is valid. */
2029         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2030             continue;
2031 
2032         /* Check the interface index.  */
2033         if (p -> nx_mdns_rr_interface_index != interface_index)
2034             continue;
2035 
2036         /* Delete the resource record.  */
2037         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
2038     }
2039 #endif /* NX_MDNS_DISABLE_CLIENT */
2040 
2041 #ifndef NX_MDNS_DISABLE_SERVER
2042 
2043     /* Get the local buffer head. */
2044     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2045 
2046     /* Set the pointer.  */
2047     head = (ULONG*)(*head);
2048 
2049     /* Send the Goodbye message, RFC6762, Section10.1, Page33.  */
2050     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2051     {
2052 
2053         /* Check whether the resource record is valid. */
2054         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2055             continue;
2056 
2057         /* Check the interface index.  */
2058         if (p -> nx_mdns_rr_interface_index != interface_index)
2059             continue;
2060 
2061         /* Skip the NSEC and DNS-SD PTR resource record.  */
2062         if ((p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) ||
2063             ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
2064              (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_size))))
2065         {
2066 
2067             /* Suspend the resource record.  */
2068             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
2069         }
2070         else
2071         {
2072 
2073             /* Set the state to send Goodbye packet.  */
2074             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
2075 
2076             /* Clear the retransmit count.  */
2077             p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
2078 
2079             /* Set the timer count. 250ms.  */
2080             p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
2081 
2082             /* Set the mDNS timer.  */
2083             _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
2084         }
2085     }
2086 #endif /* NX_MDNS_DISABLE_SERVER */
2087 
2088     /* Check if all interfaces are disabled.  */
2089     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
2090     {
2091         if (mdns_ptr -> nx_mdns_interface_enabled[i])
2092             break;
2093     }
2094 
2095     /* Set the mdns started flag.  */
2096     if (i == NX_MAX_PHYSICAL_INTERFACES)
2097         mdns_ptr -> nx_mdns_started = NX_FALSE;
2098 
2099     /* Release the mDNS mutex.  */
2100     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2101 
2102     return(NX_MDNS_SUCCESS);
2103 }
2104 
2105 
2106 /**************************************************************************/
2107 /*                                                                        */
2108 /*  FUNCTION                                               RELEASE        */
2109 /*                                                                        */
2110 /*    _nxe_mdns_local_domain_set                          PORTABLE C      */
2111 /*                                                           6.1          */
2112 /*  AUTHOR                                                                */
2113 /*                                                                        */
2114 /*    Yuxin Zhou, Microsoft Corporation                                   */
2115 /*                                                                        */
2116 /*  DESCRIPTION                                                           */
2117 /*                                                                        */
2118 /*    This function checks for errors in the mDNS domain sets             */
2119 /*    function call.                                                      */
2120 /*                                                                        */
2121 /*  INPUT                                                                 */
2122 /*                                                                        */
2123 /*    mdns_ptr                              Pointer to mDNS instance      */
2124 /*    domain_name                           Domain name                   */
2125 /*                                                                        */
2126 /*  OUTPUT                                                                */
2127 /*                                                                        */
2128 /*    status                                Completion status             */
2129 /*                                                                        */
2130 /*  CALLS                                                                 */
2131 /*                                                                        */
2132 /*    _nx_mdns_domain_name_set              Actual domain set function    */
2133 /*                                                                        */
2134 /*  CALLED BY                                                             */
2135 /*                                                                        */
2136 /*    Application Code                                                    */
2137 /*                                                                        */
2138 /*  RELEASE HISTORY                                                       */
2139 /*                                                                        */
2140 /*    DATE              NAME                      DESCRIPTION             */
2141 /*                                                                        */
2142 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2143 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2144 /*                                            resulting in version 6.1    */
2145 /*                                                                        */
2146 /**************************************************************************/
_nxe_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2147 UINT _nxe_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2148 {
2149 
2150 UINT    status;
2151 
2152 
2153     /* Check for invalid input pointers.  */
2154     if ((!mdns_ptr) || (!domain_name))
2155     {
2156         return(NX_PTR_ERROR);
2157     }
2158 
2159     /* Check for invalid non pointer input or invalid server attributes. */
2160     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2161     {
2162         return(NX_MDNS_PARAM_ERROR);
2163     }
2164 
2165     /* Call actual mDNS domain name set service.  */
2166     status =  _nx_mdns_domain_name_set(mdns_ptr, domain_name);
2167 
2168     /* Return status.  */
2169     return(status);
2170 }
2171 
2172 
2173 /**************************************************************************/
2174 /*                                                                        */
2175 /*  FUNCTION                                               RELEASE        */
2176 /*                                                                        */
2177 /*    _nx_mdns_domain_name_set                            PORTABLE C      */
2178 /*                                                           6.1          */
2179 /*  AUTHOR                                                                */
2180 /*                                                                        */
2181 /*    Yuxin Zhou, Microsoft Corporation                                   */
2182 /*                                                                        */
2183 /*  DESCRIPTION                                                           */
2184 /*                                                                        */
2185 /*    This function sets the mDNS domain name. By default is "local".     */
2186 /*                                                                        */
2187 /*  INPUT                                                                 */
2188 /*                                                                        */
2189 /*    mdns_ptr                              Pointer to mDNS instance      */
2190 /*    domain_name                           Domain name                   */
2191 /*                                                                        */
2192 /*  OUTPUT                                                                */
2193 /*                                                                        */
2194 /*    status                                Completion status             */
2195 /*                                                                        */
2196 /*  CALLS                                                                 */
2197 /*                                                                        */
2198 /*    tx_mutex_get                          Get the mDNS mutex            */
2199 /*    tx_mutex_put                          Put the mDNS mutex            */
2200 /*                                                                        */
2201 /*  CALLED BY                                                             */
2202 /*                                                                        */
2203 /*    Application Code                                                    */
2204 /*                                                                        */
2205 /*  RELEASE HISTORY                                                       */
2206 /*                                                                        */
2207 /*    DATE              NAME                      DESCRIPTION             */
2208 /*                                                                        */
2209 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2210 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2211 /*                                            verified memcpy use cases,  */
2212 /*                                            resulting in version 6.1    */
2213 /*                                                                        */
2214 /**************************************************************************/
_nx_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2215 UINT _nx_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2216 {
2217 
2218 UINT        index;
2219 UINT        domain_name_size;
2220 
2221 
2222     /* Check the size.  */
2223     if (_nx_utility_string_length_check((CHAR *)domain_name, &domain_name_size, NX_MDNS_DOMAIN_NAME_MAX))
2224     {
2225         return(NX_MDNS_DATA_SIZE_ERROR);
2226     }
2227 
2228     /* Get the mDNS mutex.  */
2229     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2230 
2231     /* Save the new domain name.  */
2232     memcpy(&mdns_ptr -> nx_mdns_domain_name[0], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2233     mdns_ptr -> nx_mdns_domain_name[domain_name_size] = NX_NULL;
2234 
2235     /* Initialize the struct.  */
2236     memset(_nx_mdns_dns_sd, 0, NX_MDNS_DNS_SD_MAX);
2237 
2238     /* Update the services dns-sd.  */
2239     memcpy(_nx_mdns_dns_sd, "_services._dns-sd._udp.", (sizeof("_services._dns-sd._udp.") - 1)); /* Use case of memcpy is verified. */
2240     index = (sizeof("_services._dns-sd._udp.") - 1);
2241     memcpy(&_nx_mdns_dns_sd[index], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2242 
2243     /* Release the mDNS mutex.  */
2244     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2245 
2246     /* Return a successful status.  */
2247     return(NX_SUCCESS);
2248 }
2249 
2250 
2251 #ifndef NX_MDNS_DISABLE_SERVER
2252 /**************************************************************************/
2253 /*                                                                        */
2254 /*  FUNCTION                                               RELEASE        */
2255 /*                                                                        */
2256 /*    _nxe_mdns_service_add                               PORTABLE C      */
2257 /*                                                           6.1          */
2258 /*  AUTHOR                                                                */
2259 /*                                                                        */
2260 /*    Yuxin Zhou, Microsoft Corporation                                   */
2261 /*                                                                        */
2262 /*  DESCRIPTION                                                           */
2263 /*                                                                        */
2264 /*    This function checks for errors in the mDNS service add             */
2265 /*    function call.                                                      */
2266 /*                                                                        */
2267 /*  INPUT                                                                 */
2268 /*                                                                        */
2269 /*    mdns_ptr                              Pointer to mDNS instance      */
2270 /*    name                                  Service instance name         */
2271 /*    type                                  The type of the service       */
2272 /*    subtype                               The subtype of the service    */
2273 /*    txt                                   The txt string of the service */
2274 /*    ttl                                   The ttl of the service        */
2275 /*    priority                              The priority of target host   */
2276 /*    weights                               Service weight                */
2277 /*    port                                  The port on this target host  */
2278 /*    is_unique                             The RR set of the service     */
2279 /*    interface_index                       The interface index           */
2280 /*                                                                        */
2281 /*  OUTPUT                                                                */
2282 /*                                                                        */
2283 /*    status                                Completion status             */
2284 /*                                                                        */
2285 /*  CALLS                                                                 */
2286 /*                                                                        */
2287 /*    _nx_mdns_service_add                  Actual service add function   */
2288 /*                                                                        */
2289 /*  CALLED BY                                                             */
2290 /*                                                                        */
2291 /*    Application Code                                                    */
2292 /*                                                                        */
2293 /*  RELEASE HISTORY                                                       */
2294 /*                                                                        */
2295 /*    DATE              NAME                      DESCRIPTION             */
2296 /*                                                                        */
2297 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2298 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2299 /*                                            resulting in version 6.1    */
2300 /*                                                                        */
2301 /**************************************************************************/
_nxe_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2302 UINT _nxe_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2303                            USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2304 {
2305 
2306 UINT    status;
2307 
2308 
2309     /* Check for invalid input pointers.  */
2310     if (!mdns_ptr)
2311     {
2312         return(NX_PTR_ERROR);
2313     }
2314 
2315     /* Check for invalid server attributes. */
2316     if ((mdns_ptr -> nx_mdns_id != NX_MDNS_ID) || (!port))
2317     {
2318         return(NX_MDNS_PARAM_ERROR);
2319     }
2320 
2321     /* Check the size of the service name string. The last four characters in the
2322        service name are reserved so DNS-SD is able to append " (2)" during the conflict
2323        resolution process. */
2324 #if (NX_MDNS_SERVICE_NAME_MAX >= NX_MDNS_LABEL_MAX)
2325     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_LABEL_MAX - 4)))
2326 #else
2327     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_SERVICE_NAME_MAX - 4)))
2328 #endif
2329     {
2330         return(NX_MDNS_DATA_SIZE_ERROR);
2331     }
2332 
2333     /* Check the type.  */
2334     if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2335     {
2336         return(NX_MDNS_DATA_SIZE_ERROR);
2337     }
2338 
2339     /* Check the txt string size.  */
2340     if (txt)
2341     {
2342         if (_nx_utility_string_length_check((CHAR *)txt, NX_NULL, NX_MDNS_NAME_MAX))
2343         {
2344             return(NX_MDNS_DATA_SIZE_ERROR);
2345         }
2346     }
2347 
2348     /* Check the txt string size.  */
2349     if (sub_type)
2350     {
2351         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
2352         {
2353             return(NX_MDNS_DATA_SIZE_ERROR);
2354         }
2355     }
2356 
2357     /* Check the interface index.  */
2358     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
2359     {
2360         return(NX_INVALID_INTERFACE);
2361     }
2362 
2363     /* Call actual mDNS service add service.  */
2364     status =  _nx_mdns_service_add(mdns_ptr, name, type, sub_type, txt, ttl, priority,
2365                                    weights, port, is_unique, interface_index);
2366 
2367     /* Return status.  */
2368     return(status);
2369 }
2370 
2371 
2372 /**************************************************************************/
2373 /*                                                                        */
2374 /*  FUNCTION                                               RELEASE        */
2375 /*                                                                        */
2376 /*    _nx_mdns_service_add                                PORTABLE C      */
2377 /*                                                           6.1          */
2378 /*  AUTHOR                                                                */
2379 /*                                                                        */
2380 /*    Yuxin Zhou, Microsoft Corporation                                   */
2381 /*                                                                        */
2382 /*  DESCRIPTION                                                           */
2383 /*                                                                        */
2384 /*    This function adds the mDNS services, and the PTR, SRV and TXT      */
2385 /*    records into the local buffer.                                      */
2386 /*                                                                        */
2387 /*  INPUT                                                                 */
2388 /*                                                                        */
2389 /*    mdns_ptr                              Pointer to mDNS instance      */
2390 /*    name                                  Service nstance name          */
2391 /*    type                                  The type of the service       */
2392 /*    subtype                               The subtype of the service    */
2393 /*    txt                                   The txt string of the service */
2394 /*    ttl                                   The ttl of the service        */
2395 /*    priority                              The priority of target host   */
2396 /*    weights                               Service weight                */
2397 /*    port                                  The port on this target host  */
2398 /*    is_unique                             The RR set of the service     */
2399 /*    interface_index                       The interface index           */
2400 /*                                                                        */
2401 /*  OUTPUT                                                                */
2402 /*                                                                        */
2403 /*    status                                Completion status             */
2404 /*                                                                        */
2405 /*  CALLS                                                                 */
2406 /*                                                                        */
2407 /*    tx_mutex_get                          Get the mDNS mutex            */
2408 /*    tx_mutex_put                          Put the mDNS mutex            */
2409 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
2410 /*    _nx_mdns_rr_srv_add                   Add the SRV resource record   */
2411 /*    _nx_mdns_rr_txt_add                   Add the TXT resource record   */
2412 /*    _nx_mdns_rr_ptr_add                   Add the PTR resource record   */
2413 /*    _nx_mdns_rr_delete                    Delete the resource record    */
2414 /*                                                                        */
2415 /*  CALLED BY                                                             */
2416 /*                                                                        */
2417 /*    Application Code                                                    */
2418 /*                                                                        */
2419 /*  RELEASE HISTORY                                                       */
2420 /*                                                                        */
2421 /*    DATE              NAME                      DESCRIPTION             */
2422 /*                                                                        */
2423 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2424 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2425 /*                                            resulting in version 6.1    */
2426 /*                                                                        */
2427 /**************************************************************************/
_nx_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2428 UINT _nx_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2429                           USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2430 {
2431 
2432 UINT        status;
2433 UINT        type_index;
2434 NX_MDNS_RR *srv_rr;
2435 NX_MDNS_RR *txt_rr;
2436 NX_MDNS_RR *ptr_rr;
2437 NX_MDNS_RR *dns_sd_rr;
2438 ULONG       *head;
2439 NX_MDNS_RR  *p;
2440 ULONG        srv_ttl;
2441 ULONG        txt_ttl;
2442 ULONG        ptr_ttl;
2443 UINT         string_length;
2444 
2445 
2446     /* Get the mDNS mutex.  */
2447     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2448 
2449     /* Check the ttl value.  */
2450     if (ttl)
2451     {
2452 
2453         /* Use user supplied TTL value if it is not zero. */
2454         srv_ttl = ttl;
2455         txt_ttl = ttl;
2456         ptr_ttl = ttl;
2457     }
2458     else
2459     {
2460 
2461         /* Use the RFC recommended TTL values if user doesn't supply one.  */
2462         srv_ttl = NX_MDNS_RR_TTL_HOST;
2463         txt_ttl = NX_MDNS_RR_TTL_OTHER;
2464         ptr_ttl = NX_MDNS_RR_TTL_OTHER;
2465     }
2466 
2467     /* Construct the SRV name.  */
2468     status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2469 
2470     /* Check the status.  */
2471     if (status)
2472     {
2473 
2474         /* Release the mDNS mutex.  */
2475         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2476         return (status);
2477     }
2478 
2479     /* Check string length.  */
2480     if (_nx_utility_string_length_check((CHAR *)(&temp_string_buffer[0]), &string_length, NX_MDNS_NAME_MAX))
2481     {
2482 
2483         /* Release the mDNS mutex.  */
2484         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2485         return (NX_MDNS_DATA_SIZE_ERROR);
2486     }
2487 
2488     /* Check whether the same service name exist.  */
2489     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2490     head = (ULONG*)(*head);
2491 
2492     /* Check the resource record.  */
2493     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2494     {
2495         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2496             continue;
2497 
2498         /* Check the interface.  */
2499         if (p -> nx_mdns_rr_interface_index != interface_index)
2500             continue;
2501 
2502         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
2503         {
2504 
2505             /* Compare the service name.  */
2506             if (!_nx_mdns_name_match(&temp_string_buffer[0], p -> nx_mdns_rr_name, string_length))
2507             {
2508 
2509                 /* Release the mDNS mutex.  */
2510                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2511 
2512                 return(NX_MDNS_EXIST_SAME_SERVICE);
2513             }
2514         }
2515     }
2516 
2517     /* Construct the SRV target name.  */
2518     status = _nx_mdns_service_name_assemble(mdns_ptr -> nx_mdns_host_name, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
2519 
2520     /* Check the status.  */
2521     if (status)
2522     {
2523 
2524         /* Release the mDNS mutex.  */
2525         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2526         return (status);
2527     }
2528 
2529     /* Add the SRV resource records message.  */
2530     status = _nx_mdns_rr_srv_add(mdns_ptr, &temp_string_buffer[0], srv_ttl, is_unique, priority, weights, port, &target_string_buffer[0], &srv_rr, interface_index);
2531 
2532     /* Check the status.  */
2533     if (status)
2534     {
2535 
2536         /* Release the mDNS mutex.  */
2537         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2538         return(status);
2539     }
2540 
2541     /* Add the TXT resource records message.  */
2542     status = _nx_mdns_rr_txt_add(mdns_ptr, &temp_string_buffer[0], txt_ttl, is_unique, txt, &txt_rr, interface_index);
2543 
2544     /* Check the status.  */
2545     if (status)
2546     {
2547 
2548         /* Delete the SRV records.  */
2549         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2550 
2551         /* Release the mDNS mutex.  */
2552         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2553 
2554         return(status);
2555     }
2556 
2557     /* Add the dns-sd PTR resource records message.  */
2558     status = _nx_mdns_rr_ptr_add(mdns_ptr, (UCHAR *)_nx_mdns_dns_sd, ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[type_index], NX_TRUE, &dns_sd_rr, interface_index);
2559 
2560     /* Check the status.  */
2561     if (status)
2562     {
2563 
2564         /* Delete the TXT records.  */
2565         _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2566 
2567         /* Delete the SRV records.  */
2568         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2569 
2570         /* Release the mDNS mutex.  */
2571         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2572 
2573         return(status);
2574     }
2575 
2576     /* Add the PTR resource records message.  */
2577     status = _nx_mdns_rr_ptr_add(mdns_ptr, &temp_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, &ptr_rr, interface_index);
2578 
2579     /* Check the status.  */
2580     if (status)
2581     {
2582 
2583         /* Delete the TXT records.  */
2584         _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2585 
2586         /* Delete the SRV records.  */
2587         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2588 
2589         /* Delete the DNS_SD PTR records.  */
2590         _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2591 
2592         /* Release the mDNS mutex.  */
2593         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2594 
2595         return(status);
2596     }
2597 
2598     /* Add another PTR type for the subtype. */
2599     if (sub_type)
2600     {
2601 
2602         /* Construct the PTR target name.  */
2603         status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2604 
2605         /* Check the status.  */
2606         if (status)
2607         {
2608 
2609             /* Release the mDNS mutex.  */
2610             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2611 
2612             return (status);
2613         }
2614 
2615         /* Add the Sub PTR resource records message.  */
2616         status = _nx_mdns_rr_ptr_add(mdns_ptr, &target_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, NX_NULL, interface_index);
2617 
2618         /* Check the status.  */
2619         if (status)
2620         {
2621 
2622             /* Delete the PTR records.  */
2623             _nx_mdns_rr_delete(mdns_ptr, ptr_rr);
2624 
2625             /* Delete the DNS_SD PTR records.  */
2626             _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2627 
2628             /* Delete the SRV records.  */
2629             _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2630 
2631             /* Delete the TXT records.  */
2632             _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2633 
2634             /* Release the mDNS mutex.  */
2635             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2636 
2637             return(status);
2638         }
2639     }
2640 
2641 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2642 
2643     /* Add the NSEC resource record for service.  */
2644     _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], NX_FALSE, NX_FALSE, NX_MDNS_ADD_NSEC_FOR_SERVICE, interface_index);
2645 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
2646 
2647     /* Release the mDNS mutex.  */
2648     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2649 
2650     /* Return a successful status.  */
2651     return(NX_SUCCESS);
2652 }
2653 
2654 
2655 /**************************************************************************/
2656 /*                                                                        */
2657 /*  FUNCTION                                               RELEASE        */
2658 /*                                                                        */
2659 /*    _nxe_mdns_service_delete                            PORTABLE C      */
2660 /*                                                           6.1          */
2661 /*  AUTHOR                                                                */
2662 /*                                                                        */
2663 /*    Yuxin Zhou, Microsoft Corporation                                   */
2664 /*                                                                        */
2665 /*  DESCRIPTION                                                           */
2666 /*                                                                        */
2667 /*    This function checks for errors in the mDNS service delete          */
2668 /*    function call.                                                      */
2669 /*                                                                        */
2670 /*  INPUT                                                                 */
2671 /*                                                                        */
2672 /*    mdns_ptr                              Pointer to mDNS instance      */
2673 /*    name                                  The name of the service       */
2674 /*    type                                  The type of the service       */
2675 /*    subtype                               The subtype of the service    */
2676 /*                                                                        */
2677 /*  OUTPUT                                                                */
2678 /*                                                                        */
2679 /*    status                                Completion status             */
2680 /*                                                                        */
2681 /*  CALLS                                                                 */
2682 /*                                                                        */
2683 /*    _nx_mdns_service_delete               Actual service delete function*/
2684 /*                                                                        */
2685 /*  CALLED BY                                                             */
2686 /*                                                                        */
2687 /*    Application Code                                                    */
2688 /*                                                                        */
2689 /*  RELEASE HISTORY                                                       */
2690 /*                                                                        */
2691 /*    DATE              NAME                      DESCRIPTION             */
2692 /*                                                                        */
2693 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2694 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2695 /*                                            resulting in version 6.1    */
2696 /*                                                                        */
2697 /**************************************************************************/
_nxe_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2698 UINT _nxe_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2699 {
2700 
2701 UINT    status;
2702 
2703     /* Check for invalid input pointers.  */
2704     if ((!mdns_ptr) || (!name) || (!type))
2705     {
2706         return(NX_PTR_ERROR);
2707     }
2708 
2709     /* Check for invalid server attributes. */
2710     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2711     {
2712         return(NX_MDNS_PARAM_ERROR);
2713     }
2714 
2715     /* Check the size.  */
2716     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX) ||
2717         _nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2718     {
2719         return(NX_MDNS_DATA_SIZE_ERROR);
2720     }
2721 
2722     /* Call actual mDNS service delete service.  */
2723     status =  _nx_mdns_service_delete(mdns_ptr, name, type, sub_type);
2724 
2725     /* Return status.  */
2726     return(status);
2727 }
2728 
2729 /**************************************************************************/
2730 /*                                                                        */
2731 /*  FUNCTION                                               RELEASE        */
2732 /*                                                                        */
2733 /*    _nx_mdns_service_delete                             PORTABLE C      */
2734 /*                                                           6.1          */
2735 /*  AUTHOR                                                                */
2736 /*                                                                        */
2737 /*    Yuxin Zhou, Microsoft Corporation                                   */
2738 /*                                                                        */
2739 /*  DESCRIPTION                                                           */
2740 /*                                                                        */
2741 /*    This function deletes the mDNS services.                            */
2742 /*                                                                        */
2743 /*  INPUT                                                                 */
2744 /*                                                                        */
2745 /*    mdns_ptr                              Pointer to mDNS instance      */
2746 /*    name                                  The name of the service       */
2747 /*    type                                  The type of the service       */
2748 /*    subtype                               The subtype of the service    */
2749 /*                                                                        */
2750 /*  OUTPUT                                                                */
2751 /*                                                                        */
2752 /*    status                                Completion status             */
2753 /*                                                                        */
2754 /*  CALLS                                                                 */
2755 /*                                                                        */
2756 /*    _nx_mdns_service_delete_internal      Actual service delete function*/
2757 /*                                                                        */
2758 /*  CALLED BY                                                             */
2759 /*                                                                        */
2760 /*    Application Code                                                    */
2761 /*                                                                        */
2762 /*  RELEASE HISTORY                                                       */
2763 /*                                                                        */
2764 /*    DATE              NAME                      DESCRIPTION             */
2765 /*                                                                        */
2766 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2767 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2768 /*                                            resulting in version 6.1    */
2769 /*                                                                        */
2770 /**************************************************************************/
_nx_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2771 UINT _nx_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2772 {
2773 
2774 UINT    i;
2775 UINT    status = NX_MDNS_NOT_ENABLED;
2776 UINT    service_delete_success = NX_FALSE;
2777 
2778     /* Delete service from all enabled interfaces.  */
2779     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i ++)
2780     {
2781 
2782         /* Call actual mDNS service delete service.  */
2783         status =  _nx_mdns_service_interface_delete(mdns_ptr, name, type, sub_type, i);
2784 
2785         /* Check status.  */
2786         if (status == NX_MDNS_SUCCESS)
2787         {
2788             service_delete_success = NX_TRUE;
2789         }
2790     }
2791 
2792     /* Check if delete service on all enabled interface.  */
2793     if (service_delete_success)
2794         return(NX_MDNS_SUCCESS);
2795     else
2796         return(status);
2797 }
2798 
2799 
2800 /**************************************************************************/
2801 /*                                                                        */
2802 /*  FUNCTION                                               RELEASE        */
2803 /*                                                                        */
2804 /*    _nx_mdns_service_interface_delete                   PORTABLE C      */
2805 /*                                                           6.1          */
2806 /*  AUTHOR                                                                */
2807 /*                                                                        */
2808 /*    Yuxin Zhou, Microsoft Corporation                                   */
2809 /*                                                                        */
2810 /*  DESCRIPTION                                                           */
2811 /*                                                                        */
2812 /*    This function deletes the mDNS services, and remove SRV and TXT     */
2813 /*    records from local buffer.                                          */
2814 /*                                                                        */
2815 /*  INPUT                                                                 */
2816 /*                                                                        */
2817 /*    mdns_ptr                              Pointer to mDNS instance      */
2818 /*    name                                  The name of the service       */
2819 /*    type                                  The type of the service       */
2820 /*    subtype                               The subtype of the service    */
2821 /*    interface_index                       The interface index           */
2822 /*                                                                        */
2823 /*  OUTPUT                                                                */
2824 /*                                                                        */
2825 /*    status                                Completion status             */
2826 /*                                                                        */
2827 /*  CALLS                                                                 */
2828 /*                                                                        */
2829 /*    tx_mutex_get                          Get the mDNS mutex            */
2830 /*    tx_mutex_put                          Put the mDNS mutex            */
2831 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
2832 /*    _nx_mdns_name_match                   Match the name string         */
2833 /*    _nx_mdns_rr_delete                    Delete the resource record    */
2834 /*                                                                        */
2835 /*  CALLED BY                                                             */
2836 /*                                                                        */
2837 /*    Application Code                                                    */
2838 /*                                                                        */
2839 /*  RELEASE HISTORY                                                       */
2840 /*                                                                        */
2841 /*    DATE              NAME                      DESCRIPTION             */
2842 /*                                                                        */
2843 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2844 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2845 /*                                            resulting in version 6.1    */
2846 /*                                                                        */
2847 /**************************************************************************/
_nx_mdns_service_interface_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT interface_index)2848 UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index)
2849 {
2850 
2851 UINT        status;
2852 UINT        found;
2853 UINT        delete_flag;
2854 UINT        type_index;
2855 ULONG      *head;
2856 NX_MDNS_RR *p;
2857 UINT        rr_name_length;
2858 UINT        rr_ptr_name_length;
2859 
2860     NX_PARAMETER_NOT_USED(sub_type);
2861 
2862     /* Get the mDNS mutex.  */
2863     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2864 
2865     /* Initialize the parameters.  */
2866     type_index = 0;
2867     delete_flag = NX_FALSE;
2868 
2869     /* Construct the SRV name.  */
2870     status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2871 
2872     /* Check the status.  */
2873     if (status)
2874     {
2875 
2876         /* Release the mDNS mutex.  */
2877         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2878         return (status);
2879     }
2880 
2881     /* Get head. */
2882     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2883     head = (ULONG*)(*head);
2884 
2885     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2886     {
2887 
2888         /* Clear the found value.  */
2889         found = NX_FALSE;
2890 
2891         /* Check the interface index.  */
2892         if (p -> nx_mdns_rr_interface_index != interface_index)
2893             continue;
2894 
2895         /* Check whether the resource record is valid. */
2896         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2897             continue;
2898 
2899         /* Check string length.  */
2900         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
2901         {
2902             continue;
2903         }
2904 
2905         /* Compare the RDATA. */
2906         switch (p -> nx_mdns_rr_type)
2907         {
2908 
2909             case NX_MDNS_RR_TYPE_SRV:
2910             case NX_MDNS_RR_TYPE_TXT:
2911             {
2912                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2913                 {
2914                     found = NX_TRUE;
2915                     delete_flag = NX_TRUE;
2916                 }
2917                 break;
2918             }
2919             case NX_MDNS_RR_TYPE_PTR:
2920             {
2921 
2922                 /* Check string length.  */
2923                 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), &rr_ptr_name_length, NX_MDNS_NAME_MAX))
2924                 {
2925                     break;
2926                 }
2927 
2928                 /* Find the PTR and Sub PTR resource record which pointer to the SRV resource record.*/
2929                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[0], rr_ptr_name_length))
2930                 {
2931                     found = NX_TRUE;
2932                 }
2933 
2934                 /* Find one DNS-SD PRT which pointer to the PTR resource record.  */
2935                 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)) &&
2936                     (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[type_index], rr_ptr_name_length)))
2937                 {
2938 
2939                     /* Check the count.  */
2940                     if (p -> nx_mdns_rr_count)
2941                     {
2942                         p -> nx_mdns_rr_count --;
2943                     }
2944                     else
2945                     {
2946 
2947                         /* Delete this resource record directly.  */
2948                         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2949                     }
2950                 }
2951                 break;
2952             }
2953 
2954 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2955             case NX_MDNS_RR_TYPE_NSEC:
2956             {
2957                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2958                 {
2959 
2960                     /* Delete this resource record directly.  */
2961                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2962                 }
2963                 break;
2964             }
2965 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
2966         }
2967 
2968         if (found)
2969         {
2970 
2971             /* Delete the resource records.  */
2972             status = _nx_mdns_rr_delete(mdns_ptr, p);
2973 
2974             /* Check the status.  */
2975             if (status)
2976             {
2977                 /* Release the mDNS mutex.  */
2978                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2979 
2980                 return(status);
2981             }
2982         }
2983     }
2984 
2985     /* Release the mDNS mutex.  */
2986     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2987 
2988     if (delete_flag == NX_TRUE)
2989         return(NX_MDNS_SUCCESS);
2990     else
2991         return(NX_MDNS_ERROR);
2992 }
2993 #endif /* NX_MDNS_DISABLE_SERVER */
2994 
2995 
2996 #ifndef NX_MDNS_DISABLE_CLIENT
2997 /**************************************************************************/
2998 /*                                                                        */
2999 /*  FUNCTION                                               RELEASE        */
3000 /*                                                                        */
3001 /*    _nxe_mdns_service_one_shot_query                      PORTABLE C    */
3002 /*                                                           6.1          */
3003 /*  AUTHOR                                                                */
3004 /*                                                                        */
3005 /*    Yuxin Zhou, Microsoft Corporation                                   */
3006 /*                                                                        */
3007 /*  DESCRIPTION                                                           */
3008 /*                                                                        */
3009 /*    This function checks for errors in the mDNS resource record query   */
3010 /*    add function call.                                                  */
3011 /*                                                                        */
3012 /*  INPUT                                                                 */
3013 /*                                                                        */
3014 /*    mdns_ptr                              Pointer to mDNS instance      */
3015 /*    name                                  The name of the service       */
3016 /*    type                                  The type of the service       */
3017 /*    subtype                               The subtype of the service    */
3018 /*    service                               Pointer to response service   */
3019 /*    timeout                               The timeour for service query */
3020 /*                                                                        */
3021 /*  OUTPUT                                                                */
3022 /*                                                                        */
3023 /*    status                                Completion status             */
3024 /*                                                                        */
3025 /*  CALLS                                                                 */
3026 /*                                                                        */
3027 /*    _nx_mdns_service_one_shot_query       Actual query service function */
3028 /*                                                                        */
3029 /*  CALLED BY                                                             */
3030 /*                                                                        */
3031 /*    Application Code                                                    */
3032 /*                                                                        */
3033 /*  RELEASE HISTORY                                                       */
3034 /*                                                                        */
3035 /*    DATE              NAME                      DESCRIPTION             */
3036 /*                                                                        */
3037 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3038 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3039 /*                                            resulting in version 6.1    */
3040 /*                                                                        */
3041 /**************************************************************************/
_nxe_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3042 UINT _nxe_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3043 {
3044 
3045 UINT    status;
3046 
3047 
3048     /* Check for invalid input pointers.  */
3049     if ((!mdns_ptr) || (!type) || (!service))
3050     {
3051         return(NX_PTR_ERROR);
3052     }
3053 
3054     /* Check for mDNS started flag.  */
3055     if (!mdns_ptr -> nx_mdns_started)
3056     {
3057         return(NX_MDNS_NOT_STARTED);
3058     }
3059 
3060     /* Check for name.  */
3061     if (name)
3062     {
3063 
3064         /* Check the name size.  */
3065         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3066         {
3067             return(NX_MDNS_DATA_SIZE_ERROR);
3068         }
3069     }
3070 
3071     /* Check the type size.  */
3072     if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3073     {
3074         return(NX_MDNS_DATA_SIZE_ERROR);
3075     }
3076 
3077     /* Check the sub type.  */
3078     if (sub_type)
3079     {
3080 
3081         /* Check the name size.  */
3082         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3083         {
3084             return(NX_MDNS_DATA_SIZE_ERROR);
3085         }
3086     }
3087 
3088     /* Call actual mDNS create service.  */
3089     status = _nx_mdns_service_one_shot_query(mdns_ptr, name, type, sub_type, service, timeout);
3090 
3091     /* Return status.  */
3092     return(status);
3093 }
3094 
3095 
3096 /**************************************************************************/
3097 /*                                                                        */
3098 /*  FUNCTION                                               RELEASE        */
3099 /*                                                                        */
3100 /*    _nx_mdns_service_one_shot_query                     PORTABLE C      */
3101 /*                                                           6.1.11       */
3102 /*  AUTHOR                                                                */
3103 /*                                                                        */
3104 /*    Yuxin Zhou, Microsoft Corporation                                   */
3105 /*                                                                        */
3106 /*  DESCRIPTION                                                           */
3107 /*                                                                        */
3108 /*    This function starts service one-shot query on all enabled          */
3109 /*    interfaces.                                                         */
3110 /*                                                                        */
3111 /*  INPUT                                                                 */
3112 /*                                                                        */
3113 /*    mdns_ptr                              Pointer to mDNS instance      */
3114 /*    name                                  The name of the service       */
3115 /*    type                                  The type of the service       */
3116 /*    subtype                               The subtype of the service    */
3117 /*    service                               Pointer to response service   */
3118 /*    timeout                               The timeour for service query */
3119 /*                                                                        */
3120 /*  OUTPUT                                                                */
3121 /*                                                                        */
3122 /*    status                                Completion status             */
3123 /*                                                                        */
3124 /*  CALLS                                                                 */
3125 /*                                                                        */
3126 /*    tx_mutex_get                          Get the mDNS mutex            */
3127 /*    tx_mutex_put                          Put the mDNS mutex            */
3128 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3129 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
3130 /*    _nx_mdns_query                        Send the One Shot query       */
3131 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
3132 /*                                                                        */
3133 /*  CALLED BY                                                             */
3134 /*                                                                        */
3135 /*    Application Code                                                    */
3136 /*                                                                        */
3137 /*  RELEASE HISTORY                                                       */
3138 /*                                                                        */
3139 /*    DATE              NAME                      DESCRIPTION             */
3140 /*                                                                        */
3141 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3142 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3143 /*                                            verified memcpy use cases,  */
3144 /*                                            resulting in version 6.1    */
3145 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3146 /*                                            fixed compiler warnings,    */
3147 /*                                            resulting in version 6.1.11 */
3148 /*                                                                        */
3149 /**************************************************************************/
_nx_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3150 UINT _nx_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3151 {
3152 
3153 UINT        type_index;
3154 UINT        status;
3155 NX_MDNS_RR *answer_rr;
3156 UCHAR      *query_name;
3157 USHORT      query_type;
3158 UINT        i;
3159 UINT        name_length;
3160 
3161 
3162     /* Get the mDNS mutex.  */
3163     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3164 
3165     /* Initialize the struct.  */
3166     memset(service, 0, sizeof(NX_MDNS_SERVICE));
3167 
3168     /* Loop to start one-shot query on all enabled interfaces until get the answer or query timeout.  */
3169     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3170     {
3171 
3172         /* Check if this interface is enabled.  */
3173         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3174             continue;
3175 
3176         /* Step1. Construct the query name and set the query type.  */
3177         if (name)
3178         {
3179 
3180             /* Construct the SRV name.  */
3181             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3182 
3183             /* Check the status.  */
3184             if (status)
3185             {
3186 
3187                 /* Release the mDNS mutex.  */
3188                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3189                 return(status);
3190             }
3191 
3192             /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT).  */
3193             query_name = temp_string_buffer;
3194             query_type = NX_MDNS_RR_TYPE_ALL;
3195         }
3196         else
3197         {
3198 
3199             /* Construct the PTR name.  */
3200             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3201 
3202             /* Check the status.  */
3203             if (status)
3204             {
3205 
3206                 /* Release the mDNS mutex.  */
3207                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3208                 return (status);
3209             }
3210 
3211             /* Set the query name and query type.  */
3212             query_name = &temp_string_buffer[type_index];
3213             query_type = NX_MDNS_RR_TYPE_PTR;
3214         }
3215 
3216         /* Step2. Start one shot query.  */
3217         status = _nx_mdns_one_shot_query(mdns_ptr, query_name, query_type, &answer_rr, timeout, i);
3218 
3219         /* Check the status.  */
3220         if ((status == NX_SUCCESS) ||
3221             (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3222             (status == NX_MDNS_EXIST_SHARED_RR))
3223         {
3224 
3225             /* Check the query type.  */
3226             if (name)
3227             {
3228 
3229                 /* Store the service name from SRV record.  */
3230                 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_name, &name_length, NX_MDNS_NAME_MAX))
3231                 {
3232 
3233                     /* Release the mDNS mutex.  */
3234                     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3235                     return (NX_MDNS_DATA_SIZE_ERROR);
3236                 }
3237                 memcpy((char *)(service -> buffer), (char*)(answer_rr -> nx_mdns_rr_name), name_length); /* Use case of memcpy is verified. */
3238             }
3239             else
3240             {
3241 
3242                 /* Store the service name from PTR record.  */
3243                 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &name_length, NX_MDNS_NAME_MAX))
3244                 {
3245 
3246                     /* Release the mDNS mutex.  */
3247                     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3248                     return (NX_MDNS_DATA_SIZE_ERROR);
3249                 }
3250                 memcpy((CHAR *)(service -> buffer), (CHAR *)(answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), name_length); /* Use case of memcpy is verified. */
3251             }
3252 
3253             /* Get the additional information of service.  */
3254             _nx_mdns_service_addition_info_get(mdns_ptr, service -> buffer, service, i);
3255 
3256             /* Reslove the service name.  */
3257             status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
3258 
3259             /* Check status.  */
3260             if (status)
3261                 continue;
3262 
3263             /* Release the mDNS mutex.  */
3264             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3265 
3266             /* Return success.  */
3267             return (NX_MDNS_SUCCESS);
3268         }
3269     }
3270 
3271     /* Release the mDNS mutex.  */
3272     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3273 
3274     /* Return error.  */
3275     return (NX_MDNS_ERROR);
3276 }
3277 
3278 
3279 /**************************************************************************/
3280 /*                                                                        */
3281 /*  FUNCTION                                               RELEASE        */
3282 /*                                                                        */
3283 /*    _nx_mdns_one_shot_query                             PORTABLE C      */
3284 /*                                                           6.1.11       */
3285 /*  AUTHOR                                                                */
3286 /*                                                                        */
3287 /*    Yuxin Zhou, Microsoft Corporation                                   */
3288 /*                                                                        */
3289 /*  DESCRIPTION                                                           */
3290 /*                                                                        */
3291 /*    This function adds the mDNS resource record into remote buffer,     */
3292 /*    mDNS thread send the query message.                                 */
3293 /*                                                                        */
3294 /*  INPUT                                                                 */
3295 /*                                                                        */
3296 /*    mdns_ptr                              Pointer to mDNS instance      */
3297 /*    name                                  The resource record name      */
3298 /*    type                                  The resource record type      */
3299 /*    out_rr                                Pointer to response RR        */
3300 /*    one_shot                              One shot or continuous        */
3301 /*    wait_option                           Wait option                   */
3302 /*                                                                        */
3303 /*  OUTPUT                                                                */
3304 /*                                                                        */
3305 /*    status                                Completion status             */
3306 /*                                                                        */
3307 /*  CALLS                                                                 */
3308 /*                                                                        */
3309 /*    tx_mutex_get                          Get the mDNS mutex            */
3310 /*    tx_mutex_put                          Put the mDNS mutex            */
3311 /*    _tx_thread_system_suspend             Suspend the thread            */
3312 /*    _nx_mdns_query_check                  Check the query RR            */
3313 /*    _nx_mdns_cache_add_string             Add the string into cache     */
3314 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
3315 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
3316 /*                                            into cache                  */
3317 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
3318 /*                                            from cache                  */
3319 /*                                                                        */
3320 /*  CALLED BY                                                             */
3321 /*                                                                        */
3322 /*    Application Code                                                    */
3323 /*                                                                        */
3324 /*  RELEASE HISTORY                                                       */
3325 /*                                                                        */
3326 /*    DATE              NAME                      DESCRIPTION             */
3327 /*                                                                        */
3328 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3329 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3330 /*                                            resulting in version 6.1    */
3331 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3332 /*                                            corrected the random value, */
3333 /*                                            fixed the issue of timer,   */
3334 /*                                            resulting in version 6.1.11 */
3335 /*                                                                        */
3336 /**************************************************************************/
_nx_mdns_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,NX_MDNS_RR ** out_rr,ULONG wait_option,UINT interface_index)3337 static UINT _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index)
3338 {
3339 
3340 UINT        status;
3341 NX_MDNS_RR  *rr;
3342 NX_MDNS_RR  *insert_rr;
3343 NX_MDNS_RR  temp_resource_record;
3344 UINT        name_length;
3345 
3346 
3347     /* Clear the return record.  */
3348     *out_rr =   NX_NULL;
3349 
3350     /* Check the query RR.  */
3351     status = _nx_mdns_query_check(mdns_ptr, name, type, NX_TRUE, &rr, interface_index);
3352 
3353     /* Check the state.  */
3354     if (status)
3355     {
3356 
3357         /* Whether exists unique resource record in cache.  */
3358         if ((status == NX_MDNS_EXIST_UNIQUE_RR) ||
3359             (status == NX_MDNS_EXIST_SHARED_RR))
3360         {
3361             *out_rr = rr;
3362             return (NX_MDNS_SUCCESS);
3363         }
3364         else
3365         {
3366             return(status);
3367         }
3368     }
3369 
3370     if (wait_option != 0)
3371     {
3372 
3373         /* Initialize the struct.  */
3374         memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3375 
3376         if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3377         {
3378             return (NX_MDNS_DATA_SIZE_ERROR);
3379         }
3380 
3381         /* Add the name.  */
3382         status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3383                                            (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3384 
3385         /* Check for error.  */
3386         if (status)
3387         {
3388             return(status);
3389         }
3390 
3391         /* Add the parameters.  */
3392         temp_resource_record.nx_mdns_rr_type = type;
3393         temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3394 
3395         /* Set the resource record status.  */
3396         temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3397 
3398         /* Remote resource record, set the owner flag.  */
3399         temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3400 
3401         /* Set the interface index.  */
3402         temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3403 
3404         /* Add the resource record.  */
3405         status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3406 
3407         /* Check for error.  */
3408         if (status)
3409         {
3410 
3411             /* Delete the same strings. */
3412             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3413             return(status);
3414         }
3415 
3416         /* A multicast DNS querier should also delay the first query of the series by
3417            a randomly chosen amount in the range 20-120ms.  */
3418         insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3419         insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3420 
3421         /* Set the mDNS timer.  */
3422         _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3423 
3424         /* Release the mDNS mutex to process response.  */
3425         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3426 
3427         /* Suspend the thread on this mDNS query attempt.  */
3428         _nx_mdns_query_thread_suspend(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), _nx_mdns_query_cleanup, mdns_ptr, out_rr, wait_option);
3429 
3430         /* Get the mDNS mutex.  */
3431         tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3432 
3433         /* Determine if a packet was received successfully.  */
3434         if (_tx_thread_current_ptr -> tx_thread_suspend_status != NX_MDNS_SUCCESS)
3435         {
3436 
3437             /* Delete the query resource record.  */
3438             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, insert_rr);
3439         }
3440 
3441         /* Return the status.  */
3442         return(_tx_thread_current_ptr -> tx_thread_suspend_status);
3443     }
3444     else
3445     {
3446 
3447         /* Immediate return, return error completion.  */
3448         return(NX_MDNS_NO_RR);
3449     }
3450 }
3451 
3452 
3453 /**************************************************************************/
3454 /*                                                                        */
3455 /*  FUNCTION                                               RELEASE        */
3456 /*                                                                        */
3457 /*    _nxe_mdns_service_continuous_query                    PORTABLE C    */
3458 /*                                                           6.1          */
3459 /*  AUTHOR                                                                */
3460 /*                                                                        */
3461 /*    Yuxin Zhou, Microsoft Corporation                                   */
3462 /*                                                                        */
3463 /*  DESCRIPTION                                                           */
3464 /*                                                                        */
3465 /*    This function checks for errors in the mDNS resource record query   */
3466 /*    add function call.                                                  */
3467 /*                                                                        */
3468 /*  INPUT                                                                 */
3469 /*                                                                        */
3470 /*    mdns_ptr                              Pointer to mDNS instance      */
3471 /*    name                                  The name of the service       */
3472 /*    type                                  The type of the service       */
3473 /*    subtype                               The subtype of the service    */
3474 /*                                                                        */
3475 /*  OUTPUT                                                                */
3476 /*                                                                        */
3477 /*    status                                Completion status             */
3478 /*                                                                        */
3479 /*  CALLS                                                                 */
3480 /*                                                                        */
3481 /*    _nx_mdns_service_continuous_query     Actual mDNS query RR function */
3482 /*                                                                        */
3483 /*  CALLED BY                                                             */
3484 /*                                                                        */
3485 /*    Application Code                                                    */
3486 /*                                                                        */
3487 /*  RELEASE HISTORY                                                       */
3488 /*                                                                        */
3489 /*    DATE              NAME                      DESCRIPTION             */
3490 /*                                                                        */
3491 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3492 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3493 /*                                            resulting in version 6.1    */
3494 /*                                                                        */
3495 /**************************************************************************/
_nxe_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3496 UINT _nxe_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3497 {
3498 
3499 UINT    status;
3500 
3501 
3502     /* Check for invalid input pointers.  */
3503     if (!mdns_ptr)
3504     {
3505         return(NX_PTR_ERROR);
3506     }
3507 
3508     /* Check for invalid server attributes. */
3509     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3510     {
3511         return(NX_MDNS_PARAM_ERROR);
3512     }
3513 
3514     /* Check for mDNS stareted flag.  */
3515     if (!mdns_ptr -> nx_mdns_started)
3516     {
3517         return(NX_MDNS_NOT_STARTED);
3518     }
3519 
3520     /* Check the type. If the type is null,indicate lookup the all service type, the name and sub type must be null.  */
3521     if (!type)
3522     {
3523         if ((name) || (sub_type))
3524         {
3525             return(NX_MDNS_PARAM_ERROR);
3526         }
3527     }
3528     else
3529     {
3530 
3531         /* Check the name, If the name is non-null, the sub type must be null.  */
3532         if ((name) && (sub_type))
3533         {
3534             return(NX_MDNS_PARAM_ERROR);
3535         }
3536     }
3537 
3538     /* Check the name.  */
3539     if (name)
3540     {
3541 
3542         /* Check the name size.  */
3543         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3544         {
3545             return(NX_MDNS_DATA_SIZE_ERROR);
3546         }
3547     }
3548 
3549     /* Check the type.  */
3550     if (type)
3551     {
3552 
3553         /* Check the type size.  */
3554         if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3555         {
3556             return(NX_MDNS_DATA_SIZE_ERROR);
3557         }
3558     }
3559 
3560     /* Check the sub type.  */
3561     if (sub_type)
3562     {
3563 
3564         /* Check the sub type size.  */
3565         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3566         {
3567             return(NX_MDNS_DATA_SIZE_ERROR);
3568         }
3569     }
3570 
3571     /* Call actual mDNS create service.  */
3572     status =  _nx_mdns_service_continuous_query(mdns_ptr, name, type, sub_type);
3573 
3574     /* Return status.  */
3575     return(status);
3576 }
3577 
3578 
3579 /**************************************************************************/
3580 /*                                                                        */
3581 /*  FUNCTION                                               RELEASE        */
3582 /*                                                                        */
3583 /*    _nx_mdns_service_continuous_query                   PORTABLE C      */
3584 /*                                                           6.1          */
3585 /*  AUTHOR                                                                */
3586 /*                                                                        */
3587 /*    Yuxin Zhou, Microsoft Corporation                                   */
3588 /*                                                                        */
3589 /*  DESCRIPTION                                                           */
3590 /*                                                                        */
3591 /*    This function starts service continuous query on all enabled        */
3592 /*    interfaces.                                                         */
3593 /*                                                                        */
3594 /*  INPUT                                                                 */
3595 /*                                                                        */
3596 /*    mdns_ptr                              Pointer to mDNS instance      */
3597 /*    name                                  The name of the service       */
3598 /*    type                                  The type of the service       */
3599 /*    subtype                               The subtype of the service    */
3600 /*                                                                        */
3601 /*  OUTPUT                                                                */
3602 /*                                                                        */
3603 /*    status                                Completion status             */
3604 /*                                                                        */
3605 /*  CALLS                                                                 */
3606 /*                                                                        */
3607 /*    tx_mutex_get                          Get the mDNS mutex            */
3608 /*    tx_mutex_put                          Put the mDNS mutex            */
3609 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3610 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
3611 /*    _nx_mdns_query                        Send the One Shot query       */
3612 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
3613 /*                                                                        */
3614 /*  CALLED BY                                                             */
3615 /*                                                                        */
3616 /*    Application Code                                                    */
3617 /*                                                                        */
3618 /*  RELEASE HISTORY                                                       */
3619 /*                                                                        */
3620 /*    DATE              NAME                      DESCRIPTION             */
3621 /*                                                                        */
3622 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3623 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3624 /*                                            resulting in version 6.1    */
3625 /*                                                                        */
3626 /**************************************************************************/
_nx_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3627 UINT _nx_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3628 {
3629 
3630 UINT        status = NX_MDNS_ERROR;
3631 UINT        type_index;
3632 UCHAR      *query_name;
3633 USHORT      query_type;
3634 UINT        query_success = NX_FALSE;
3635 UINT        i;
3636 
3637 
3638     /* Get the mDNS mutex.  */
3639     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3640 
3641     /* Step1. Construct the query name and set the query type.  */
3642     /* Check the type. if the type is null, indicate search all service.  */
3643     if (!type)
3644     {
3645 
3646         /* Set the query name and query type.  */
3647         query_name = (UCHAR *)_nx_mdns_dns_sd;
3648         query_type = NX_MDNS_RR_TYPE_PTR;
3649     }
3650     else if (name)
3651     {
3652 
3653         /* Construct the SRV name.  */
3654         status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3655 
3656         /* Check the status.  */
3657         if (status)
3658         {
3659 
3660             /* Release the mDNS mutex.  */
3661             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3662             return (status);
3663         }
3664 
3665         /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT).  */
3666         query_name = temp_string_buffer;
3667         query_type = NX_MDNS_RR_TYPE_ALL;
3668     }
3669     else
3670     {
3671 
3672         /* Construct the PTR name.  */
3673         status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3674 
3675         /* Check the status.  */
3676         if (status)
3677         {
3678 
3679             /* Release the mDNS mutex.  */
3680             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3681             return (status);
3682         }
3683 
3684         /* Set the query name and query type.  */
3685         query_name = &temp_string_buffer[type_index];
3686         query_type = NX_MDNS_RR_TYPE_PTR;
3687     }
3688 
3689     /* Step2. Loop to start continuous query on all enabled interfaces.  */
3690     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3691     {
3692 
3693         /* Check if this interface is enabled.  */
3694         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3695             continue;
3696 
3697         /* Start continuous query.  */
3698         status = _nx_mdns_continuous_query(mdns_ptr, query_name, query_type, i);
3699 
3700         /* Check the status.  */
3701         if ((status == NX_SUCCESS) ||
3702             (status == NX_MDNS_EXIST_SAME_QUERY) ||
3703             (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3704             (status == NX_MDNS_EXIST_SHARED_RR))
3705             query_success = NX_TRUE;
3706     }
3707 
3708     /* Release the mDNS mutex.  */
3709     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3710 
3711     /* Check if start continuous query success.  */
3712     if (query_success)
3713         return (NX_MDNS_SUCCESS);
3714     else
3715         return(status);
3716 }
3717 
3718 
3719 /**************************************************************************/
3720 /*                                                                        */
3721 /*  FUNCTION                                               RELEASE        */
3722 /*                                                                        */
3723 /*    _nx_mdns_continuous_query                           PORTABLE C      */
3724 /*                                                           6.1.11       */
3725 /*  AUTHOR                                                                */
3726 /*                                                                        */
3727 /*    Yuxin Zhou, Microsoft Corporation                                   */
3728 /*                                                                        */
3729 /*  DESCRIPTION                                                           */
3730 /*                                                                        */
3731 /*    This function starts continuous query on specified interfaces.      */
3732 /*                                                                        */
3733 /*  INPUT                                                                 */
3734 /*                                                                        */
3735 /*    mdns_ptr                              Pointer to mDNS instance      */
3736 /*    interface_index                       The interface index           */
3737 /*    name                                  The resource record name      */
3738 /*    type                                  The resource record type      */
3739 /*                                                                        */
3740 /*  OUTPUT                                                                */
3741 /*                                                                        */
3742 /*    status                                Completion status             */
3743 /*                                                                        */
3744 /*  CALLS                                                                 */
3745 /*                                                                        */
3746 /*    tx_mutex_get                          Get the mDNS mutex            */
3747 /*    tx_mutex_put                          Put the mDNS mutex            */
3748 /*    _nx_mdns_query_check                  Check the query RR            */
3749 /*    _nx_mdns_cache_add_string             Add the string into cache     */
3750 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
3751 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
3752 /*                                            into cache                  */
3753 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
3754 /*                                            from cache                  */
3755 /*                                                                        */
3756 /*  CALLED BY                                                             */
3757 /*                                                                        */
3758 /*    Application Code                                                    */
3759 /*                                                                        */
3760 /*  RELEASE HISTORY                                                       */
3761 /*                                                                        */
3762 /*    DATE              NAME                      DESCRIPTION             */
3763 /*                                                                        */
3764 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3765 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3766 /*                                            resulting in version 6.1    */
3767 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3768 /*                                            corrected the random value, */
3769 /*                                            fixed the issue of timer,   */
3770 /*                                            resulting in version 6.1.11 */
3771 /*                                                                        */
3772 /**************************************************************************/
_nx_mdns_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT interface_index)3773 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index)
3774 {
3775 
3776 UINT        status;
3777 NX_MDNS_RR  *insert_rr;
3778 NX_MDNS_RR  temp_resource_record;
3779 UINT        name_length;
3780 
3781 
3782     /* Check the query RR.  */
3783     status = _nx_mdns_query_check(mdns_ptr, name, type, NX_FALSE, NX_NULL, interface_index);
3784 
3785     /* Check the state.  */
3786     if (status)
3787     {
3788         return(status);
3789     }
3790 
3791     /* Initialize the struct.  */
3792     memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3793 
3794     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3795     {
3796         return (NX_MDNS_DATA_SIZE_ERROR);
3797     }
3798 
3799     /* Add the name.  */
3800     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3801                                        (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3802 
3803     /* Check for error.  */
3804     if (status)
3805     {
3806         return(status);
3807     }
3808 
3809     /* Add the parameters.  */
3810     temp_resource_record.nx_mdns_rr_type = type;
3811     temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3812 
3813     /* Set the resource record status.  */
3814     temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3815 
3816     /* Remote resource record, set the owner flag.  */
3817     temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3818 
3819     /* Continuous query, set the query type flag.  */
3820     if ((type != NX_MDNS_RR_TYPE_A) &&
3821         (type != NX_MDNS_RR_TYPE_AAAA))
3822     {
3823         temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_CONTINUOUS_QUERY);
3824     }
3825 
3826     /* Set the interface index.  */
3827     temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3828 
3829     /* Add the resource record.  */
3830     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3831 
3832     /* Check for error.  */
3833     if (status)
3834     {
3835 
3836         /* Delete the same strings. */
3837         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3838         return(status);
3839     }
3840 
3841     /* A multicast DNS querier should also delay the first query of the series by
3842         a randomly chosen amount in the range 20-120ms.  */
3843     insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3844     insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3845 
3846     /* Set the mDNS timer.  */
3847     _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3848 
3849     /* Return success.  */
3850     return NX_SUCCESS;
3851 }
3852 
3853 
3854 /**************************************************************************/
3855 /*                                                                        */
3856 /*  FUNCTION                                               RELEASE        */
3857 /*                                                                        */
3858 /*    _nxe_mdns_service_query_stop                          PORTABLE C    */
3859 /*                                                           6.1          */
3860 /*  AUTHOR                                                                */
3861 /*                                                                        */
3862 /*    Yuxin Zhou, Microsoft Corporation                                   */
3863 /*                                                                        */
3864 /*  DESCRIPTION                                                           */
3865 /*                                                                        */
3866 /*    This function checks for errors in the mDNS resource record query   */
3867 /*    add function call.                                                  */
3868 /*                                                                        */
3869 /*  INPUT                                                                 */
3870 /*                                                                        */
3871 /*    mdns_ptr                              Pointer to mDNS instance      */
3872 /*    name                                  The name of the service       */
3873 /*    type                                  The type of the service       */
3874 /*    subtype                               The subtype of the service    */
3875 /*                                                                        */
3876 /*  OUTPUT                                                                */
3877 /*                                                                        */
3878 /*    status                                Completion status             */
3879 /*                                                                        */
3880 /*  CALLS                                                                 */
3881 /*                                                                        */
3882 /*    _nx_mdns_service_query_stop           Actual query RR function      */
3883 /*                                                                        */
3884 /*  CALLED BY                                                             */
3885 /*                                                                        */
3886 /*    Application Code                                                    */
3887 /*                                                                        */
3888 /*  RELEASE HISTORY                                                       */
3889 /*                                                                        */
3890 /*    DATE              NAME                      DESCRIPTION             */
3891 /*                                                                        */
3892 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3893 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3894 /*                                            resulting in version 6.1    */
3895 /*                                                                        */
3896 /**************************************************************************/
_nxe_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3897 UINT _nxe_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3898 {
3899 
3900 UINT    status;
3901 
3902 
3903     /* Check for invalid input pointers.  */
3904     if (!mdns_ptr)
3905     {
3906         return(NX_PTR_ERROR);
3907     }
3908 
3909     /* Check for invalid server attributes. */
3910     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3911     {
3912         return(NX_MDNS_PARAM_ERROR);
3913     }
3914 
3915     if (name)
3916     {
3917 
3918         /* Check the size.  */
3919         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
3920         {
3921             return(NX_MDNS_DATA_SIZE_ERROR);
3922         }
3923     }
3924 
3925     /* Call actual mDNS create service.  */
3926     status =  _nx_mdns_service_query_stop(mdns_ptr, name, type, sub_type);
3927 
3928     /* Return status.  */
3929     return(status);
3930 }
3931 
3932 
3933 /**************************************************************************/
3934 /*                                                                        */
3935 /*  FUNCTION                                               RELEASE        */
3936 /*                                                                        */
3937 /*    _nx_mdns_service_query_stop                         PORTABLE C      */
3938 /*                                                           6.1          */
3939 /*  AUTHOR                                                                */
3940 /*                                                                        */
3941 /*    Yuxin Zhou, Microsoft Corporation                                   */
3942 /*                                                                        */
3943 /*  DESCRIPTION                                                           */
3944 /*                                                                        */
3945 /*    This function adds the mDNS resource record into peer service cache,*/
3946 /*    mDNS thread send the query message using continuous type.           */
3947 /*                                                                        */
3948 /*  INPUT                                                                 */
3949 /*                                                                        */
3950 /*    mdns_ptr                              Pointer to mDNS instance      */
3951 /*    name                                  The name of the service       */
3952 /*    type                                  The type of the service       */
3953 /*    subtype                               The subtype of the service    */
3954 /*                                                                        */
3955 /*  OUTPUT                                                                */
3956 /*                                                                        */
3957 /*    status                                Completion status             */
3958 /*                                                                        */
3959 /*  CALLS                                                                 */
3960 /*                                                                        */
3961 /*    tx_mutex_get                          Get the mDNS mutex            */
3962 /*    tx_mutex_put                          Put the mDNS mutex            */
3963 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3964 /*    _nx_mdns_name_match                   Match the name string         */
3965 /*    _nx_mdns_rr_delete                    Delete the resource record    */
3966 /*                                                                        */
3967 /*  CALLED BY                                                             */
3968 /*                                                                        */
3969 /*    Application Code                                                    */
3970 /*                                                                        */
3971 /*  RELEASE HISTORY                                                       */
3972 /*                                                                        */
3973 /*    DATE              NAME                      DESCRIPTION             */
3974 /*                                                                        */
3975 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3976 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3977 /*                                            resulting in version 6.1    */
3978 /*                                                                        */
3979 /**************************************************************************/
_nx_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3980 UINT _nx_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3981 {
3982 
3983 UINT        status;
3984 UINT        type_index = 0;
3985 UINT        query_stop = NX_FALSE;
3986 ULONG       *head;
3987 NX_MDNS_RR  *p;
3988 UINT         rr_name_length;
3989 
3990 
3991     /* Get the mDNS mutex.  */
3992     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3993 
3994     if (type)
3995     {
3996         if (name)
3997         {
3998 
3999             /* Construct the SRV name.  */
4000             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4001 
4002             /* Check the status.  */
4003             if (status)
4004             {
4005 
4006                 /* Release the mDNS mutex.  */
4007                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4008                 return (status);
4009             }
4010         }
4011         else
4012         {
4013 
4014             /* Construct the PTR name.  */
4015             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4016 
4017             /* Check the status.  */
4018             if (status)
4019             {
4020 
4021                 /* Release the mDNS mutex.  */
4022                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4023                 return (status);
4024             }
4025         }
4026     }
4027 
4028     /* Get the remote buffer head. */
4029     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4030 
4031     if (!head)
4032     {
4033 
4034         /* Release the mDNS mutex.  */
4035         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4036 
4037         /* Return a successful status.  */
4038         return(NX_MDNS_CACHE_ERROR);
4039     }
4040 
4041     /* Set the pointer.  */
4042     head = (ULONG*)(*head);
4043 
4044     /* Loop to delete query resource record.  */
4045     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
4046     {
4047 
4048         /* Check the resource record state. */
4049         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
4050             continue;
4051 
4052         /* Check string length.  */
4053         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
4054         {
4055             continue;
4056         }
4057 
4058         if (!type)
4059         {
4060             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
4061                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
4062             {
4063 
4064                 /* Delete the resource records.  */
4065                 status = _nx_mdns_rr_delete(mdns_ptr, p);
4066 
4067                 /* Check status.  */
4068                 if (status == NX_MDNS_SUCCESS)
4069                     query_stop = NX_TRUE;
4070             }
4071         }
4072         else
4073         {
4074             if (name)
4075             {
4076                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) &&
4077                     (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length)))
4078                 {
4079 
4080                     /* Delete the resource records.  */
4081                     status = _nx_mdns_rr_delete(mdns_ptr, p);
4082 
4083                     /* Check status.  */
4084                     if (status == NX_MDNS_SUCCESS)
4085                         query_stop = NX_TRUE;
4086                 }
4087             }
4088             else
4089             {
4090                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)&&
4091                     (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[type_index], rr_name_length)))
4092                 {
4093 
4094                     /* Delete the resource records.  */
4095                     status = _nx_mdns_rr_delete(mdns_ptr, p);
4096 
4097                     /* Check status.  */
4098                     if (status == NX_MDNS_SUCCESS)
4099                         query_stop = NX_TRUE;
4100                 }
4101             }
4102         }
4103     }
4104 
4105     /* Release the mDNS mutex.  */
4106     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4107 
4108     /* Check if stop service continuous query.  */
4109     if (query_stop == NX_TRUE)
4110         return(NX_MDNS_SUCCESS);
4111     else
4112         return(NX_MDNS_ERROR);
4113 }
4114 
4115 
4116 /**************************************************************************/
4117 /*                                                                        */
4118 /*  FUNCTION                                               RELEASE        */
4119 /*                                                                        */
4120 /*    _nxe_mdns_service_lookup                              PORTABLE C    */
4121 /*                                                           6.1          */
4122 /*  AUTHOR                                                                */
4123 /*                                                                        */
4124 /*    Yuxin Zhou, Microsoft Corporation                                   */
4125 /*                                                                        */
4126 /*  DESCRIPTION                                                           */
4127 /*                                                                        */
4128 /*    This function checks for errors in the mDNS resource record query   */
4129 /*    add function call.                                                  */
4130 /*                                                                        */
4131 /*  INPUT                                                                 */
4132 /*                                                                        */
4133 /*    mdns_ptr                              Pointer to mDNS instance      */
4134 /*    name                                  The name of the service       */
4135 /*    type                                  The type of the service       */
4136 /*    subtype                               The subtype of the service    */
4137 /*    service_index                         The index of the service      */
4138 /*    service                               Pointer to Service instance   */
4139 /*                                                                        */
4140 /*  OUTPUT                                                                */
4141 /*                                                                        */
4142 /*    status                                Completion status             */
4143 /*                                                                        */
4144 /*  CALLS                                                                 */
4145 /*                                                                        */
4146 /*    _nx_mdns_service_lookup               Actual mDNS query RR function */
4147 /*                                                                        */
4148 /*  CALLED BY                                                             */
4149 /*                                                                        */
4150 /*    Application Code                                                    */
4151 /*                                                                        */
4152 /*  RELEASE HISTORY                                                       */
4153 /*                                                                        */
4154 /*    DATE              NAME                      DESCRIPTION             */
4155 /*                                                                        */
4156 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4157 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4158 /*                                            resulting in version 6.1    */
4159 /*                                                                        */
4160 /**************************************************************************/
_nxe_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4161 UINT _nxe_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4162 {
4163 
4164 UINT    status;
4165 
4166 
4167     /* Check for invalid input pointers.  */
4168     if (!mdns_ptr)
4169     {
4170         return(NX_PTR_ERROR);
4171     }
4172 
4173     /* Check for invalid server attributes. */
4174     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4175     {
4176         return(NX_MDNS_PARAM_ERROR);
4177     }
4178 
4179     if (name)
4180     {
4181 
4182         /* Check the size.  */
4183         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
4184         {
4185             return(NX_MDNS_DATA_SIZE_ERROR);
4186         }
4187     }
4188 
4189     /* Call actual mDNS create service.  */
4190     status =  _nx_mdns_service_lookup(mdns_ptr, name, type, sub_type, service_index, service);
4191 
4192     /* Return status.  */
4193     return(status);
4194 }
4195 
4196 
4197 /**************************************************************************/
4198 /*                                                                        */
4199 /*  FUNCTION                                               RELEASE        */
4200 /*                                                                        */
4201 /*    _nx_mdns_service_lookup                             PORTABLE C      */
4202 /*                                                           6.1.11       */
4203 /*  AUTHOR                                                                */
4204 /*                                                                        */
4205 /*    Yuxin Zhou, Microsoft Corporation                                   */
4206 /*                                                                        */
4207 /*  DESCRIPTION                                                           */
4208 /*                                                                        */
4209 /*    This function adds the mDNS resource record into peer service cache,*/
4210 /*    mDNS thread send the query message using continuous type.           */
4211 /*                                                                        */
4212 /*  INPUT                                                                 */
4213 /*                                                                        */
4214 /*    mdns_ptr                              Pointer to mDNS instance      */
4215 /*    name                                  The name of the service       */
4216 /*    type                                  The type of the service       */
4217 /*    subtype                               The subtype of the service    */
4218 /*    service_index                         The index of the service      */
4219 /*    service                               Pointer to Service instance   */
4220 /*                                                                        */
4221 /*  OUTPUT                                                                */
4222 /*                                                                        */
4223 /*    status                                Completion status             */
4224 /*                                                                        */
4225 /*  CALLS                                                                 */
4226 /*                                                                        */
4227 /*    tx_mutex_get                          Get the mDNS mutex            */
4228 /*    tx_mutex_put                          Put the mDNS mutex            */
4229 /*    tx_time_get                           Get the time                  */
4230 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
4231 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
4232 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
4233 /*    _nx_mdns_name_match                   Match the name string         */
4234 /*                                                                        */
4235 /*  CALLED BY                                                             */
4236 /*                                                                        */
4237 /*    Application Code                                                    */
4238 /*                                                                        */
4239 /*  RELEASE HISTORY                                                       */
4240 /*                                                                        */
4241 /*    DATE              NAME                      DESCRIPTION             */
4242 /*                                                                        */
4243 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4244 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4245 /*                                            verified memcpy use cases,  */
4246 /*                                            resulting in version 6.1    */
4247 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
4248 /*                                            fixed compiler warnings,    */
4249 /*                                            resulting in version 6.1.11 */
4250 /*                                                                        */
4251 /**************************************************************************/
_nx_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4252 UINT _nx_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4253 {
4254 
4255 UINT        status;
4256 UINT        type_index;
4257 UINT        dns_sd_flag;
4258 UINT        sub_type_flag;
4259 UINT        index;
4260 UINT        count;
4261 UINT        found;
4262 UCHAR       *srv_name = NX_NULL;
4263 UCHAR       *ptr;
4264 UCHAR       *tmp_sub_type;
4265 UCHAR       *tmp_type;
4266 UCHAR       *tmp_domain;
4267 NX_MDNS_RR  *p = NX_NULL;
4268 NX_MDNS_RR  *p1;
4269 ULONG       *head, *tail;
4270 UCHAR       i;
4271 UINT        interface_index = 0;
4272 UINT        temp_string_length;
4273 UINT        dns_sd_length;
4274 UINT        srv_name_length;
4275 UINT        target_string_length;
4276 
4277 
4278     /* Get the mDNS mutex.  */
4279     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4280 
4281     /* Zero out the content of service */
4282     memset(service, 0, sizeof(NX_MDNS_SERVICE));
4283 
4284     /* Initialize the struct.  */
4285     count = 0;
4286     found = NX_FALSE;
4287 
4288     /* Check the type.  */
4289     if (type)
4290     {
4291         if (name)
4292         {
4293 
4294             /* Construct the Service name.  */
4295             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4296 
4297         }
4298         else
4299         {
4300 
4301             /* Construct the Service name.  */
4302             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4303         }
4304         /* Check the status.  */
4305         if (status)
4306         {
4307 
4308             /* Release the mDNS mutex.  */
4309             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4310             return (status);
4311         }
4312 
4313         /* Check string length.  */
4314         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
4315         {
4316 
4317             /* Release the mDNS mutex.  */
4318             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4319             return (NX_MDNS_DATA_SIZE_ERROR);
4320         }
4321     }
4322 
4323     /* Check the DNS-SD string.  */
4324     if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_length, NX_MDNS_DNS_SD_MAX))
4325     {
4326 
4327         /* Release the mDNS mutex.  */
4328         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4329         return (NX_MDNS_DATA_SIZE_ERROR);
4330     }
4331 
4332     /* Loop to search local and peer cache.  */
4333     for(i = 0; i < 2; i++)
4334     {
4335 
4336         /* Set the pointer. */
4337         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
4338         {
4339 #ifndef NX_MDNS_DISABLE_SERVER
4340             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
4341 #else
4342             continue;
4343 #endif /* NX_MDNS_DISABLE_SERVER */
4344         }
4345         else
4346         {
4347             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4348         }
4349 
4350         if(head == NX_NULL)
4351             continue;
4352 
4353         /* Set the pointer.  */
4354         tail = (ULONG*)(*head);
4355 
4356         /* Check the resource record.  */
4357         for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
4358         {
4359 
4360             /* Check whether the resource record is valid. */
4361             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4362                 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4363                 continue;
4364 
4365             if((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) || (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4366             {
4367 
4368                 if(type)
4369                 {
4370                     if (_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], temp_string_length))
4371                         continue;
4372                 }
4373                 else if(p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
4374                     continue;
4375 
4376                 if(name && (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4377                 {
4378 
4379                     /* Store the service name.  */
4380                     srv_name = p -> nx_mdns_rr_name;
4381                     interface_index = p -> nx_mdns_rr_interface_index;
4382                 }
4383                 else
4384                 {
4385 
4386                     /* Set the service name pointer.  */
4387                     srv_name = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name;
4388                     interface_index = p -> nx_mdns_rr_interface_index;
4389                 }
4390 
4391                 /* Check string length.  */
4392                 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
4393                     continue;
4394 
4395                 /* Store the service name.  */
4396                 memcpy((CHAR *)(service -> buffer), (CHAR *)srv_name, srv_name_length + 1); /* Use case of memcpy is verified. */
4397 
4398                 /* Reslove the service name and check the PTR rdata name. Ignore the PTR when the PTR rdata does not pointer the service.  */
4399                 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
4400 
4401                 if (status)
4402                     continue;
4403 
4404                 if(type == NX_NULL)
4405                 {
4406 
4407                     /* Set the parameters.  */
4408                     sub_type_flag = NX_FALSE;
4409                     dns_sd_flag = NX_FALSE;
4410                     index = 0;
4411 
4412                     /* Check the PTR resource record with sub type.  */
4413                     ptr = p -> nx_mdns_rr_name;
4414                     while (*ptr != '\0')
4415                     {
4416                         if (*ptr == '.')
4417                         {
4418                             if (!_nx_mdns_name_match(ptr - index, (UCHAR *)"_sub", 4))
4419                             {
4420                                 sub_type_flag = NX_TRUE;
4421                                 break;
4422                             }
4423                             index = 0;
4424                         }
4425                         else
4426                             index ++;
4427                         ptr ++;
4428                     }
4429                     if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_length))
4430                     {
4431                         dns_sd_flag = NX_TRUE;
4432                     }
4433 
4434                     /* Check the DNS-SD PTR reousrce record.  */
4435                     if ((dns_sd_flag == NX_TRUE) ||
4436                         (sub_type_flag == NX_TRUE))
4437                     {
4438 
4439                         /* Find the PTR resource record which pointer to the service.  */
4440                         for(p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
4441                         {
4442 
4443                             /* Check whether the resource record is valid. */
4444                             if ((p1 == p) ||
4445                                 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4446                                 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4447                                 continue;
4448 
4449                             /* Check the interface index.  */
4450                             if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
4451                                 continue;
4452 
4453                             if (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
4454                             {
4455                                 if ((dns_sd_flag == NX_TRUE))
4456                                 {
4457 
4458                                     /* Check string length.  */
4459                                     if (_nx_utility_string_length_check((CHAR *)(p1 -> nx_mdns_rr_name), &target_string_length, NX_MDNS_NAME_MAX))
4460                                     {
4461                                         continue;
4462                                     }
4463 
4464                                     /* Set the pointer.  */
4465                                     memcpy((CHAR *)&target_string_buffer[0], (CHAR *)(p1 -> nx_mdns_rr_name), target_string_length + 1); /* Use case of memcpy is verified. */
4466 
4467                                     /* Reslove the type.  */
4468                                     status = _nx_mdns_service_name_resolve(&target_string_buffer[0], &tmp_sub_type, &tmp_type, &tmp_domain);
4469 
4470                                     if (status)
4471                                         continue;
4472 
4473                                     /* Check string length.  */
4474                                     if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4475                                     {
4476                                         continue;
4477                                     }
4478 
4479                                     /* Construct the type and doamin, _http._tcp.local.  */
4480                                     *(tmp_type + target_string_length) = '.';
4481 
4482                                     /* Check string length.  */
4483                                     if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4484                                     {
4485                                         continue;
4486                                     }
4487 
4488                                     /* Compare the DNS_SD rdata.  */
4489                                     if (!_nx_mdns_name_match(tmp_type, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, target_string_length))
4490                                     {
4491 
4492                                         /* Exist resource record including more info.  */
4493                                         count --;
4494                                         break;
4495                                     }
4496                                 }
4497                                 else
4498                                 {
4499 
4500                                     /* Exist the PTR RR which pointer to the same service.  */
4501                                     if (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
4502                                     {
4503                                         count --;
4504                                         break;
4505                                     }
4506                                 }
4507                             }
4508                         }
4509                     }
4510                 }
4511 
4512                 /* Check the count state.  */
4513                 if (count == service_index)
4514                 {
4515                     /* Yes, find. */
4516                     found = NX_TRUE;
4517                     break;
4518                 }
4519                 count ++;
4520             }
4521         }
4522 
4523         /* Check if find the service.  */
4524         if (found == NX_TRUE)
4525         {
4526             break;
4527         }
4528     }
4529 
4530     if (found)
4531     {
4532 
4533         /* Update the elasped time.  */
4534         p -> nx_mdns_rr_elapsed_time = tx_time_get();
4535 
4536         /* Get the additional information.  */
4537         _nx_mdns_service_addition_info_get(mdns_ptr, srv_name, service, interface_index);
4538 
4539         /* Release the mDNS mutex.  */
4540         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4541         return(NX_MDNS_SUCCESS);
4542     }
4543     else
4544     {
4545         /* Release the mDNS mutex.  */
4546         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4547         return(NX_MDNS_NO_MORE_ENTRIES);
4548     }
4549 }
4550 
4551 
4552 /**************************************************************************/
4553 /*                                                                        */
4554 /*  FUNCTION                                               RELEASE        */
4555 /*                                                                        */
4556 /*    _nxe_mdns_peer_cache_clear                            PORTABLE C    */
4557 /*                                                           6.1          */
4558 /*  AUTHOR                                                                */
4559 /*                                                                        */
4560 /*    Yuxin Zhou, Microsoft Corporation                                   */
4561 /*                                                                        */
4562 /*  DESCRIPTION                                                           */
4563 /*                                                                        */
4564 /*    This function checks for errors in the mDNS peer service cache      */
4565 /*    clear function call.                                                */
4566 /*                                                                        */
4567 /*  INPUT                                                                 */
4568 /*                                                                        */
4569 /*    mdns_ptr                              Pointer to mDNS instance      */
4570 /*                                                                        */
4571 /*  OUTPUT                                                                */
4572 /*                                                                        */
4573 /*    status                                Completion status             */
4574 /*                                                                        */
4575 /*  CALLS                                                                 */
4576 /*                                                                        */
4577 /*    _nx_mdns_peer_cache_clear             Actual peer cache clear       */
4578 /*                                            function                    */
4579 /*                                                                        */
4580 /*  CALLED BY                                                             */
4581 /*                                                                        */
4582 /*    Application Code                                                    */
4583 /*                                                                        */
4584 /*  RELEASE HISTORY                                                       */
4585 /*                                                                        */
4586 /*    DATE              NAME                      DESCRIPTION             */
4587 /*                                                                        */
4588 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4589 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4590 /*                                            resulting in version 6.1    */
4591 /*                                                                        */
4592 /**************************************************************************/
_nxe_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4593 UINT _nxe_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4594 {
4595 
4596 UINT    status;
4597 
4598 
4599     /* Check for invalid input pointers.  */
4600     if (!mdns_ptr)
4601     {
4602         return(NX_PTR_ERROR);
4603     }
4604 
4605     /* Check for invalid server attributes. */
4606     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4607     {
4608         return(NX_MDNS_PARAM_ERROR);
4609     }
4610 
4611     /* Call actual mDNS create service.  */
4612     status =  _nx_mdns_peer_cache_clear(mdns_ptr);
4613 
4614     /* Return status.  */
4615     return(status);
4616 }
4617 
4618 
4619 /**************************************************************************/
4620 /*                                                                        */
4621 /*  FUNCTION                                               RELEASE        */
4622 /*                                                                        */
4623 /*    _nx_mdns_peer_cache_clear                           PORTABLE C      */
4624 /*                                                           6.1          */
4625 /*  AUTHOR                                                                */
4626 /*                                                                        */
4627 /*    Yuxin Zhou, Microsoft Corporation                                   */
4628 /*                                                                        */
4629 /*  DESCRIPTION                                                           */
4630 /*                                                                        */
4631 /*    This function clears the mDNS peer service cache.                   */
4632 /*                                                                        */
4633 /*  INPUT                                                                 */
4634 /*                                                                        */
4635 /*    mdns_ptr                              Pointer to mDNS instance      */
4636 /*                                                                        */
4637 /*  OUTPUT                                                                */
4638 /*                                                                        */
4639 /*    status                                Completion status             */
4640 /*                                                                        */
4641 /*  CALLS                                                                 */
4642 /*                                                                        */
4643 /*    tx_mutex_get                          Get the mDNS mutex            */
4644 /*    tx_mutex_put                          Put the mDNS mutex            */
4645 /*    _nx_mdns_cache_initialize             Initialize the cache          */
4646 /*                                                                        */
4647 /*  CALLED BY                                                             */
4648 /*                                                                        */
4649 /*    Application Code                                                    */
4650 /*                                                                        */
4651 /*  RELEASE HISTORY                                                       */
4652 /*                                                                        */
4653 /*    DATE              NAME                      DESCRIPTION             */
4654 /*                                                                        */
4655 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4656 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4657 /*                                            resulting in version 6.1    */
4658 /*                                                                        */
4659 /**************************************************************************/
_nx_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4660 UINT _nx_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4661 {
4662 
4663 UINT    status;
4664 
4665 
4666     /* Get the mDNS mutex.  */
4667     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4668 
4669     status = _nx_mdns_cache_initialize(mdns_ptr, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_peer_service_cache, mdns_ptr -> nx_mdns_peer_service_cache_size);
4670 
4671     /* Release the mDNS mutex.  */
4672     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4673 
4674     /* Return a error status.  */
4675     return(status);
4676 }
4677 
4678 
4679 /**************************************************************************/
4680 /*                                                                        */
4681 /*  FUNCTION                                               RELEASE        */
4682 /*                                                                        */
4683 /*    _nxe_mdns_host_address_get                          PORTABLE C      */
4684 /*                                                           6.1          */
4685 /*  AUTHOR                                                                */
4686 /*                                                                        */
4687 /*    Yuxin Zhou, Microsoft Corporation                                   */
4688 /*                                                                        */
4689 /*  DESCRIPTION                                                           */
4690 /*                                                                        */
4691 /*    This function checks for errors in the mDNS host address get        */
4692 /*    function call.                                                      */
4693 /*                                                                        */
4694 /*  INPUT                                                                 */
4695 /*                                                                        */
4696 /*    mdns_ptr                              Pointer to mDNS instance      */
4697 /*    name                                  The name of the service       */
4698 /*    type                                  The type of the service       */
4699 /*    subtype                               The subtype of the service    */
4700 /*    service                               Pointer to response service   */
4701 /*    timeout                               The timeour for service query */
4702 /*                                                                        */
4703 /*  OUTPUT                                                                */
4704 /*                                                                        */
4705 /*    status                                Completion status             */
4706 /*                                                                        */
4707 /*  CALLS                                                                 */
4708 /*                                                                        */
4709 /*    _nx_mdns_host_address_get             Actual mDNS host address      */
4710 /*                                            get function                */
4711 /*                                                                        */
4712 /*  CALLED BY                                                             */
4713 /*                                                                        */
4714 /*    Application Code                                                    */
4715 /*                                                                        */
4716 /*  RELEASE HISTORY                                                       */
4717 /*                                                                        */
4718 /*    DATE              NAME                      DESCRIPTION             */
4719 /*                                                                        */
4720 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4721 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
4722 /*                                            buffer length verification, */
4723 /*                                            resulting in version 6.1    */
4724 /*                                                                        */
4725 /**************************************************************************/
_nxe_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4726 UINT _nxe_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address,  UINT timeout)
4727 {
4728 
4729 UINT    status;
4730 
4731 
4732     /* Check for invalid input pointers.  */
4733     if ((!mdns_ptr) || (!host_name))
4734     {
4735         return(NX_PTR_ERROR);
4736     }
4737 
4738     /* Check for mDNS started flag.  */
4739     if (!mdns_ptr -> nx_mdns_started)
4740     {
4741         return(NX_MDNS_NOT_STARTED);
4742     }
4743 
4744     /* Call actual mDNS create service.  */
4745     status = _nx_mdns_host_address_get(mdns_ptr, host_name, ipv4_address, ipv6_address, timeout);
4746 
4747     /* Return status.  */
4748     return(status);
4749 }
4750 
4751 
4752 /**************************************************************************/
4753 /*                                                                        */
4754 /*  FUNCTION                                               RELEASE        */
4755 /*                                                                        */
4756 /*    _nx_mdns_host_address_get                           PORTABLE C      */
4757 /*                                                           6.1          */
4758 /*  AUTHOR                                                                */
4759 /*                                                                        */
4760 /*    Yuxin Zhou, Microsoft Corporation                                   */
4761 /*                                                                        */
4762 /*  DESCRIPTION                                                           */
4763 /*                                                                        */
4764 /*    This function adds the mDNS query record into peer buffer,          */
4765 /*    mDNS thread send the query message using one-shot type.             */
4766 /*                                                                        */
4767 /*  INPUT                                                                 */
4768 /*                                                                        */
4769 /*    mdns_ptr                              Pointer to mDNS instance      */
4770 /*    name                                  The name of the service       */
4771 /*    type                                  The type of the service       */
4772 /*    subtype                               The subtype of the service    */
4773 /*    service                               Pointer to response service   */
4774 /*    timeout                               The timeour for service query */
4775 /*                                                                        */
4776 /*  OUTPUT                                                                */
4777 /*                                                                        */
4778 /*    status                                Completion status             */
4779 /*                                                                        */
4780 /*  CALLS                                                                 */
4781 /*                                                                        */
4782 /*    tx_mutex_get                          Get the mDNS mutex            */
4783 /*    tx_mutex_put                          Put the mDNS mutex            */
4784 /*    tx_time_get                           Get the mDNS time             */
4785 /*    _nx_mdns_host_check                   Check the host info           */
4786 /*    _nx_mdns_answer_wait                  Wait the answer               */
4787 /*    _nx_mdns_cache_add_query              Add the query into cache      */
4788 /*    _nx_mdns_cache_delete_query           Delete the query from cache   */
4789 /*                                                                        */
4790 /*  CALLED BY                                                             */
4791 /*                                                                        */
4792 /*    Application Code                                                    */
4793 /*                                                                        */
4794 /*  RELEASE HISTORY                                                       */
4795 /*                                                                        */
4796 /*    DATE              NAME                      DESCRIPTION             */
4797 /*                                                                        */
4798 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4799 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4800 /*                                            verified memcpy use cases,  */
4801 /*                                            resulting in version 6.1    */
4802 /*                                                                        */
4803 /**************************************************************************/
_nx_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4804 UINT _nx_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4805 {
4806 
4807 UINT                status;
4808 ULONG               start_time;
4809 ULONG               current_time;
4810 ULONG               elapsed_time;
4811 ULONG               wait_time = timeout;
4812 NX_MDNS_RR         *a_rr;
4813 NX_MDNS_RR         *aaaa_rr;
4814 UCHAR               host_name_query[NX_MDNS_NAME_MAX + 1];
4815 UINT                i = 0;
4816 UCHAR               domain_flag = NX_FALSE;
4817 UINT                answer = NX_FALSE;
4818 UINT                domain_name_length;
4819 
4820 
4821     /* Check string length.  */
4822     if (_nx_utility_string_length_check((CHAR *)host_name, NX_NULL, NX_MDNS_HOST_NAME_MAX))
4823     {
4824         return(NX_MDNS_DATA_SIZE_ERROR);
4825     }
4826 
4827     /* Get the mDNS mutex.  */
4828     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
4829 
4830     /* Clear the buffer.  */
4831     memset(host_name_query, 0, NX_MDNS_NAME_MAX + 1);
4832 
4833     /* Copy the host name into host name query buffer.  */
4834     while(host_name[i] != NX_NULL)
4835     {
4836         host_name_query[i] = host_name[i];
4837         if (host_name[i] == '.')
4838         {
4839 
4840             /* Update the flag.  */
4841             domain_flag = NX_TRUE;
4842         }
4843         i++;
4844     }
4845 
4846     /* Check if include the domain.  */
4847     if (domain_flag == NX_FALSE)
4848     {
4849         host_name_query[i++] = '.';
4850 
4851         /* Check string length.  */
4852         if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &domain_name_length, NX_MDNS_DOMAIN_NAME_MAX))
4853         {
4854 
4855             /* Release the mDNS mutex.  */
4856             tx_mutex_put(&(mdns_ptr->nx_mdns_mutex));
4857             return (NX_MDNS_DATA_SIZE_ERROR);
4858         }
4859 
4860         memcpy((char*)(&host_name_query[i]), (const char*)mdns_ptr -> nx_mdns_domain_name, domain_name_length + 1); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX and NX_MDNS_DOMAIN_NAME_MAX are limited in nxd_mdns.h. */
4861     }
4862 
4863     /* Initialize the value.  */
4864     if (ipv4_address)
4865         *ipv4_address = NX_NULL;
4866     if (ipv6_address)
4867         memset(ipv6_address, 0, 16);
4868 
4869     /* Start host address query on all enabled interfaces until get the answer or query timeout.  */
4870     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
4871     {
4872 
4873         /* Check if this interface is enabled.  */
4874         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
4875             continue;
4876 
4877         /* Get the query start time.  */
4878         wait_time = timeout;
4879         start_time = tx_time_get();
4880 
4881         /* Get the host IPv4 address.  */
4882         if (ipv4_address)
4883         {
4884 
4885             /* One shot query for host name.  */
4886             status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_A, &a_rr, wait_time, i);
4887 
4888             /* Check the status.  */
4889             if (status == NX_MDNS_SUCCESS)
4890             {
4891 
4892                 /* Set the IPv4 address.  */
4893                 *ipv4_address = a_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
4894                 answer = NX_TRUE;
4895             }
4896         }
4897 
4898         /* Get the host IPv6 address.  */
4899         if (ipv6_address)
4900         {
4901 
4902             /* How much time has elapsed? */
4903             current_time = tx_time_get();
4904 
4905             /* Has the time wrapped? */
4906             if (current_time >= start_time)
4907             {
4908                 /* No, simply subtract to get the elapsed time.   */
4909                 elapsed_time =  current_time - start_time;
4910             }
4911             else
4912             {
4913 
4914                 /* Yes it has. Time has rolled over the 32-bit boundary.  */
4915                 elapsed_time =  (((ULONG) 0xFFFFFFFF) - start_time) + current_time;
4916             }
4917 
4918             /* Update the timeout.  */
4919             if (wait_time > elapsed_time)
4920                 wait_time -= elapsed_time;
4921             else
4922                 wait_time = 0;
4923 
4924             /* Lookup the service.  */
4925             status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_AAAA, &aaaa_rr, wait_time, i);
4926 
4927             /* Check the status.  */
4928             if (status == NX_MDNS_SUCCESS)
4929             {
4930 
4931                 /* Set the IPv6 address.  */
4932                 *ipv6_address = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[0];
4933                 *(ipv6_address + 1) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[1];
4934                 *(ipv6_address + 2) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[2];
4935                 *(ipv6_address + 3) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[3];
4936                 answer = NX_TRUE;
4937             }
4938         }
4939 
4940         /* Check if get IPv4 address or IPv6 address.  */
4941         if (answer == NX_TRUE)
4942         {
4943 
4944             /* Release the mDNS mutex.  */
4945             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4946             return (NX_MDNS_SUCCESS);
4947         }
4948     }
4949 
4950     /* Release the mDNS mutex.  */
4951     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4952     return (NX_MDNS_ERROR);
4953 }
4954 #endif /* NX_MDNS_DISABLE_CLIENT */
4955 
4956 
4957 #ifndef NX_MDNS_DISABLE_SERVER
4958 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
4959 /**************************************************************************/
4960 /*                                                                        */
4961 /*  FUNCTION                                               RELEASE        */
4962 /*                                                                        */
4963 /*    _nx_mdns_rr_a_aaaa_add                                PORTABLE C    */
4964 /*                                                           6.1          */
4965 /*  AUTHOR                                                                */
4966 /*                                                                        */
4967 /*    Yuxin Zhou, Microsoft Corporation                                   */
4968 /*                                                                        */
4969 /*  DESCRIPTION                                                           */
4970 /*                                                                        */
4971 /*    This function adds the mDNS A/AAAA resource record into local cache.*/
4972 /*                                                                        */
4973 /*  INPUT                                                                 */
4974 /*                                                                        */
4975 /*    mdns_ptr                              Pointer to mDNS instance      */
4976 /*    set                                   The resource record set       */
4977 /*    address                               The resource record address   */
4978 /*    insert_rr                             Pointer to insert resource    */
4979 /*                                            record                      */
4980 /*    name                                  Host name                     */
4981 /*    ttl                                   The resource record ttl       */
4982 /*                                                                        */
4983 /*  OUTPUT                                                                */
4984 /*                                                                        */
4985 /*    status                                Completion status             */
4986 /*                                                                        */
4987 /*  CALLS                                                                 */
4988 /*                                                                        */
4989 /*    tx_mutex_get                          Get the mDNS mutex            */
4990 /*    tx_mutex_put                          Put the mDNS mutex            */
4991 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
4992 /*    _nx_mdns_cache_add_string             Add the string into cache     */
4993 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
4994 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
4995 /*                                            into cache                  */
4996 /*                                                                        */
4997 /*  CALLED BY                                                             */
4998 /*                                                                        */
4999 /*    _nx_mdns_host_name_register           Register the host name        */
5000 /*                                                                        */
5001 /*  RELEASE HISTORY                                                       */
5002 /*                                                                        */
5003 /*    DATE              NAME                      DESCRIPTION             */
5004 /*                                                                        */
5005 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5006 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5007 /*                                            resulting in version 6.1    */
5008 /*                                                                        */
5009 /**************************************************************************/
_nx_mdns_rr_a_aaaa_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG * address,UINT addr_length,UCHAR type,UINT interface_index)5010 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index)
5011 {
5012 UINT        status;
5013 NX_MDNS_RR *insert_rr;
5014 USHORT      rr_type;
5015 NX_MDNS_RR  temp_resource_record;
5016 
5017 
5018     /* Set the resource record type.  */
5019     if(addr_length == 4)
5020         rr_type = NX_MDNS_RR_TYPE_A;
5021     else
5022         rr_type = NX_MDNS_RR_TYPE_AAAA;
5023 
5024     /* Set the resource record parameters.  */
5025     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, rr_type, NX_MDNS_RR_TTL_HOST, addr_length, NX_MDNS_RR_SET_UNIQUE, type, NX_FALSE, &temp_resource_record, interface_index);
5026 
5027     /* Check for error.  */
5028     if (status)
5029     {
5030         return(status);
5031     }
5032 
5033     /* Add the parameters.  */
5034     if(rr_type == NX_MDNS_RR_TYPE_A)
5035     {
5036         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = *address;
5037     }
5038     else
5039     {
5040         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = *address;
5041         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = *(address +1);
5042         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = *(address + 2);
5043         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = *(address + 3);
5044     }
5045 
5046     /* Add the resource record.  */
5047     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5048 
5049     /* Check for error.  */
5050     if (status)
5051     {
5052 
5053         /* Delete the name strings. */
5054         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5055         return(status);
5056     }
5057 
5058     /* Set the mDNS timer.  */
5059     _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
5060 
5061     /* Return a successful status.  */
5062     return(NX_SUCCESS);
5063 }
5064 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
5065 
5066 
5067 /**************************************************************************/
5068 /*                                                                        */
5069 /*  FUNCTION                                               RELEASE        */
5070 /*                                                                        */
5071 /*    _nx_mdns_rr_ptr_add                                 PORTABLE C      */
5072 /*                                                           6.1          */
5073 /*  AUTHOR                                                                */
5074 /*                                                                        */
5075 /*    Yuxin Zhou, Microsoft Corporation                                   */
5076 /*                                                                        */
5077 /*  DESCRIPTION                                                           */
5078 /*                                                                        */
5079 /*    This function adds the mDNS PTR resource record into local buffer.  */
5080 /*                                                                        */
5081 /*  INPUT                                                                 */
5082 /*                                                                        */
5083 /*    mdns_ptr                              Pointer to mDNS instance      */
5084 /*    name                                  The resource record name      */
5085 /*    ttl                                   The resource record ttl       */
5086 /*    set                                   The resource record set       */
5087 /*    ptr_name                              The domain name               */
5088 /*    insert_rr                             Pointer to insert resource    */
5089 /*                                            record                      */
5090 /*                                                                        */
5091 /*  OUTPUT                                                                */
5092 /*                                                                        */
5093 /*    status                                Completion status             */
5094 /*                                                                        */
5095 /*  CALLS                                                                 */
5096 /*                                                                        */
5097 /*    tx_mutex_get                          Get the mDNS mutex            */
5098 /*    tx_mutex_put                          Put the mDNS mutex            */
5099 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5100 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5101 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5102 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5103 /*                                            into cache                  */
5104 /*                                                                        */
5105 /*  CALLED BY                                                             */
5106 /*                                                                        */
5107 /*    Application Code                                                    */
5108 /*                                                                        */
5109 /*  RELEASE HISTORY                                                       */
5110 /*                                                                        */
5111 /*    DATE              NAME                      DESCRIPTION             */
5112 /*                                                                        */
5113 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5114 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5115 /*                                            resulting in version 6.1    */
5116 /*                                                                        */
5117 /**************************************************************************/
_nx_mdns_rr_ptr_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * ptr_name,UCHAR is_valid,NX_MDNS_RR ** insert_rr,UINT interface_index)5118 static UINT _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index)
5119 {
5120 
5121 UINT        status;
5122 NX_MDNS_RR  *ptr_rr;
5123 NX_MDNS_RR  temp_resource_record;
5124 UINT        ptr_name_length;
5125 
5126 
5127     if (_nx_utility_string_length_check((CHAR *)ptr_name, &ptr_name_length, NX_MDNS_NAME_MAX))
5128     {
5129         return (NX_MDNS_DATA_SIZE_ERROR);
5130     }
5131 
5132     /* Get the mDNS mutex.  */
5133     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5134 
5135     /* Set the resource record parameters. Rdata length: PTR name, string should include the first'.' and last '\0'.  */
5136     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_PTR, ttl, (ptr_name_length + 2), set, NX_TRUE, is_valid, &temp_resource_record, interface_index);
5137 
5138     /* Check for error.  */
5139     if (status)
5140     {
5141 
5142         /* Release the mDNS mutex.  */
5143         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5144 
5145         return(status);
5146     }
5147 
5148     /* Add the ptr name.  */
5149     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, ptr_name, ptr_name_length,
5150                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name),
5151                                        NX_FALSE, NX_TRUE);
5152 
5153     /* Check for error.  */
5154     if (status)
5155     {
5156 
5157         /* Delete the strings. */
5158         _nx_mdns_cache_delete_string(mdns_ptr,  NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5159 
5160         /* Release the mDNS mutex.  */
5161         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5162 
5163         return(status);
5164     }
5165 
5166     /* Add the resource record.  */
5167     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &ptr_rr, NX_NULL);
5168 
5169     /* Check for error.  */
5170     if (status)
5171     {
5172 
5173         /* Delete the same strings. */
5174         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5175 
5176         /* Delete the same strings. */
5177         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, 0);
5178 
5179         /* Release the mDNS mutex.  */
5180         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5181 
5182         return(status);
5183     }
5184 
5185     /* Set the mDNS timer.  */
5186     _nx_mdns_timer_set(mdns_ptr, ptr_rr, ptr_rr -> nx_mdns_rr_timer_count);
5187 
5188     if (insert_rr)
5189         *insert_rr = ptr_rr;
5190 
5191     /* Release the mDNS mutex.  */
5192     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5193 
5194     /* Return a successful status.  */
5195     return(NX_SUCCESS);
5196 }
5197 
5198 
5199 /**************************************************************************/
5200 /*                                                                        */
5201 /*  FUNCTION                                               RELEASE        */
5202 /*                                                                        */
5203 /*    _nx_mdns_rr_srv_add                                 PORTABLE C      */
5204 /*                                                           6.1          */
5205 /*  AUTHOR                                                                */
5206 /*                                                                        */
5207 /*    Yuxin Zhou, Microsoft Corporation                                   */
5208 /*                                                                        */
5209 /*  DESCRIPTION                                                           */
5210 /*                                                                        */
5211 /*    This function adds the mDNS SRV resource record into local buffer.  */
5212 /*                                                                        */
5213 /*  INPUT                                                                 */
5214 /*                                                                        */
5215 /*    mdns_ptr                              Pointer to mDNS instance      */
5216 /*    name                                  Service nstance name          */
5217 /*    ttl                                   The ttl of the service        */
5218 /*    set                                   The resource record set       */
5219 /*    priority                              The priority of target host   */
5220 /*    weights                               Service weight                */
5221 /*    port                                  The port on this target host  */
5222 /*    target                                The target host               */
5223 /*    insert_rr                             Pointer to insert record      */
5224 /*                                                                        */
5225 /*  OUTPUT                                                                */
5226 /*                                                                        */
5227 /*    status                                Completion status             */
5228 /*                                                                        */
5229 /*  CALLS                                                                 */
5230 /*                                                                        */
5231 /*    tx_mutex_get                          Get the mDNS mutex            */
5232 /*    tx_mutex_put                          Put the mDNS mutex            */
5233 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5234 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5235 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5236 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5237 /*                                            into cache                  */
5238 /*                                                                        */
5239 /*  CALLED BY                                                             */
5240 /*                                                                        */
5241 /*    Application Code                                                    */
5242 /*                                                                        */
5243 /*  RELEASE HISTORY                                                       */
5244 /*                                                                        */
5245 /*    DATE              NAME                      DESCRIPTION             */
5246 /*                                                                        */
5247 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5248 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5249 /*                                            resulting in version 6.1    */
5250 /*                                                                        */
5251 /**************************************************************************/
_nx_mdns_rr_srv_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,USHORT priority,USHORT weights,USHORT port,UCHAR * target,NX_MDNS_RR ** insert_rr,UINT interface_index)5252 static UINT _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority,
5253                                 USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index)
5254 {
5255 
5256 UINT        status;
5257 NX_MDNS_RR  *srv_rr;
5258 NX_MDNS_RR  temp_resource_record;
5259 UINT        target_length;
5260 
5261     if (_nx_utility_string_length_check((CHAR *)target, &target_length, NX_MDNS_NAME_MAX))
5262     {
5263         return (NX_MDNS_DATA_SIZE_ERROR);
5264     }
5265 
5266     /* Get the mDNS mutex.  */
5267     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5268 
5269     /* Set the resource record parameters. Rdata length: PRIORITY, WEIGHTS, PORT, TARGET, name string should include the first'.' and last '\0'.  */
5270     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_SRV, ttl, target_length + 8, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5271 
5272     /* Check for error.  */
5273     if (status)
5274     {
5275         /* Release the mDNS mutex.  */
5276         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5277 
5278         return(status);
5279     }
5280 
5281     /* Add the name.  */
5282     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, target, target_length,
5283                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
5284                                        NX_FALSE, NX_TRUE);
5285 
5286     /* Check for error.  */
5287     if (status)
5288     {
5289 
5290         /* Delete the same strings. */
5291         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5292 
5293         /* Release the mDNS mutex.  */
5294         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5295 
5296         return(status);
5297     }
5298 
5299     /* Set the SRV parameters.  */
5300     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = priority;
5301     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = weights;
5302     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = port;
5303 
5304     /* Add the resource record.  */
5305     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &srv_rr, NX_NULL);
5306 
5307     /* Check for error.  */
5308     if (status)
5309     {
5310         /* Delete the same strings. */
5311         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5312 
5313         /* Delete the same strings. */
5314         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
5315 
5316         /* Release the mDNS mutex.  */
5317         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5318 
5319         return(status);
5320     }
5321 
5322     /* Set the mDNS timer.  */
5323     _nx_mdns_timer_set(mdns_ptr, srv_rr, srv_rr -> nx_mdns_rr_timer_count);
5324 
5325     if (insert_rr)
5326         *insert_rr = srv_rr;
5327 
5328     /* Release the mDNS mutex.  */
5329     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5330 
5331     /* Return a successful status.  */
5332     return(NX_SUCCESS);
5333 }
5334 
5335 
5336 /**************************************************************************/
5337 /*                                                                        */
5338 /*  FUNCTION                                               RELEASE        */
5339 /*                                                                        */
5340 /*    _nx_mdns_rr_txt_add                                 PORTABLE C      */
5341 /*                                                           6.1          */
5342 /*  AUTHOR                                                                */
5343 /*                                                                        */
5344 /*    Yuxin Zhou, Microsoft Corporation                                   */
5345 /*                                                                        */
5346 /*  DESCRIPTION                                                           */
5347 /*                                                                        */
5348 /*    This function adds the mDNS TXT resource record into local buffer.  */
5349 /*    the TXT records are formatted in a "key=value" notation with ";"    */
5350 /*    acting as separator when more then one key is available.            */
5351 /*                                                                        */
5352 /*  INPUT                                                                 */
5353 /*                                                                        */
5354 /*    mdns_ptr                              Pointer to mDNS instance      */
5355 /*    name                                  The resource record name      */
5356 /*    ttl                                   The resource record ttl       */
5357 /*    set                                   The resource record set       */
5358 /*    txt                                   The txt string                */
5359 /*    insert_rr                             Pointer to insert record      */
5360 /*                                                                        */
5361 /*  OUTPUT                                                                */
5362 /*                                                                        */
5363 /*    status                                Completion status             */
5364 /*                                                                        */
5365 /*  CALLS                                                                 */
5366 /*                                                                        */
5367 /*    tx_mutex_get                          Get the mDNS mutex            */
5368 /*    tx_mutex_put                          Put the mDNS mutex            */
5369 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5370 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5371 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5372 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5373 /*                                            into the cache              */
5374 /*                                                                        */
5375 /*  CALLED BY                                                             */
5376 /*                                                                        */
5377 /*    Application Code                                                    */
5378 /*                                                                        */
5379 /*  RELEASE HISTORY                                                       */
5380 /*                                                                        */
5381 /*    DATE              NAME                      DESCRIPTION             */
5382 /*                                                                        */
5383 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5384 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5385 /*                                            resulting in version 6.1    */
5386 /*                                                                        */
5387 /**************************************************************************/
_nx_mdns_rr_txt_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * txt,NX_MDNS_RR ** insert_rr,UINT interface_index)5388 static UINT _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index)
5389 {
5390 
5391 UINT        status;
5392 NX_MDNS_RR  *txt_rr;
5393 NX_MDNS_RR  temp_resource_record;
5394 UINT        txt_length;
5395 
5396 
5397     /* Get the mDNS mutex.  */
5398     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5399 
5400     /* Set the resource record parameters.  */
5401     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_TXT, ttl, 0, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5402 
5403     /* Check for error.  */
5404     if (status)
5405     {
5406         /* Release the mDNS mutex.  */
5407         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5408 
5409         return(status);
5410     }
5411 
5412     if (txt)
5413     {
5414 
5415         /* Check string length.  */
5416         if (_nx_utility_string_length_check((CHAR *)txt, &txt_length, NX_MDNS_NAME_MAX))
5417         {
5418 
5419             /* Release the mDNS mutex.  */
5420             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5421             return (NX_MDNS_DATA_SIZE_ERROR);
5422         }
5423 
5424         /* Calculate the text string.inlcude the one byte label.  */
5425         temp_resource_record.nx_mdns_rr_rdata_length = (USHORT)(txt_length + 1);
5426 
5427         /* Add the name.  */
5428         status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, txt, txt_length,
5429                                            (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data),
5430                                            NX_FALSE, NX_TRUE);
5431 
5432         /* Check for error.  */
5433         if (status)
5434         {
5435 
5436             /* Delete the same strings. */
5437             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5438 
5439             /* Release the mDNS mutex.  */
5440             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5441 
5442             return(status);
5443         }
5444     }
5445     else
5446     {
5447         temp_resource_record.nx_mdns_rr_rdata_length = 1;
5448         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = NX_NULL;
5449     }
5450 
5451     /* Add the resource record.  */
5452     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &txt_rr, NX_NULL);
5453 
5454     /* Check for error.  */
5455     if (status)
5456     {
5457 
5458         /* Delete the same strings. */
5459         _nx_mdns_cache_delete_string(mdns_ptr,NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5460 
5461         if (txt)
5462         {
5463 
5464             /* Delete the same strings. */
5465             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data, 0);
5466         }
5467 
5468         /* Release the mDNS mutex.  */
5469         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5470 
5471         return(status);
5472     }
5473 
5474     /* Set the mDNS timer.  */
5475     _nx_mdns_timer_set(mdns_ptr, txt_rr, txt_rr -> nx_mdns_rr_timer_count);
5476 
5477     if (insert_rr)
5478         *insert_rr = txt_rr;
5479 
5480     /* Release the mDNS mutex.  */
5481     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5482 
5483     /* Return a successful status.  */
5484     return(NX_SUCCESS);
5485 }
5486 
5487 
5488 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
5489 /**************************************************************************/
5490 /*                                                                        */
5491 /*  FUNCTION                                               RELEASE        */
5492 /*                                                                        */
5493 /*    _nx_mdns_rr_nsec_add                                  PORTABLE C    */
5494 /*                                                           6.1          */
5495 /*  AUTHOR                                                                */
5496 /*                                                                        */
5497 /*    Yuxin Zhou, Microsoft Corporation                                   */
5498 /*                                                                        */
5499 /*  DESCRIPTION                                                           */
5500 /*                                                                        */
5501 /*    This function adds the mDNS A resource record into local cache.     */
5502 /*                                                                        */
5503 /*  INPUT                                                                 */
5504 /*                                                                        */
5505 /*    mdns_ptr                              Pointer to mDNS instance      */
5506 /*    name                                  The resource record name      */
5507 /*    add_a                                 Flag for adding A record      */
5508 /*    add_aaaa                              Flag for adding AAAA record   */
5509 /*    type                                  Type for host or service      */
5510 /*                                                                        */
5511 /*  OUTPUT                                                                */
5512 /*                                                                        */
5513 /*    status                                Completion status             */
5514 /*                                                                        */
5515 /*  CALLS                                                                 */
5516 /*                                                                        */
5517 /*    tx_mutex_get                          Get the mDNS mutex            */
5518 /*    tx_mutex_put                          Put the mDNS mutex            */
5519 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5520 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5521 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5522 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5523 /*                                            into cache                  */
5524 /*                                                                        */
5525 /*  CALLED BY                                                             */
5526 /*                                                                        */
5527 /*    _nx_mdns_host_name_register           Register the host name        */
5528 /*                                                                        */
5529 /*  RELEASE HISTORY                                                       */
5530 /*                                                                        */
5531 /*    DATE              NAME                      DESCRIPTION             */
5532 /*                                                                        */
5533 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5534 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5535 /*                                            resulting in version 6.1    */
5536 /*                                                                        */
5537 /**************************************************************************/
_nx_mdns_rr_nsec_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR add_a,UCHAR add_aaaa,UCHAR type,UINT interface_index)5538 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index)
5539 {
5540 UINT        status;
5541 NX_MDNS_RR *insert_rr;
5542 UCHAR       bitmap_length = 0;
5543 ULONG       rdata_length = 0;
5544 NX_MDNS_RR  temp_resource_record;
5545 UINT        name_length;
5546 
5547 
5548     /* Check string length.  */
5549     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5550     {
5551         return (NX_MDNS_DATA_SIZE_ERROR);
5552     }
5553 
5554     /* Add the next domain name, include the first'.' and last '\0'.  */
5555     rdata_length = name_length + 2;
5556 
5557     /* Add the window block and bitmap length.  */
5558     rdata_length += 2;
5559 
5560     /* Add the NSEC with A/AAAA Bitmap.  */
5561     if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5562     {
5563         /* Set the Bitmaps length.  */
5564         if (add_aaaa == NX_TRUE)
5565             bitmap_length = 4;
5566         else
5567             bitmap_length = 1;
5568     }
5569     else
5570     {
5571 
5572         /* Add the NSEC with SRV/TXT Bitmap.   */
5573         bitmap_length = 5;
5574     }
5575 
5576     /* Add the Bitmaps.  */
5577     rdata_length += bitmap_length;
5578 
5579     /* Set the resource record parameters.  */
5580     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_NSEC, NX_MDNS_RR_TTL_HOST, rdata_length,
5581                                        NX_MDNS_RR_SET_UNIQUE, NX_FALSE, NX_TRUE, &temp_resource_record, interface_index);
5582 
5583     /* Check for error.  */
5584     if (status)
5585     {
5586         return(status);
5587     }
5588 
5589     /* Add the next domain name.  */
5590     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5591                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain),
5592                                        NX_FALSE, NX_TRUE);
5593 
5594     /* Check for error.  */
5595     if (status)
5596     {
5597         /* Delete the same strings. */
5598         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5599 
5600         return(status);
5601     }
5602 
5603     /* Set the window block and bitmap length.  */
5604     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block = 0;
5605     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length = bitmap_length;
5606 
5607     /* Add the Bitmap for host.  */
5608     if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5609     {
5610 
5611         /* Encode the Bitmap.  */
5612         if ((add_a == NX_TRUE) && (add_aaaa == NX_TRUE))
5613         {
5614 
5615             /* Add the A Bitmap.  */
5616             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5617 
5618             /* Add the AAAA Bitmap.  */
5619             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5620         }
5621         else if ((add_a == NX_TRUE))
5622         {
5623 
5624             /* Add the A Bit map.  */
5625             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5626         }
5627         else
5628         {
5629 
5630             /* Add the AAAA Bitmap.  */
5631             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5632         }
5633     }
5634     else
5635     {
5636         /* Add the TXT Bitmap for service.  */
5637         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[2] =  128;
5638 
5639         /* Add the SRV Bitmap for service.  */
5640         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[4] =  64;
5641 
5642     }
5643 
5644     /* Add the resource record.  */
5645     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5646 
5647     /* Check for error.  */
5648     if (status)
5649     {
5650         /* Delete the same strings. */
5651         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5652 
5653         /* Delete the same strings. */
5654         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain, 0);
5655 
5656         return(status);
5657     }
5658 
5659     /* Return a successful status.  */
5660     return(NX_SUCCESS);
5661 }
5662 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
5663 
5664 
5665 /**************************************************************************/
5666 /*                                                                        */
5667 /*  FUNCTION                                               RELEASE        */
5668 /*                                                                        */
5669 /*    _nx_mdns_rr_parameter_set                           PORTABLE C      */
5670 /*                                                           6.1.11       */
5671 /*  AUTHOR                                                                */
5672 /*                                                                        */
5673 /*    Yuxin Zhou, Microsoft Corporation                                   */
5674 /*                                                                        */
5675 /*  DESCRIPTION                                                           */
5676 /*                                                                        */
5677 /*    This function sets the parameters of resource record.               */
5678 /*                                                                        */
5679 /*  INPUT                                                                 */
5680 /*                                                                        */
5681 /*    mdns_ptr                              Pointer to mDNS instance      */
5682 /*    name                                  The resource record name      */
5683 /*    type                                  The resource record type      */
5684 /*    ttl                                   The resource record ttl       */
5685 /*    rdata_lenth                           The resource record length    */
5686 /*    set                                   The resource record set       */
5687 /*    is_register                           Register flag                 */
5688 /*    is_valid                              Valid flag                    */
5689 /*    rr_record                             Pointer to resource record    */
5690 /*                                                                        */
5691 /*  OUTPUT                                                                */
5692 /*                                                                        */
5693 /*    status                                Completion status             */
5694 /*                                                                        */
5695 /*  CALLS                                                                 */
5696 /*                                                                        */
5697 /*    None                                                                */
5698 /*                                                                        */
5699 /*  CALLED BY                                                             */
5700 /*                                                                        */
5701 /*    Application Code                                                    */
5702 /*                                                                        */
5703 /*  RELEASE HISTORY                                                       */
5704 /*                                                                        */
5705 /*    DATE              NAME                      DESCRIPTION             */
5706 /*                                                                        */
5707 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5708 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5709 /*                                            resulting in version 6.1    */
5710 /*  04-25-2022     Yuxin Zhou               Modified comment(s),          */
5711 /*                                            fixed the issue of timer,   */
5712 /*                                            resulting in version 6.1.11 */
5713 /*                                                                        */
5714 /**************************************************************************/
_nx_mdns_rr_parameter_set(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,ULONG ttl,UINT rdata_length,UCHAR set,UCHAR is_register,UCHAR is_valid,NX_MDNS_RR * rr_record,UINT interface_index)5715 static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length,
5716                                       UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index)
5717 {
5718 
5719 UINT        status;
5720 UINT        name_length;
5721 
5722 
5723     /* Check string length.  */
5724     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5725     {
5726         return (NX_MDNS_DATA_SIZE_ERROR);
5727     }
5728 
5729     /* Initialize the struct.  */
5730     memset(rr_record, 0, sizeof(NX_MDNS_RR));
5731 
5732     /* Add the name.  */
5733     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5734                                        (VOID **)(&rr_record -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
5735 
5736     /* Check for error.  */
5737     if (status)
5738         return(status);
5739 
5740     /* Set the parameters.  */
5741     rr_record -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
5742     rr_record -> nx_mdns_rr_type = type;
5743     rr_record -> nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
5744     rr_record -> nx_mdns_rr_ttl = ttl;
5745     rr_record -> nx_mdns_rr_rdata_length = (USHORT)rdata_length;
5746 
5747     /* Set the resource record as uniqure.  */
5748     if (set == NX_MDNS_RR_SET_UNIQUE)
5749         rr_record -> nx_mdns_rr_word = (rr_record -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_UNIQUE);
5750 
5751     /* Check for mDNS started flag.  */
5752     if (mdns_ptr -> nx_mdns_started)
5753     {
5754 
5755         /* Check the valid flag for PTR resource record.  */
5756         if (is_valid == NX_TRUE)
5757         {
5758             /* Set the resource record state.  */
5759             rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
5760         }
5761         else
5762         {
5763 
5764             /* The is_register value be used for A/AAAA type, the value being NX_TRUE indicates the operation is to register the host name(probing and announcing the A/AAAA). The value being NX_FALSE indicates the operation is an address change, (announcing the A/AAAA).  */
5765             if ((set == NX_MDNS_RR_SET_UNIQUE) && (is_register == NX_TRUE))
5766             {
5767 
5768                 /* Set the resource record status.  */
5769                 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
5770                 rr_record -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
5771                 rr_record -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
5772             }
5773             else
5774             {
5775 
5776                 /* Set the resource record state.  */
5777                 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
5778                 rr_record -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
5779                 rr_record -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
5780 
5781                 /* Check the announcing max time.  */
5782                 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
5783                     rr_record -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
5784                 else
5785                     rr_record -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
5786 
5787                 /* Set the retransmit count.  */
5788                 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
5789                     rr_record -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
5790                 else
5791                     rr_record -> nx_mdns_rr_retransmit_count = 1;
5792             }
5793         }
5794     }
5795     else
5796     {
5797 
5798         /* Set the resource record status.  */
5799         rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
5800     }
5801 
5802     return(NX_MDNS_SUCCESS);
5803 }
5804 #endif /* NX_MDNS_DISABLE_SERVER */
5805 
5806 
5807 /**************************************************************************/
5808 /*                                                                        */
5809 /*  FUNCTION                                               RELEASE        */
5810 /*                                                                        */
5811 /*    _nx_mdns_rr_delete                                  PORTABLE C      */
5812 /*                                                           6.1          */
5813 /*  AUTHOR                                                                */
5814 /*                                                                        */
5815 /*    Yuxin Zhou, Microsoft Corporation                                   */
5816 /*                                                                        */
5817 /*  DESCRIPTION                                                           */
5818 /*                                                                        */
5819 /*    This function deletes the mDNS resource record from the             */
5820 /*    local bufferor remote buffer according to the resource record set.  */
5821 /*                                                                        */
5822 /*  INPUT                                                                 */
5823 /*                                                                        */
5824 /*    mdns_ptr                              Pointer to mDNS instance      */
5825 /*    record_rr                             The resource record           */
5826 /*                                                                        */
5827 /*  OUTPUT                                                                */
5828 /*                                                                        */
5829 /*    status                                Completion status             */
5830 /*                                                                        */
5831 /*  CALLS                                                                 */
5832 /*                                                                        */
5833 /*    tx_mutex_get                          Get the mDNS mutex            */
5834 /*    tx_mutex_put                          Put the mDNS mutex            */
5835 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5836 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
5837 /*                                            from cache                  */
5838 /*                                                                        */
5839 /*  CALLED BY                                                             */
5840 /*                                                                        */
5841 /*    Application Code                                                    */
5842 /*                                                                        */
5843 /*  RELEASE HISTORY                                                       */
5844 /*                                                                        */
5845 /*    DATE              NAME                      DESCRIPTION             */
5846 /*                                                                        */
5847 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5848 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5849 /*                                            resulting in version 6.1    */
5850 /*                                                                        */
5851 /**************************************************************************/
_nx_mdns_rr_delete(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)5852 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
5853 {
5854 
5855 UINT        status = NX_MDNS_SUCCESS;
5856 
5857 #ifndef NX_MDNS_DISABLE_CLIENT
5858 ULONG       *head;
5859 NX_MDNS_RR  *p;
5860 #endif /* NX_MDNS_DISABLE_CLIENT */
5861 
5862     /* Get the mDNS mutex.  */
5863     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5864 
5865 
5866     /* Check for mDNS started flag.  */
5867     if (mdns_ptr -> nx_mdns_started)
5868     {
5869 
5870         /* Check the RR owner.  */
5871         if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5872         {
5873 
5874 #ifndef NX_MDNS_DISABLE_SERVER
5875             if ((record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
5876                 (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
5877             {
5878 
5879                 /* Set the state to send Goodbye packet.  */
5880                 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
5881 
5882                 /* Set the retransmit count.  */
5883                 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
5884 
5885                 /* Set the timer count.  */
5886                 record_rr -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
5887 
5888                 /* Set the delete flag.  */
5889                 record_rr -> nx_mdns_rr_word = (record_rr -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
5890 
5891                 /* Set the mDNS timer.  */
5892                 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
5893             }
5894             else
5895             {
5896 
5897                 /* Delete the resource records.  */
5898                 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5899             }
5900 
5901 #endif /* NX_MDNS_DISABLE_SERVER */
5902         }
5903         else
5904         {
5905 
5906 #ifndef NX_MDNS_DISABLE_CLIENT
5907             if (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
5908             {
5909 
5910                 /* Set the pointer.  */
5911                 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
5912 
5913                 if(head)
5914                 {
5915                     head = (ULONG*)(*head);
5916 
5917                     /* Check the remote resource record, stop the updating resource record.  */
5918                     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
5919                     {
5920 
5921                         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
5922                             continue;
5923 
5924                         if (p == record_rr)
5925                             continue;
5926 
5927                         if ((p -> nx_mdns_rr_name  == record_rr -> nx_mdns_rr_name) &&
5928                             (p -> nx_mdns_rr_type == record_rr -> nx_mdns_rr_type) &&
5929                             (p -> nx_mdns_rr_class == record_rr -> nx_mdns_rr_class))
5930                         {
5931 
5932                             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)
5933                             {
5934 
5935                                 /* Clear the Updating flag.  */
5936                                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_UPDATING));
5937                             }
5938 
5939                             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
5940                             {
5941                                 if (p -> nx_mdns_rr_retransmit_count)
5942                                 {
5943 
5944                                     /* mDNS querier need not update the RR, The original updating ttl is at 80%, 85%, 90%, 95%. Update the timer.*/
5945                                     /* timer_count: P, timer_count: C, rr_ttl: T.
5946                                     P = P + C * T * 5%.  */
5947                                     p -> nx_mdns_rr_timer_count = (p -> nx_mdns_rr_timer_count + p -> nx_mdns_rr_retransmit_count * p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 /100);
5948 
5949                                     /* Clear the retransmit count.  */
5950                                     p -> nx_mdns_rr_retransmit_count = 0;
5951 
5952                                     /* Set the mDNS timer.  */
5953                                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
5954                                 }
5955                             }
5956                         }
5957                     }
5958                 }
5959             }
5960 
5961             /* Delete the resource record.  */
5962             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5963 
5964 #endif /* NX_MDNS_DISABLE_CLIENT */
5965         }
5966     }
5967     else
5968     {
5969         /* Check the RR owner.  */
5970         if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5971         {
5972 
5973 #ifndef NX_MDNS_DISABLE_SERVER
5974             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5975 #endif /* NX_MDNS_DISABLE_SERVER  */
5976         }
5977         else
5978         {
5979 
5980 #ifndef NX_MDNS_DISABLE_CLIENT
5981             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5982 #endif /* NX_MDNS_DISABLE_CLIENT  */
5983         }
5984     }
5985 
5986     /* Release the mDNS mutex.  */
5987     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5988 
5989     /* Return status.  */
5990     return (status);
5991 }
5992 
5993 
5994 #ifndef NX_MDNS_DISABLE_SERVER
5995 /**************************************************************************/
5996 /*                                                                        */
5997 /*  FUNCTION                                               RELEASE        */
5998 /*                                                                        */
5999 /*    _nx_mdns_local_cache_clear                            PORTABLE C    */
6000 /*                                                           6.1          */
6001 /*  AUTHOR                                                                */
6002 /*                                                                        */
6003 /*    Yuxin Zhou, Microsoft Corporation                                   */
6004 /*                                                                        */
6005 /*  DESCRIPTION                                                           */
6006 /*                                                                        */
6007 /*    This function deletes the mDNS instance.                            */
6008 /*                                                                        */
6009 /*  INPUT                                                                 */
6010 /*                                                                        */
6011 /*    mdns_ptr                              Pointer to mDNS instance      */
6012 /*                                                                        */
6013 /*  OUTPUT                                                                */
6014 /*                                                                        */
6015 /*    status                                Completion status             */
6016 /*                                                                        */
6017 /*  CALLS                                                                 */
6018 /*                                                                        */
6019 /*    _nx_mdns_local_cache_clear            Actual local cache clear      */
6020 /*                                            function                    */
6021 /*                                                                        */
6022 /*  CALLED BY                                                             */
6023 /*                                                                        */
6024 /*    Application Code                                                    */
6025 /*                                                                        */
6026 /*  RELEASE HISTORY                                                       */
6027 /*                                                                        */
6028 /*    DATE              NAME                      DESCRIPTION             */
6029 /*                                                                        */
6030 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6031 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6032 /*                                            resulting in version 6.1    */
6033 /*                                                                        */
6034 /**************************************************************************/
_nxe_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6035 UINT _nxe_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6036 {
6037 
6038 UINT    status;
6039 
6040 
6041     /* Check for invalid input pointers.  */
6042     if (!mdns_ptr)
6043     {
6044         return(NX_PTR_ERROR);
6045     }
6046 
6047     /* Check for invalid server attributes. */
6048     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
6049     {
6050         return(NX_MDNS_PARAM_ERROR);
6051     }
6052 
6053     /* Call actual mDNS local cache clear service.  */
6054     status =  _nx_mdns_local_cache_clear(mdns_ptr);
6055 
6056     /* Return status.  */
6057     return(status);
6058 }
6059 
6060 
6061 /**************************************************************************/
6062 /*                                                                        */
6063 /*  FUNCTION                                               RELEASE        */
6064 /*                                                                        */
6065 /*    _nx_mdns_local_cache_clear                          PORTABLE C      */
6066 /*                                                           6.1          */
6067 /*  AUTHOR                                                                */
6068 /*                                                                        */
6069 /*    Yuxin Zhou, Microsoft Corporation                                   */
6070 /*                                                                        */
6071 /*  DESCRIPTION                                                           */
6072 /*                                                                        */
6073 /*    This function clears the mDNS local cache.                          */
6074 /*                                                                        */
6075 /*  INPUT                                                                 */
6076 /*                                                                        */
6077 /*    mdns_ptr                              Pointer to mDNS instance      */
6078 /*                                                                        */
6079 /*  OUTPUT                                                                */
6080 /*                                                                        */
6081 /*    status                                Completion status             */
6082 /*                                                                        */
6083 /*  CALLS                                                                 */
6084 /*                                                                        */
6085 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
6086 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
6087 /*                                            from cache                  */
6088 /*                                                                        */
6089 /*  CALLED BY                                                             */
6090 /*                                                                        */
6091 /*    Application Code                                                    */
6092 /*                                                                        */
6093 /*  RELEASE HISTORY                                                       */
6094 /*                                                                        */
6095 /*    DATE              NAME                      DESCRIPTION             */
6096 /*                                                                        */
6097 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6098 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6099 /*                                            resulting in version 6.1    */
6100 /*                                                                        */
6101 /**************************************************************************/
_nx_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6102 UINT _nx_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6103 {
6104 
6105 UINT            status = NX_MDNS_SUCCESS;
6106 ULONG           *head;
6107 NX_MDNS_RR      *p;
6108 
6109 
6110     /* Get the mDNS mutex.  */
6111     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
6112 
6113     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6114     head = (ULONG*)(*head);
6115 
6116     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
6117     {
6118 
6119         /* Delete the resource records.  */
6120         status = _nx_mdns_rr_delete(mdns_ptr, p);
6121 
6122         /* Check the status.  */
6123         if (status)
6124             break;
6125     }
6126 
6127     /* Release the mDNS mutex.  */
6128     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
6129 
6130     /* Return a successful status.  */
6131     return(status);
6132 }
6133 #endif /* NX_MDNS_DISABLE_SERVER  */
6134 
6135 
6136 /**************************************************************************/
6137 /*                                                                        */
6138 /*  FUNCTION                                               RELEASE        */
6139 /*                                                                        */
6140 /*    _nx_mdns_service_name_resolve                       PORTABLE C      */
6141 /*                                                           6.1          */
6142 /*  AUTHOR                                                                */
6143 /*                                                                        */
6144 /*    Yuxin Zhou, Microsoft Corporation                                   */
6145 /*                                                                        */
6146 /*  DESCRIPTION                                                           */
6147 /*                                                                        */
6148 /*    This function resloves the service name, type, domain.              */
6149 /*                                                                        */
6150 /*  INPUT                                                                 */
6151 /*                                                                        */
6152 /*    srv_name                              Pointer to SRV name           */
6153 /*    name                                  The name of the service       */
6154 /*    type                                  The type of to the service    */
6155 /*    domain                                The domain                    */
6156 /*                                                                        */
6157 /*  OUTPUT                                                                */
6158 /*                                                                        */
6159 /*    status                                Completion status             */
6160 /*                                                                        */
6161 /*  CALLS                                                                 */
6162 /*                                                                        */
6163 /*    tx_mutex_get                          Get the mDNS mutex            */
6164 /*    tx_mutex_put                          Put the mDNS mutex            */
6165 /*                                                                        */
6166 /*  CALLED BY                                                             */
6167 /*                                                                        */
6168 /*    mDNS component                                                      */
6169 /*                                                                        */
6170 /*  RELEASE HISTORY                                                       */
6171 /*                                                                        */
6172 /*    DATE              NAME                      DESCRIPTION             */
6173 /*                                                                        */
6174 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6175 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6176 /*                                            resulting in version 6.1    */
6177 /*                                                                        */
6178 /**************************************************************************/
_nx_mdns_service_name_resolve(UCHAR * srv_name,UCHAR ** name,UCHAR ** type,UCHAR ** domain)6179 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain)
6180 {
6181 
6182 UINT    i;
6183 UINT    count;
6184 UINT    prepend_index;
6185 UINT    append_index;
6186 UINT    type_index;
6187 UINT    domain_index;
6188 UCHAR   *pointer;
6189 UINT     protocol_length;
6190 
6191 
6192     /* Initialize the parameters.  */
6193     count = 0;
6194     prepend_index = 0;
6195     append_index = 0;
6196     type_index = 0;
6197     domain_index = 0;
6198 
6199     /* Set the service name pointer.  */
6200     pointer = srv_name;
6201 
6202     /* Service Instance name,  */
6203     /* <Instance>.<sn>._tcp.<domain> :
6204        name: <Instance>
6205        type: <sn>._tcp
6206        domain: <domain>.  */
6207     while (*srv_name != '\0')
6208     {
6209 
6210         /* Update the index.  */
6211         append_index ++;
6212 
6213         if (*srv_name == '.')
6214         {
6215 
6216             /* Set the value.  */
6217             i = 0;
6218 
6219             while (nx_mdns_app_protocol[i])
6220             {
6221 
6222                 /* Check string length.  */
6223                 if (_nx_utility_string_length_check(nx_mdns_app_protocol[i], &protocol_length, NX_MDNS_TYPE_MAX))
6224                 {
6225                     continue;
6226                 }
6227 
6228                 /* Find the key string. "_tcp" , "_udp" etc.  */
6229                 if (!_nx_mdns_name_match(pointer + prepend_index, (UCHAR *)(nx_mdns_app_protocol[i]), protocol_length))
6230                 {
6231 
6232                     /* Get the <domain> pointer.  */
6233                     /* EL-PC.Test._http._tcp.local
6234                        type index pointer to the _http._tcp,
6235                        domain_index pointer to the local.  */
6236                     domain_index = append_index;
6237 
6238                     /* Set the name pointer.  */
6239                     if (type_index)
6240                     {
6241                         *name = pointer;
6242 
6243                         /* Set the trailing null of name.  */
6244                         *(pointer + type_index -1) = '\0';
6245                     }
6246                     else
6247                     {
6248                         *name = NX_NULL;
6249                     }
6250 
6251                     /* Set the type pointer.  */
6252                     *type = pointer + type_index;
6253 
6254                     /* Set the trailing null of type.  */
6255                     *(pointer + domain_index -1) = '\0';
6256 
6257                     /* Set the type pointer.  */
6258                     *domain = pointer + domain_index;
6259 
6260                     return(NX_MDNS_SUCCESS);
6261                 }
6262                 i ++;
6263             }
6264 
6265             /* Update the '.' count.  */
6266             count ++;
6267 
6268             /* The type index is pointer to the <sn>.  */
6269             if (count != 1)
6270             {
6271 
6272                 /* Update the type index.  */
6273                 type_index = prepend_index;
6274             }
6275 
6276             prepend_index = append_index;
6277         }
6278 
6279         srv_name ++;
6280     }
6281 
6282     return(NX_MDNS_ERROR);
6283 }
6284 
6285 
6286 /**************************************************************************/
6287 /*                                                                        */
6288 /*  FUNCTION                                               RELEASE        */
6289 /*                                                                        */
6290 /*    _nx_mdns_service_name_assemble                      PORTABLE C      */
6291 /*                                                           6.1          */
6292 /*  AUTHOR                                                                */
6293 /*                                                                        */
6294 /*    Yuxin Zhou, Microsoft Corporation                                   */
6295 /*                                                                        */
6296 /*  DESCRIPTION                                                           */
6297 /*                                                                        */
6298 /*    This function resloves the service name, type, domain.              */
6299 /*                                                                        */
6300 /*  INPUT                                                                 */
6301 /*                                                                        */
6302 /*    srv_name                              Pointer to SRV name           */
6303 /*    name                                  The name of the service       */
6304 /*    type                                  The type of to the service    */
6305 /*    domain                                The domain                    */
6306 /*                                                                        */
6307 /*  OUTPUT                                                                */
6308 /*                                                                        */
6309 /*    status                                Completion status             */
6310 /*                                                                        */
6311 /*  CALLS                                                                 */
6312 /*                                                                        */
6313 /*    tx_mutex_get                          Get the mDNS mutex            */
6314 /*    tx_mutex_put                          Put the mDNS mutex            */
6315 /*                                                                        */
6316 /*  CALLED BY                                                             */
6317 /*                                                                        */
6318 /*    mDNS component                                                      */
6319 /*                                                                        */
6320 /*  RELEASE HISTORY                                                       */
6321 /*                                                                        */
6322 /*    DATE              NAME                      DESCRIPTION             */
6323 /*                                                                        */
6324 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6325 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
6326 /*                                            buffer length verification, */
6327 /*                                            verified memcpy use cases,  */
6328 /*                                            resulting in version 6.1    */
6329 /*                                                                        */
6330 /**************************************************************************/
_nx_mdns_service_name_assemble(UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * domain,UCHAR * record_buffer,UINT buffer_size,UINT * type_index)6331 static UINT _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index)
6332 {
6333 
6334 UINT        index;
6335 UINT        length;
6336 
6337     /* Initialize the struct.  */
6338     index = 0;
6339     memset(record_buffer, 0, buffer_size);
6340     if (type_index)
6341     {
6342         *type_index = 0;
6343     }
6344 
6345     /* Construct the service name.  */
6346 
6347     /* Add the name.  */
6348     if (name)
6349     {
6350 
6351         /* Check string length.  */
6352         if (_nx_utility_string_length_check((CHAR *)name, &length, NX_MDNS_NAME_MAX))
6353         {
6354             return (NX_MDNS_DATA_SIZE_ERROR);
6355         }
6356 
6357         /* Verify buffer length. */
6358         if (index + length + 1 > buffer_size)
6359         {
6360             return (NX_MDNS_DATA_SIZE_ERROR);
6361         }
6362 
6363         memcpy((CHAR *)(record_buffer + index), (const char*)name, length); /* Use case of memcpy is verified. */
6364         index += length;
6365 
6366         *(record_buffer + index) = '.';
6367         index ++;
6368     }
6369 
6370     /* Add the sub type.  */
6371     if (sub_type)
6372     {
6373 
6374         /* Check string length.  */
6375         if (_nx_utility_string_length_check((CHAR *)sub_type, &length, NX_MDNS_LABEL_MAX))
6376         {
6377             return (NX_MDNS_DATA_SIZE_ERROR);
6378         }
6379 
6380         /* Verify buffer length. */
6381         if (index + length + 1 + 4 + 1 > buffer_size)
6382         {
6383             return (NX_MDNS_DATA_SIZE_ERROR);
6384         }
6385 
6386         if (type_index)
6387         {
6388             *type_index = index;
6389         }
6390         memcpy((CHAR *)(record_buffer + index), (const char*)sub_type, length); /* Use case of memcpy is verified. */
6391         index += length;
6392         *(record_buffer + index) = '.';
6393         index ++;
6394 
6395         /* Add the key word "_sub".  */
6396         memcpy((CHAR *)(record_buffer + index), (const char*)"_sub", 4); /* Use case of memcpy is verified. */
6397         index += 4;
6398         *(record_buffer + index) = '.';
6399         index ++;
6400     }
6401 
6402     /* Add the type.  */
6403     if (type)
6404     {
6405 
6406         /* Check string length.  */
6407         if (_nx_utility_string_length_check((CHAR *)type, &length, NX_MDNS_TYPE_MAX))
6408         {
6409             return (NX_MDNS_DATA_SIZE_ERROR);
6410         }
6411 
6412         /* Verify buffer length. */
6413         if (index + length + 1 > buffer_size)
6414         {
6415             return (NX_MDNS_DATA_SIZE_ERROR);
6416         }
6417 
6418         /* Set the type index.  */
6419         if ((type_index) &&
6420             (!sub_type))
6421         {
6422             *type_index = index;
6423         }
6424 
6425         memcpy((CHAR *)record_buffer + index, (const char*)type, length); /* Use case of memcpy is verified. */
6426         index += length;
6427         *(record_buffer + index) = '.';
6428         index ++;
6429     }
6430 
6431     /* Add the domain. */
6432     if (domain)
6433     {
6434 
6435         /* Check string length.  */
6436         if (_nx_utility_string_length_check((CHAR *)domain, &length, NX_MDNS_DOMAIN_NAME_MAX))
6437         {
6438             return (NX_MDNS_DATA_SIZE_ERROR);
6439         }
6440 
6441         /* Verify buffer length. */
6442         if (index + length > buffer_size)
6443         {
6444             return (NX_MDNS_DATA_SIZE_ERROR);
6445         }
6446 
6447         memcpy((CHAR *)(record_buffer + index), (const char*)domain, length); /* Use case of memcpy is verified. */
6448         index += length;
6449     }
6450 
6451     return(NX_MDNS_SUCCESS);
6452 }
6453 
6454 
6455 #ifndef NX_MDNS_DISABLE_SERVER
6456 /**************************************************************************/
6457 /*                                                                        */
6458 /*  FUNCTION                                               RELEASE        */
6459 /*                                                                        */
6460 /*    nx_mdns_host_name_register                          PORTABLE C      */
6461 /*                                                           6.1          */
6462 /*  AUTHOR                                                                */
6463 /*                                                                        */
6464 /*    Yuxin Zhou, Microsoft Corporation                                   */
6465 /*                                                                        */
6466 /*  DESCRIPTION                                                           */
6467 /*                                                                        */
6468 /*    This function resloves the service name, type, domain.              */
6469 /*                                                                        */
6470 /*  INPUT                                                                 */
6471 /*                                                                        */
6472 /*    mdns_ptr                              Pointer to mDNS instance      */
6473 /*    type                                  The type of operation         */
6474 /*    interface_index                       The interface index           */
6475 /*                                                                        */
6476 /*  OUTPUT                                                                */
6477 /*                                                                        */
6478 /*    status                                Completion status             */
6479 /*                                                                        */
6480 /*  CALLS                                                                 */
6481 /*                                                                        */
6482 /*    tx_mutex_get                          Get the mDNS mutex            */
6483 /*    tx_mutex_put                          Put the mDNS mutex            */
6484 /*    _nx_mdns_rr_a_aaaa_add                Add the A/AAAA resource record*/
6485 /*                                                                        */
6486 /*  CALLED BY                                                             */
6487 /*                                                                        */
6488 /*    _nx_mdns_enable                       Enable mDNS                   */
6489 /*    _nx_mdns_address_change_process       Process address change        */
6490 /*                                                                        */
6491 /*  RELEASE HISTORY                                                       */
6492 /*                                                                        */
6493 /*    DATE              NAME                      DESCRIPTION             */
6494 /*                                                                        */
6495 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6496 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
6497 /*                                            verified memcpy use cases,  */
6498 /*                                            resulting in version 6.1    */
6499 /*                                                                        */
6500 /**************************************************************************/
_nx_mdns_host_name_register(NX_MDNS * mdns_ptr,UCHAR type,UINT interface_index)6501 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index)
6502 {
6503 
6504 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
6505 UINT    status;
6506 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
6507 NX_IP   *ip_ptr;
6508 UINT    index = 0;
6509 UCHAR   add_a = NX_FALSE;
6510 UCHAR   add_aaaa = NX_FALSE;
6511 UINT    host_name_length;
6512 
6513 #ifdef NX_MDNS_ENABLE_IPV6
6514 NXD_IPV6_ADDRESS *ipv6_address_ptr;
6515 #endif /* NX_MDNS_ENABLE_IPV6  */
6516 
6517 
6518 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
6519     NX_PARAMETER_NOT_USED(type);
6520 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6  */
6521 
6522     /* Check string length.  */
6523     if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_host_name, &host_name_length, NX_MDNS_HOST_NAME_MAX))
6524     {
6525         return (NX_MDNS_DATA_SIZE_ERROR);
6526     }
6527 
6528     /* Construct the A/AAAA name.  */
6529     memcpy((CHAR *)(&temp_string_buffer[index]), (const char*)mdns_ptr -> nx_mdns_host_name, host_name_length); /* Use case of memcpy is verified. */
6530     index += host_name_length;
6531 
6532     temp_string_buffer[index] = '.';
6533     index ++;
6534     memcpy((CHAR *)(&temp_string_buffer[index]), (CHAR *)"local", sizeof("local")); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h.*/
6535 
6536     /* Set the ip pointer.  */
6537     ip_ptr = mdns_ptr -> nx_mdns_ip_ptr;
6538 
6539     /* Get the IP mutex.  */
6540     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
6541 
6542 #ifndef NX_DISABLE_IPV4
6543     /* Add the A resource records message.  */
6544     if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
6545     {
6546 
6547         /* Add the A resource records message.  */
6548         status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], &(ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address),
6549                                         NX_MDNS_IPV4_ADDRESS_LENGTH, type, interface_index);
6550 
6551         /* Check the status.  */
6552         if (status)
6553         {
6554 
6555             /* Release the IP mutex.  */
6556             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6557 
6558             return(status);
6559         }
6560 
6561         /* Set the flag.  */
6562         add_a = NX_TRUE;
6563     }
6564 #endif /* NX_DISABLE_IPV4  */
6565 
6566 #ifdef NX_MDNS_ENABLE_IPV6
6567     /* Get the IPv6 address pointer.*/
6568     ipv6_address_ptr = ip_ptr -> nx_ip_interface[interface_index].nxd_interface_ipv6_address_list_head;
6569 
6570     while(ipv6_address_ptr)
6571     {
6572 
6573         if (ipv6_address_ptr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)
6574         {
6575 
6576             /* Add the AAAA resource records message.  */
6577             status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], (ULONG *)(&ipv6_address_ptr -> nxd_ipv6_address[0]),
6578                                             NX_MDNS_IPV6_ADDRESS_LENGTH, type, interface_index);
6579 
6580             /* Check the status.  */
6581             if (status)
6582             {
6583 
6584                 /* Release the IP mutex.  */
6585                 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6586 
6587                 return(status);
6588             }
6589 
6590             /* Set the flag.  */
6591             add_aaaa = NX_TRUE;
6592         }
6593 
6594         /* Update the pointer.  */
6595         ipv6_address_ptr = ipv6_address_ptr -> nxd_ipv6_address_next;
6596     }
6597 #endif /* NX_MDNS_ENABLE_IPV6  */
6598 
6599 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
6600 
6601     /* Add the NSEC resource record.  */
6602     if ((add_a == NX_TRUE) || (add_aaaa == NX_TRUE))
6603         _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], add_a, add_aaaa, NX_MDNS_ADD_NSEC_FOR_HOST, interface_index);
6604 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
6605 
6606     /* Release the IP mutex.  */
6607     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6608 
6609     /* Return a successful status.  */
6610     return(NX_SUCCESS);
6611 }
6612 #endif /* NX_MDNS_DISABLE_SERVER */
6613 
6614 
6615 /**************************************************************************/
6616 /*                                                                        */
6617 /*  FUNCTION                                               RELEASE        */
6618 /*                                                                        */
6619 /*    _nx_mdns_timer_entry                                PORTABLE C      */
6620 /*                                                           6.1          */
6621 /*  AUTHOR                                                                */
6622 /*                                                                        */
6623 /*    Yuxin Zhou, Microsoft Corporation                                   */
6624 /*                                                                        */
6625 /*  DESCRIPTION                                                           */
6626 /*                                                                        */
6627 /*    This function handles waking up the mDNS helper thread to process   */
6628 /*    the timer event on a periodic basis.                                */
6629 /*                                                                        */
6630 /*  INPUT                                                                 */
6631 /*                                                                        */
6632 /*    mdns_value                            mDNS instance for a ulong     */
6633 /*                                                                        */
6634 /*  OUTPUT                                                                */
6635 /*                                                                        */
6636 /*    None                                                                */
6637 /*                                                                        */
6638 /*  CALLS                                                                 */
6639 /*                                                                        */
6640 /*    tx_event_flags_set                    Set event flags               */
6641 /*                                                                        */
6642 /*  CALLED BY                                                             */
6643 /*                                                                        */
6644 /*    ThreadX system timer thread                                         */
6645 /*                                                                        */
6646 /*  RELEASE HISTORY                                                       */
6647 /*                                                                        */
6648 /*    DATE              NAME                      DESCRIPTION             */
6649 /*                                                                        */
6650 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6651 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6652 /*                                            resulting in version 6.1    */
6653 /*                                                                        */
6654 /**************************************************************************/
_nx_mdns_timer_entry(ULONG mdns_value)6655 static VOID _nx_mdns_timer_entry(ULONG mdns_value)
6656 {
6657 
6658 NX_MDNS     *mdns_ptr;
6659 
6660 
6661     /* Setup mDNS pointer from the input value.  */
6662     mdns_ptr = (NX_MDNS *) mdns_value;
6663 
6664     /* Set the timer event.  */
6665     tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_TIMER_EVENT, TX_OR);
6666 
6667     return;
6668 }
6669 
6670 
6671 /**************************************************************************/
6672 /*                                                                        */
6673 /*  FUNCTION                                               RELEASE        */
6674 /*                                                                        */
6675 /*    _nx_mdns_timer_set                                  PORTABLE C      */
6676 /*                                                           6.1          */
6677 /*  AUTHOR                                                                */
6678 /*                                                                        */
6679 /*    Yuxin Zhou, Microsoft Corporation                                   */
6680 /*                                                                        */
6681 /*  DESCRIPTION                                                           */
6682 /*                                                                        */
6683 /*    This function process all resource records according to the state,  */
6684 /*    Set the flags to send the probing, announcing, query, response and  */
6685 /*    goodbye mDNS message. Delete the resource record when the resource  */
6686 /*    record is invalid.                                                  */
6687 /*                                                                        */
6688 /*  INPUT                                                                 */
6689 /*                                                                        */
6690 /*    mdns_ptr                              Pointer to mDNS instance      */
6691 /*                                                                        */
6692 /*  OUTPUT                                                                */
6693 /*                                                                        */
6694 /*    status                                Completion status             */
6695 /*                                                                        */
6696 /*  CALLS                                                                 */
6697 /*                                                                        */
6698 /*    tx_timer_info_get                     Get the timer info            */
6699 /*    tx_timer_deactivate                   Deactivate the timer          */
6700 /*    tx_timer_change                       Change the timer              */
6701 /*    tx_timer_activate                     Activate the timer            */
6702 /*                                                                        */
6703 /*  CALLED BY                                                             */
6704 /*                                                                        */
6705 /*    _nx_mdns_enable                       Enable the mDNS               */
6706 /*    _nx_mdns_rr_a_aaaa_add                Add the A/AAAA resource record*/
6707 /*    _nx_mdns_rr_ptr_add                   Add the ptr resource record   */
6708 /*    _nx_mdns_rr_srv_add                   Add the srv resource record   */
6709 /*    _nx_mdns_rr_txt_add                   Add the txt resource record   */
6710 /*    _nx_mdns_rr_delete                    Delete the resource record    */
6711 /*    _nx_mdns_local_cache_clear            Clear the local cache         */
6712 /*    _nx_mdns_query                        Send the continuous query     */
6713 /*    _nx_mdns_packet_process               Process mDNS packet           */
6714 /*    _nx_mdns_conflict_process             Process the conflict          */
6715 /*                                                                        */
6716 /*  RELEASE HISTORY                                                       */
6717 /*                                                                        */
6718 /*    DATE              NAME                      DESCRIPTION             */
6719 /*                                                                        */
6720 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6721 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6722 /*                                            resulting in version 6.1    */
6723 /*                                                                        */
6724 /**************************************************************************/
_nx_mdns_timer_set(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr,ULONG timer_count)6725 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr, ULONG timer_count)
6726 {
6727 
6728 
6729 TX_INTERRUPT_SAVE_AREA
6730 ULONG       remaining_ticks;
6731 ULONG       schedule_count;
6732 UINT        active;
6733 
6734     if (timer_count)
6735     {
6736 
6737         /* Disable interrupt */
6738         TX_DISABLE
6739 
6740         /* Get the remaining_ticks of mDNS timer;*/
6741         tx_timer_info_get(&mdns_ptr -> nx_mdns_timer, TX_NULL, &active, &remaining_ticks, TX_NULL, TX_NULL);
6742 
6743         /* If the timer is not active, the remaining ticks and schedule count are set to 0. */
6744         if(active == NX_FALSE)
6745         {
6746             remaining_ticks = 0;
6747             schedule_count = 0;
6748         }
6749         else
6750         {
6751 
6752             /* Get the reschedule timer count of last timer.  */
6753             schedule_count = mdns_ptr -> nx_mdns_timer_min_count;
6754         }
6755 
6756         /* Check the timer.  if exceed the timer count range, update the timer. */
6757         if((timer_count < remaining_ticks) || active == NX_FALSE)
6758         {
6759 
6760             /* Set the minimum timer count.
6761             The minimum timer count indicate the intervals between last timer event and next timer event. */
6762             mdns_ptr -> nx_mdns_timer_min_count = (schedule_count - remaining_ticks) + timer_count;
6763 
6764             /* Change the timer ticks with minimum timer count.*/
6765             tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
6766             tx_timer_change(&(mdns_ptr -> nx_mdns_timer), timer_count, timer_count );
6767             tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
6768         }
6769 
6770         /* Update the Resource record life timer count*/
6771         record_rr -> nx_mdns_rr_timer_count = (schedule_count - remaining_ticks) + timer_count;
6772 
6773         /* Restore interrupts.  */
6774         TX_RESTORE
6775     }
6776 }
6777 
6778 
6779 /**************************************************************************/
6780 /*                                                                        */
6781 /*  FUNCTION                                               RELEASE        */
6782 /*                                                                        */
6783 /*    _nx_mdns_timer_event_process                        PORTABLE C      */
6784 /*                                                           6.1.11       */
6785 /*  AUTHOR                                                                */
6786 /*                                                                        */
6787 /*    Yuxin Zhou, Microsoft Corporation                                   */
6788 /*                                                                        */
6789 /*  DESCRIPTION                                                           */
6790 /*                                                                        */
6791 /*    This function process all resource records according to the state,  */
6792 /*    Set the flags to send the probing, announcing, query, response and  */
6793 /*    goodbye mDNS message. Delete the resource record when the resource  */
6794 /*    record is invalid.                                                  */
6795 /*                                                                        */
6796 /*  INPUT                                                                 */
6797 /*                                                                        */
6798 /*    mdns_ptr                              Pointer to mDNS instance      */
6799 /*                                                                        */
6800 /*  OUTPUT                                                                */
6801 /*                                                                        */
6802 /*    status                                Completion status             */
6803 /*                                                                        */
6804 /*  CALLS                                                                 */
6805 /*                                                                        */
6806 /*    tx_event_flags_set                    Set event flags to wake mDNS  */
6807 /*    tx_timer_deactivate                   Deactivate the timer          */
6808 /*    tx_timer_change                       Change the timer              */
6809 /*    tx_timer_activate                     Activate the timer            */
6810 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
6811 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
6812 /*                                            from the cache              */
6813 /*                                                                        */
6814 /*  CALLED BY                                                             */
6815 /*                                                                        */
6816 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
6817 /*                                                                        */
6818 /*  RELEASE HISTORY                                                       */
6819 /*                                                                        */
6820 /*    DATE              NAME                      DESCRIPTION             */
6821 /*                                                                        */
6822 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6823 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
6824 /*                                            verified memcpy use cases,  */
6825 /*                                            resulting in version 6.1    */
6826 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
6827 /*                                            corrected the random value, */
6828 /*                                            fixed the issue of timer,   */
6829 /*                                            resulting in version 6.1.11 */
6830 /*                                                                        */
6831 /**************************************************************************/
_nx_mdns_timer_event_process(NX_MDNS * mdns_ptr)6832 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr)
6833 {
6834 
6835 ULONG       event_flags = 0;
6836 ULONG       timer_min_count = 0xFFFFFFFF;
6837 ULONG       *head, *tail;
6838 NX_MDNS_RR  *p;
6839 UCHAR       i;
6840 
6841 #ifndef NX_MDNS_DISABLE_CLIENT
6842 ULONG       remaining_ticks;
6843 #endif /* NX_MDNS_DISABLE_CLIENT  */
6844 
6845 #ifndef NX_MDNS_DISABLE_SERVER
6846 UINT        status;
6847 NX_MDNS_RR  *p1;
6848 UCHAR       *service_name;
6849 UCHAR       *service_type;
6850 UCHAR       *service_domain;
6851 UINT        rr_name_length;
6852 #endif /* NX_MDNS_DISABLE_SERVER */
6853 
6854 
6855     for(i = 0; i < 2; i++)
6856     {
6857 
6858         /* Set the pointer. */
6859         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
6860         {
6861 #ifndef NX_MDNS_DISABLE_SERVER
6862             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6863 #else
6864             continue;
6865 #endif /* NX_MDNS_DISABLE_SERVER */
6866         }
6867         else
6868         {
6869 #ifndef NX_MDNS_DISABLE_CLIENT
6870             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
6871 #else
6872             continue;
6873 #endif /* NX_MDNS_DISABLE_CLIENT  */
6874         }
6875 
6876         if(head == NX_NULL)
6877             continue;
6878 
6879         tail = (ULONG*)(*head);
6880 
6881         /* Check the remote resource record lifetime.  */
6882         for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
6883         {
6884 
6885             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
6886                 continue;
6887 
6888             /* Update the remaining ticks of peer resource record.  */
6889             if (((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
6890                  (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)))
6891             {
6892                 if (p -> nx_mdns_rr_remaining_ticks > mdns_ptr -> nx_mdns_timer_min_count)
6893                 {
6894                     p -> nx_mdns_rr_remaining_ticks -= mdns_ptr -> nx_mdns_timer_min_count;
6895                 }
6896                 else
6897                 {
6898                     p -> nx_mdns_rr_remaining_ticks = 0;
6899                 }
6900             }
6901 
6902             /* Calculate the time interval for two responses.*/
6903             if (p -> nx_mdns_rr_response_interval > mdns_ptr -> nx_mdns_timer_min_count)
6904             {
6905                 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count);
6906 
6907                 /* Compare the timer count.and set the minimum timer count. */
6908                 if ((p -> nx_mdns_rr_response_interval != 0) &&
6909                     (p -> nx_mdns_rr_response_interval < timer_min_count))
6910                 {
6911                     timer_min_count = p -> nx_mdns_rr_response_interval;
6912                 }
6913             }
6914             else
6915             {
6916                 p -> nx_mdns_rr_response_interval = 0;
6917             }
6918 
6919             /* If the timer count is zero, means do not do anything */
6920             if (p -> nx_mdns_rr_timer_count == 0)
6921                 continue;
6922 
6923             if (p -> nx_mdns_rr_timer_count > mdns_ptr -> nx_mdns_timer_min_count)
6924             {
6925                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_timer_count - mdns_ptr -> nx_mdns_timer_min_count;
6926 
6927                 /* Check the timer count range.  */
6928                 if (p -> nx_mdns_rr_timer_count <= NX_MDNS_TIMER_COUNT_RANGE)
6929                 {
6930                     p -> nx_mdns_rr_timer_count = 0;
6931                 }
6932                 else
6933                 {
6934                     /* Compare the timer count.and set the minimum timer count. */
6935                     if (p -> nx_mdns_rr_timer_count < timer_min_count)
6936                     {
6937                         timer_min_count = p -> nx_mdns_rr_timer_count;
6938                     }
6939                 }
6940             }
6941             else
6942             {
6943                 p -> nx_mdns_rr_timer_count = 0;
6944             }
6945 
6946             /* If the timer count is zero, means the timeout. */
6947             if (p -> nx_mdns_rr_timer_count != 0)
6948                 continue;
6949 
6950             /* Check the state. */
6951             switch (p -> nx_mdns_rr_state)
6952             {
6953 
6954 #ifndef NX_MDNS_DISABLE_SERVER
6955                 case NX_MDNS_RR_STATE_PROBING:
6956                 {
6957 
6958                     /* mDNS Server probing the RRs at 0ms, 250ms, 500ms. RFC6762, Section8.1, Page26.  */
6959                     if (p -> nx_mdns_rr_retransmit_count)
6960                     {
6961 
6962                         /* Set the send flag.*/
6963                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
6964 
6965                         /* Set the probing flag.  */
6966                         event_flags = event_flags | NX_MDNS_PROBING_SEND_EVENT;
6967 
6968                         /* Set the timer count. 250ms.  */
6969                         p -> nx_mdns_rr_timer_count = NX_MDNS_PROBING_TIMER_COUNT;
6970 
6971                         /* Compare the timer count.and set the minimum timer count. */
6972                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
6973                         {
6974                             timer_min_count = p -> nx_mdns_rr_timer_count;
6975                         }
6976                     }
6977                     else
6978                     {
6979 
6980                         /* Probing complete, and move to the next step, Announcing. */
6981                         p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
6982 
6983                         /* Set the first announcing timer interval.  */
6984                         p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
6985 
6986                         /* Set the retransmit count.  */
6987                         if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
6988                             p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
6989                         else
6990                             p -> nx_mdns_rr_retransmit_count = 1;
6991 
6992                         /* Set the next timer count.  */
6993                         p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
6994 
6995                         /* Check the announcing max time.  */
6996                         if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
6997                             p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
6998                         else
6999                             p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
7000 
7001                         /* Yes, probing complete, add the related PTR resource records.  */
7002                         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
7003                         {
7004 
7005                             /* Check string length.  */
7006                             if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
7007                             {
7008                                 break;
7009                             }
7010 
7011                             /* Store the service name.  */
7012                             memcpy((CHAR *)(&temp_string_buffer[0]), (const char*)p -> nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
7013 
7014                             /* Reslove the service name.  */
7015                             status = _nx_mdns_service_name_resolve(&temp_string_buffer[0], &service_name, &service_type, &service_domain);
7016 
7017                             /* Check the status.  */
7018                             if (status)
7019                             {
7020                                 break;
7021                             }
7022 
7023                             /* Service name registered success, invoke the notify function.  */
7024                             if (mdns_ptr -> nx_mdns_probing_notify)
7025                             {
7026                                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, service_name, NX_MDNS_LOCAL_SERVICE_REGISTERED_SUCCESS);
7027                             }
7028                         }
7029 
7030                         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A)
7031                         {
7032 
7033                             /* Service name registered success, invoke the notify function.  */
7034                             if (mdns_ptr -> nx_mdns_probing_notify)
7035                             {
7036                                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, mdns_ptr -> nx_mdns_host_name, NX_MDNS_LOCAL_HOST_REGISTERED_SUCCESS);
7037                             }
7038                         }
7039 
7040                         /* Probing complete, Has been wating for 250ms, Directly announcing the resource record.  */
7041                         p --;
7042                     }
7043                     break;
7044                 }
7045 
7046                 case NX_MDNS_RR_STATE_ANNOUNCING:
7047                 {
7048 
7049                     /* mDNS Server Announcing the Resource records.  */
7050                     if (p -> nx_mdns_rr_retransmit_count)
7051                     {
7052 
7053                         /* Set the send flag to send the probing. */
7054                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7055 
7056                         /* Set the announcing flag.  */
7057                         event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7058 
7059                         /* Yes, probing complete, add the related PTR resource records and NSEC resource records. */
7060                         if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
7061                             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
7062                             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
7063                         {
7064 
7065                             for (p1 = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p1 < tail; p1++)
7066                             {
7067 
7068                                 /* Check the state.  */
7069                                 if (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
7070                                     continue;
7071 
7072                                 /* Check the interface.  */
7073                                 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
7074                                     continue;
7075 
7076 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7077                                 if ((p1 ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
7078                                     (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name))
7079                                 {
7080 
7081                                     /* Set the send flag to send the probing. */
7082                                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7083                                 }
7084 #endif /*NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7085 
7086                                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
7087                                     (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
7088                                     (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_name))
7089                                 {
7090 
7091                                     /* Set the send flag to send the probing. */
7092                                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7093                                 }
7094                             }
7095                         }
7096 
7097                         /* Check last the retransmit in this period announcing.  */
7098                         if (p -> nx_mdns_rr_retransmit_count - 1)
7099                         {
7100 
7101                             if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7102                             {
7103 
7104                                 /* Set the timer count.  */
7105                                 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_announcing_retrans_interval;
7106 
7107                                 /* Compare the timer count and set the minimum timer count. */
7108                                 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7109                                 {
7110                                     timer_min_count = p -> nx_mdns_rr_timer_count;
7111                                 }
7112                             }
7113                         }
7114                         else
7115                         {
7116                             if (p -> nx_mdns_rr_announcing_max_time)
7117                             {
7118 
7119                                 /* Update the timer count.  */
7120                                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7121 
7122                                 /* Calculate the next timer count.   */
7123                                 p -> nx_mdns_rr_retransmit_lifetime = (ULONG)(p -> nx_mdns_rr_retransmit_lifetime * (ULONG)(2 << (mdns_ptr -> nx_mdns_announcing_factor - 1)));
7124 
7125                                 /* Check the announcing period time interval.  */
7126                                 if (p -> nx_mdns_rr_retransmit_lifetime > mdns_ptr -> nx_mdns_announcing_period_interval)
7127                                     p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period_interval;
7128 
7129                                 /* Set the retransmit count.  */
7130                                 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7131                                     p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
7132                                 else
7133                                     p -> nx_mdns_rr_retransmit_count = 1;
7134 
7135                                 /* Set the retransmit count.  */
7136                                 p -> nx_mdns_rr_retransmit_count++;
7137 
7138                                 /* Check the announcing time.  */
7139                                 if (p -> nx_mdns_rr_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
7140                                     p -> nx_mdns_rr_announcing_max_time--;
7141 
7142                                 /* Compare the timer count and set the minimum timer count. */
7143                                 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7144                                 {
7145                                     timer_min_count = p -> nx_mdns_rr_timer_count;
7146                                 }
7147                             }
7148                             else
7149                             {
7150 
7151                                 /* Announcing complete, Update the resource record state valid,  . */
7152                                 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
7153 
7154                                 /* Clear the timer count.  */
7155                                 p -> nx_mdns_rr_timer_count = 0;
7156                             }
7157                         }
7158                     }
7159                     break;
7160                 }
7161 
7162                 case NX_MDNS_RR_STATE_GOODBYE:
7163                 {
7164 
7165                     /* mDNS Server send Goodbye packet.  */
7166                     if (p -> nx_mdns_rr_retransmit_count)
7167                     {
7168 
7169                         /* Set the send flag to send the probing. */
7170                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7171 
7172                         /* Set the announcing flag.  */
7173                         event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7174 
7175                         /* Set the timer count.  */
7176                         p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
7177 
7178                         /* Compare the timer count.and set the minimum timer count. */
7179                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7180                         {
7181                             timer_min_count = p -> nx_mdns_rr_timer_count;
7182                         }
7183                     }
7184                     else
7185                     {
7186 
7187                         /* Check for RR delete flag.  */
7188                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE)
7189                         {
7190 
7191                             /* Delete the resource records.  */
7192                             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
7193                         }
7194                         else
7195                         {
7196 
7197                             /* Suspend the resource record.  */
7198                             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
7199                             p -> nx_mdns_rr_timer_count = 0;
7200                         }
7201                     }
7202                     break;
7203                 }
7204 #endif /* NX_MDNS_DISABLE_SERVER */
7205 
7206 
7207                 case NX_MDNS_RR_STATE_VALID:
7208                 {
7209 
7210                     if(i == NX_MDNS_CACHE_TYPE_PEER)
7211                     {
7212                         /* Set the resource record status.  */
7213                         p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_UPDATING;
7214 
7215                         /* Check the updating flag.  */
7216                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UPDATING)
7217                         {
7218 
7219                             /* Set the retransmit count.  */
7220                             p -> nx_mdns_rr_retransmit_count = NX_MDNS_RR_UPDATE_COUNT;
7221 
7222                             /* 50% of the record lifetime has elapsed,the querier should plan to issure a query at 80%-82% of the record lifetime */
7223                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (((ULONG)NX_RAND()) % 3)) / 100;
7224                         }
7225                         else
7226                         {
7227                             /* Set the retransmit count.  */
7228                             p -> nx_mdns_rr_retransmit_count = 0;
7229 
7230                             /* 50% of the record lifetime has elapsed, Delete the resource record at 100% of the record lifetime */
7231                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
7232                         }
7233 
7234                         /* Compare the timer count.and set the minimum timer count. */
7235                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7236                         {
7237                             timer_min_count = p -> nx_mdns_rr_timer_count;
7238                         }
7239                     }
7240 
7241                     /* Check the send flag.  */
7242                     else
7243                     {
7244                         if (p -> nx_mdns_rr_send_flag)
7245                         {
7246 
7247                             /* Set the send flag to send the response. */
7248                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7249 
7250 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7251                             /* Clear the NSEC additional send.  */
7252                             if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7253                                 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7254 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7255 
7256                             /* mDNS Responder MUST NOT multicast a record until at least one second has elapsed since the last time that record was multicast. RFC6762, Section6, Page16.  */
7257                             /* Set the next response time interval.  */
7258                             p -> nx_mdns_rr_response_interval = (ULONG)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE);
7259 
7260                             /* Compare the timer count.and set the minimum timer count. */
7261                             if (p -> nx_mdns_rr_response_interval < timer_min_count)
7262                             {
7263                                 timer_min_count = p -> nx_mdns_rr_response_interval;
7264                             }
7265 
7266                             /* Set the announcing flag.  */
7267                             event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7268                         }
7269 
7270 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7271                         else
7272                         {
7273                             if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7274                             {
7275                                 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send)
7276                                 {
7277                                     p -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_ADDITIONAL;
7278                                     p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7279 
7280                                     /* Set the announcing flag.  */
7281                                     event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7282                                 }
7283                             }
7284                         }
7285 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7286                     }
7287                     break;
7288                 }
7289 
7290 
7291 #ifndef NX_MDNS_DISABLE_CLIENT
7292                 case NX_MDNS_RR_STATE_QUERY:
7293                 {
7294 
7295                     /* mDNS Client did not receive the response, send the query again.  */
7296                     if (!p -> nx_mdns_rr_timer_count)
7297                     {
7298 
7299                         /* Check the Duplicate Question. If the flag set, Host should not send the query until the next timeout.  */
7300                         if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DUPLICATE_QUERY))
7301                         {
7302 
7303                             /* Set the send flag to send the query. */
7304                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7305 
7306                             /* Set the query flag.  */
7307                             event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7308                         }
7309 
7310                         /* Clear the duplicate flag.  */
7311                         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
7312 
7313                         /* Double the next timer count.   */
7314                         p -> nx_mdns_rr_retransmit_lifetime = p -> nx_mdns_rr_retransmit_lifetime << 1;
7315 
7316                         /* The interval between the first two queries MUST be at least one second. RFC6762, Section5.2, Page9.  */
7317                         if (p -> nx_mdns_rr_retransmit_lifetime < NX_MDNS_QUERY_MIN_TIMER_COUNT)
7318                         {
7319                             p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MIN_TIMER_COUNT;
7320                         }
7321 
7322                         /* When the interval between queries reaches or exceeds 60 minutes, a querier MAY cap the interval to a maximum of 60 minutes. RFC6762, Section5.2, Page10.  */
7323                         if (p -> nx_mdns_rr_retransmit_lifetime > NX_MDNS_QUERY_MAX_TIMER_COUNT)
7324                         {
7325                             p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MAX_TIMER_COUNT;
7326                         }
7327 
7328                         /* Update the timer count.  */
7329                         p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7330 
7331                         /* Compare the timer count.and set the minimum timer count. */
7332                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7333                         {
7334                             timer_min_count = p -> nx_mdns_rr_timer_count;
7335                         }
7336                     }
7337                     break;
7338                 }
7339 
7340                 case NX_MDNS_RR_STATE_UPDATING:
7341                 {
7342 
7343                     /* The querier should plan to issure a query at 80%-82% of the record lifetime, and then if no answer is received,
7344                        at 85%-87%, 90%-92% and 95%-97%. the record is deleted when it reaches 100% of its lifetime. RFC6762, Section5.2, Page10.  */
7345                     if (p -> nx_mdns_rr_retransmit_count)
7346                     {
7347 
7348                         /* Set the send flag to retransmit its query. */
7349                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7350 
7351                         /* Set the query flag.  */
7352                         event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7353 
7354                         /* Update the timer count. Client should send the updating message every 5% of ttl.   */
7355                         if (p -> nx_mdns_rr_retransmit_count == 1)
7356                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_remaining_ticks;
7357                         else
7358                         {
7359                             remaining_ticks = p -> nx_mdns_rr_remaining_ticks;
7360                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 / 100;
7361 
7362                             /* Get the remaining ticks in 5% of TTL. */
7363                             while(remaining_ticks > p -> nx_mdns_rr_timer_count)
7364                                 remaining_ticks -= p -> nx_mdns_rr_timer_count;
7365 
7366                             p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(((ULONG)NX_RAND()) % 3) / 100);
7367                         }
7368 
7369                         /* Compare the timer count.and set the minimum timer count. */
7370                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7371                         {
7372                             timer_min_count = p -> nx_mdns_rr_timer_count;
7373                         }
7374                     }
7375                     else
7376                     {
7377 
7378                         /* Delete the resource record.  */
7379                         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7380                     }
7381                     break;
7382                 }
7383 
7384                 case NX_MDNS_RR_STATE_DELETE:
7385                 case NX_MDNS_RR_STATE_POOF_DELETE:
7386                 {
7387 
7388                     /* Delete the resource record.  */
7389                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7390                     break;
7391                 }
7392 #endif /* NX_MDNS_DISABLE_CLIENT  */
7393 
7394                 default:
7395                 {
7396                     break;
7397                 }
7398             }
7399         }
7400     }
7401 
7402     /* If the specified timer rate is different with the new timer min count,then update it.*/
7403     if (mdns_ptr -> nx_mdns_timer_min_count != timer_min_count)
7404     {
7405 
7406         /* Set the minimum timer count.*/
7407         mdns_ptr -> nx_mdns_timer_min_count = timer_min_count;
7408 
7409         /* Deactivate the timer. */
7410         tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
7411 
7412         if (timer_min_count != 0xFFFFFFFF)
7413         {
7414 
7415             /* Change the timer ticks with minimum timer count.*/
7416             tx_timer_change(&(mdns_ptr -> nx_mdns_timer),
7417                             mdns_ptr -> nx_mdns_timer_min_count,
7418                             mdns_ptr -> nx_mdns_timer_min_count);
7419             tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
7420         }
7421     }
7422 
7423     /* Set the event to send mDNS query.  */
7424     tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), event_flags, TX_OR);
7425 }
7426 
7427 
7428 /**************************************************************************/
7429 /*                                                                        */
7430 /*  FUNCTION                                               RELEASE        */
7431 /*                                                                        */
7432 /*    _nx_mdns_udp_receive_notify                         PORTABLE C      */
7433 /*                                                           6.1          */
7434 /*  AUTHOR                                                                */
7435 /*                                                                        */
7436 /*    Yuxin Zhou, Microsoft Corporation                                   */
7437 /*                                                                        */
7438 /*  DESCRIPTION                                                           */
7439 /*                                                                        */
7440 /*    This function is the mDNS UDP receive notify callback.              */
7441 /*                                                                        */
7442 /*  INPUT                                                                 */
7443 /*                                                                        */
7444 /*    socket_ptr                            Pointer to udp socket         */
7445 /*                                                                        */
7446 /*  OUTPUT                                                                */
7447 /*                                                                        */
7448 /*    None                                                                */
7449 /*                                                                        */
7450 /*  CALLS                                                                 */
7451 /*                                                                        */
7452 /*    tx_event_flags_set                    Set event flags               */
7453 /*                                                                        */
7454 /*  CALLED BY                                                             */
7455 /*                                                                        */
7456 /*    UDP receive callback                                                */
7457 /*                                                                        */
7458 /*  RELEASE HISTORY                                                       */
7459 /*                                                                        */
7460 /*    DATE              NAME                      DESCRIPTION             */
7461 /*                                                                        */
7462 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7463 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7464 /*                                            resulting in version 6.1    */
7465 /*                                                                        */
7466 /**************************************************************************/
_nx_mdns_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)7467 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
7468 {
7469 
7470 
7471     NX_PARAMETER_NOT_USED(socket_ptr);
7472 
7473     /* Check the mDNS.  */
7474     if(_nx_mdns_created_ptr)
7475     {
7476 
7477         /* Set the receive UDP packet notify. */
7478         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_PKT_RX_EVENT, TX_OR);
7479     }
7480 
7481     return;
7482 }
7483 
7484 #ifndef NX_MDNS_DISABLE_SERVER
7485 #ifndef NX_DISABLE_IPV4
7486 /**************************************************************************/
7487 /*                                                                        */
7488 /*  FUNCTION                                               RELEASE        */
7489 /*                                                                        */
7490 /*    _nx_mdns_ip_address_change_notify                   PORTABLE C      */
7491 /*                                                           6.1          */
7492 /*  AUTHOR                                                                */
7493 /*                                                                        */
7494 /*    Yuxin Zhou, Microsoft Corporation                                   */
7495 /*                                                                        */
7496 /*  DESCRIPTION                                                           */
7497 /*                                                                        */
7498 /*    This function is the mDNS UDP receive notify callback.              */
7499 /*                                                                        */
7500 /*  INPUT                                                                 */
7501 /*                                                                        */
7502 /*    socket_ptr                            Pointer to udp socket         */
7503 /*                                                                        */
7504 /*  OUTPUT                                                                */
7505 /*                                                                        */
7506 /*    None                                                                */
7507 /*                                                                        */
7508 /*  CALLS                                                                 */
7509 /*                                                                        */
7510 /*    tx_event_flags_set                    Set event flags               */
7511 /*                                                                        */
7512 /*  CALLED BY                                                             */
7513 /*                                                                        */
7514 /*    UDP receive callback                                                */
7515 /*                                                                        */
7516 /*  RELEASE HISTORY                                                       */
7517 /*                                                                        */
7518 /*    DATE              NAME                      DESCRIPTION             */
7519 /*                                                                        */
7520 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7521 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7522 /*                                            resulting in version 6.1    */
7523 /*                                                                        */
7524 /**************************************************************************/
_nx_mdns_ip_address_change_notify(NX_IP * ip_ptr,VOID * additional_info)7525 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info)
7526 {
7527 
7528 
7529     NX_PARAMETER_NOT_USED(ip_ptr);
7530     NX_PARAMETER_NOT_USED(additional_info);
7531 
7532     /* Check the mDNS.  */
7533     if(_nx_mdns_created_ptr)
7534     {
7535 
7536         /* Set the address change event event. */
7537         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7538     }
7539 
7540     return;
7541 }
7542 #endif /* NX_DISABLE_IPV4 */
7543 
7544 
7545 /**************************************************************************/
7546 /*                                                                        */
7547 /*  FUNCTION                                               RELEASE        */
7548 /*                                                                        */
7549 /*    _nx_mdns_ipv6_address_change_notify                 PORTABLE C      */
7550 /*                                                           6.1          */
7551 /*  AUTHOR                                                                */
7552 /*                                                                        */
7553 /*    Yuxin Zhou, Microsoft Corporation                                   */
7554 /*                                                                        */
7555 /*  DESCRIPTION                                                           */
7556 /*                                                                        */
7557 /*    This function is the mDNS UDP receive notify callback.              */
7558 /*                                                                        */
7559 /*  INPUT                                                                 */
7560 /*                                                                        */
7561 /*    socket_ptr                            Pointer to udp socket         */
7562 /*                                                                        */
7563 /*  OUTPUT                                                                */
7564 /*                                                                        */
7565 /*    None                                                                */
7566 /*                                                                        */
7567 /*  CALLS                                                                 */
7568 /*                                                                        */
7569 /*    tx_event_flags_set                    Set event flags               */
7570 /*                                                                        */
7571 /*  CALLED BY                                                             */
7572 /*                                                                        */
7573 /*    UDP receive callback                                                */
7574 /*                                                                        */
7575 /*  RELEASE HISTORY                                                       */
7576 /*                                                                        */
7577 /*    DATE              NAME                      DESCRIPTION             */
7578 /*                                                                        */
7579 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7580 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7581 /*                                            resulting in version 6.1    */
7582 /*                                                                        */
7583 /**************************************************************************/
7584 #ifdef NX_MDNS_ENABLE_IPV6
_nx_mdns_ipv6_address_change_notify(NX_IP * ip_ptr,UINT method,UINT interface_index,UINT index,ULONG * ipv6_address)7585 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address)
7586 {
7587 
7588     NX_PARAMETER_NOT_USED(ip_ptr);
7589     NX_PARAMETER_NOT_USED(method);
7590     NX_PARAMETER_NOT_USED(interface_index);
7591     NX_PARAMETER_NOT_USED(index);
7592     NX_PARAMETER_NOT_USED(ipv6_address);
7593 
7594     /* Check the mDNS.  */
7595     if(_nx_mdns_created_ptr)
7596     {
7597 
7598         /* Set the address change event. */
7599         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7600     }
7601     return;
7602 }
7603 #endif /* NX_MDNS_ENABLE_IPV6  */
7604 #endif /* NX_MDNS_DISABLE_SERVER  */
7605 
7606 
7607 /**************************************************************************/
7608 /*                                                                        */
7609 /*  FUNCTION                                               RELEASE        */
7610 /*                                                                        */
7611 /*    _nx_mdns_thread_entry                               PORTABLE C      */
7612 /*                                                           6.1          */
7613 /*  AUTHOR                                                                */
7614 /*                                                                        */
7615 /*    Yuxin Zhou, Microsoft Corporation                                   */
7616 /*                                                                        */
7617 /*  DESCRIPTION                                                           */
7618 /*                                                                        */
7619 /*    This function is the entry point for the mDNS helper thread.        */
7620 /*    mDNS helper thread is responsible for processing mDNS events.       */
7621 /*    Receive and send the mDNS packet.                                   */
7622 /*                                                                        */
7623 /*  INPUT                                                                 */
7624 /*                                                                        */
7625 /*    mdns_value                            Pointer to mDNS instance      */
7626 /*                                                                        */
7627 /*  OUTPUT                                                                */
7628 /*                                                                        */
7629 /*    None                                                                */
7630 /*                                                                        */
7631 /*  CALLS                                                                 */
7632 /*                                                                        */
7633 /*    tx_mutex_get                          Get the mDNS mutex            */
7634 /*    tx_mutex_put                          Put the mDNS mutex            */
7635 /*    tx_event_flags_get                    Get the mDNS events           */
7636 /*    nx_udp_socket_receive                 Receive the mDNS packet       */
7637 /*    nx_packet_release                     Release the mDNS packet       */
7638 /*    _nx_mdns_packet_process               Process mDNS packet           */
7639 /*    _nx_mdns_announcing_send              Send announcing message       */
7640 /*    _nx_mdns_probing_send                 Send probing message          */
7641 /*    _nx_mdns_query_send                   Send query message            */
7642 /*    _nx_mdns_response_send                Send response message         */
7643 /*    _nx_mdns_timer_event_process          Process the mDNS timer event  */
7644 /*    _nx_mdns_address_change_process       Process the address change    */
7645 /*                                                                        */
7646 /*  CALLED BY                                                             */
7647 /*                                                                        */
7648 /*    ThreadX Scheduler                                                   */
7649 /*                                                                        */
7650 /*  RELEASE HISTORY                                                       */
7651 /*                                                                        */
7652 /*    DATE              NAME                      DESCRIPTION             */
7653 /*                                                                        */
7654 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7655 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7656 /*                                            resulting in version 6.1    */
7657 /*                                                                        */
7658 /**************************************************************************/
_nx_mdns_thread_entry(ULONG mdns_value)7659 static VOID  _nx_mdns_thread_entry(ULONG mdns_value)
7660 {
7661 
7662 NX_MDNS         *mdns_ptr;
7663 NX_PACKET       *packet_ptr;
7664 ULONG            mdns_events;
7665 UINT             status;
7666 UINT             interface_index;
7667 
7668 
7669     /* Setup mDNS pointer from the input value.  */
7670     mdns_ptr =  (NX_MDNS *) mdns_value;
7671 
7672     /* Get the mDNS mutex.  */
7673     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7674 
7675     /* Loop to process events for this mDNS instance.  */
7676     while(1)
7677     {
7678 
7679         /* Release the mDNS mutex.  */
7680         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
7681 
7682         /* Pickup mDNS event flags.  */
7683         tx_event_flags_get(&mdns_ptr -> nx_mdns_events,
7684                            NX_MDNS_ALL_EVENTS, TX_OR_CLEAR,
7685                            &mdns_events, TX_WAIT_FOREVER);
7686 
7687         /* Get the mDNS mutex.  */
7688         tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7689 
7690         /* Check for an UDP packet receive event. */
7691         if (mdns_events & NX_MDNS_PKT_RX_EVENT)
7692         {
7693             while (1)
7694             {
7695 
7696                 /* Receive a UDP packet.  */
7697                 status =  _nx_udp_socket_receive(&mdns_ptr -> nx_mdns_socket,
7698                                                  &packet_ptr, TX_NO_WAIT);
7699 
7700                 /* Check status.  */
7701                 if (status != NX_SUCCESS)
7702                     break;
7703 
7704 #ifndef NX_DISABLE_PACKET_CHAIN
7705 
7706                 /* Discard the chained packets.  */
7707                 if (packet_ptr -> nx_packet_next)
7708                 {
7709                     nx_packet_release(packet_ptr);
7710                     continue;
7711                 }
7712 #endif
7713 
7714                 /* Get the interface.  */
7715                 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
7716                 {
7717                     interface_index = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
7718                 }
7719                 else
7720                 {
7721                     interface_index = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_index;
7722                 }
7723 
7724                 /* Check the interface.  */
7725                 if (!mdns_ptr -> nx_mdns_interface_enabled[interface_index])
7726                 {
7727                     /* Release the packet since mDNS is not enabled on this interface. */
7728                     nx_packet_release(packet_ptr);
7729                     continue;
7730                 }
7731 
7732                 /* Yes, Get the mDNS packet, process it.  */
7733                 _nx_mdns_packet_process(mdns_ptr, packet_ptr, interface_index);
7734 
7735                 /* Release the packet. */
7736                 nx_packet_release(packet_ptr);
7737             }
7738         }
7739 
7740         /* Loop to send mDNS message for each interface.  */
7741         for (interface_index = 0; interface_index < NX_MAX_PHYSICAL_INTERFACES; interface_index++)
7742         {
7743 
7744             /* Check if this interface is enabled.
7745                Exception: Goodbye message can be sent out after disable.  */
7746             if ((!mdns_ptr -> nx_mdns_interface_enabled[interface_index]) &&
7747                 (!(mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)))
7748                 continue;
7749 
7750 #ifndef NX_MDNS_DISABLE_SERVER
7751 
7752             /* Check for an mDNS probing send event. */
7753             if (mdns_events & NX_MDNS_PROBING_SEND_EVENT)
7754             {
7755 
7756                 /* Send probing.  */
7757                 _nx_mdns_probing_send(mdns_ptr, interface_index);
7758             }
7759 
7760             /* Check for an mDNS announcing send event. */
7761             if (mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)
7762             {
7763 
7764                 /* Send announcing.  */
7765                 _nx_mdns_announcing_send(mdns_ptr, interface_index);
7766             }
7767 
7768             /* Check for an mDNS response send event. */
7769             if (mdns_events & NX_MDNS_RESPONSE_SEND_EVENT)
7770             {
7771 
7772                 /* Send response.  */
7773                 _nx_mdns_response_send(mdns_ptr, interface_index);
7774             }
7775 #endif /* NX_MDNS_DISABLE_SERVER */
7776 
7777 #ifndef NX_MDNS_DISABLE_CLIENT
7778             /* Check for an mDNS query send event. */
7779             if (mdns_events & NX_MDNS_QUERY_SEND_EVENT)
7780             {
7781 
7782                 /* Send query.  */
7783                 _nx_mdns_query_send(mdns_ptr, interface_index);
7784             }
7785 #endif /* NX_MDNS_DISABLE_CLIENT */
7786         }
7787 
7788 #ifndef NX_MDNS_DISABLE_SERVER
7789 
7790         /* Check for an mDNS address change event. */
7791         if (mdns_events & NX_MDNS_ADDRESS_CHANGE_EVENT)
7792         {
7793 
7794             /* Process the address change event.  */
7795             _nx_mdns_address_change_process(mdns_ptr);
7796         }
7797 #endif /* NX_MDNS_DISABLE_SERVER */
7798 
7799         /* Check for an mDNS timer process event. */
7800         if (mdns_events & NX_MDNS_TIMER_EVENT)
7801         {
7802 
7803             /* Process the timer event.  */
7804             _nx_mdns_timer_event_process(mdns_ptr);
7805         }
7806     }
7807 }
7808 
7809 
7810 /**************************************************************************/
7811 /*                                                                        */
7812 /*  FUNCTION                                               RELEASE        */
7813 /*                                                                        */
7814 /*    _nx_mdns_packet_process                             PORTABLE C      */
7815 /*                                                           6.1.11       */
7816 /*  AUTHOR                                                                */
7817 /*                                                                        */
7818 /*    Yuxin Zhou, Microsoft Corporation                                   */
7819 /*                                                                        */
7820 /*  DESCRIPTION                                                           */
7821 /*                                                                        */
7822 /*    This function checks the interface and the IP address of received   */
7823 /*    packet, then preocesses the packet.                                 */
7824 /*                                                                        */
7825 /*  INPUT                                                                 */
7826 /*                                                                        */
7827 /*    mdns_ptr                              Pointer to mDNS instance      */
7828 /*    packet_ptr                            Pointer to mDNS packet        */
7829 /*                                                                        */
7830 /*  OUTPUT                                                                */
7831 /*                                                                        */
7832 /*    status                                Completion status             */
7833 /*                                                                        */
7834 /*  CALLS                                                                 */
7835 /*                                                                        */
7836 /*    nx_packet_release                     Release the mDNS packet       */
7837 /*    _tx_thread_system_resume              Resume thread service         */
7838 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
7839 /*    _nx_mdns_name_string_decode           Decode the name size          */
7840 /*    _nx_mdns_name_size_calculate          Calculate the name size       */
7841 /*    _nx_mdns_rr_size_get                  Get the resource record size  */
7842 /*    _nx_mdns_conflict_process             Process the mDNS conflict     */
7843 /*    _nx_mdns_cache_find_resource_record   Find the mDNS resource record */
7844 /*    _nx_mdns_packet_address_check         Check the address and port    */
7845 /*    _nx_mdns_packet_rr_process            Process resource record       */
7846 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
7847 /*                                            from cache                  */
7848 /*    nxd_udp_packet_info_extract           Extract the packet info       */
7849 /*                                                                        */
7850 /*  CALLED BY                                                             */
7851 /*                                                                        */
7852 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
7853 /*                                                                        */
7854 /*  RELEASE HISTORY                                                       */
7855 /*                                                                        */
7856 /*    DATE              NAME                      DESCRIPTION             */
7857 /*                                                                        */
7858 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7859 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7860 /*                                            resulting in version 6.1    */
7861 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
7862 /*                                            packet length verification, */
7863 /*                                            resulting in version 6.1.4  */
7864 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
7865 /*                                            corrected the random value, */
7866 /*                                            fixed the issue of timer,   */
7867 /*                                            resulting in version 6.1.11 */
7868 /*                                                                        */
7869 /**************************************************************************/
_nx_mdns_packet_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)7870 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
7871 {
7872 
7873 USHORT              mdns_flags;
7874 UCHAR              *data_ptr;
7875 USHORT              question_count;
7876 USHORT              authority_count;
7877 USHORT              answer_count;
7878 UINT                index;
7879 NX_MDNS_RR         *rr_search;
7880 NX_MDNS_RR          temp_resource_record;
7881 
7882 #ifndef NX_MDNS_DISABLE_SERVER
7883 ULONG              *head;
7884 NX_MDNS_RR         *p;
7885 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7886 ULONG               match_count;
7887 NX_MDNS_RR         *nsec_rr;
7888 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7889 #endif /* NX_MDNS_DISABLE_SERVER  */
7890 
7891 
7892 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
7893     /* Check the address and port.  */
7894     if (_nx_mdns_packet_address_check(packet_ptr))
7895     {
7896         return(NX_MDNS_ERROR);
7897     }
7898 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
7899 
7900     /* Check the packet length.  */
7901     if (packet_ptr -> nx_packet_length < NX_MDNS_QDSECT_OFFSET)
7902     {
7903         return(NX_MDNS_ERROR);
7904     }
7905 
7906     /* Extract the message type which should be the first byte.  */
7907     mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
7908 
7909     /* Get the question count.  */
7910     question_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET);
7911 
7912     /* Determine if we have any 'answers' to our DNS query. */
7913     answer_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET);
7914 
7915     /* Also check if there are any 'hints' from the Authoritative nameserver. */
7916     authority_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET);
7917 
7918     /* Update the answer count. Ignore the authority count and additional count for query message.  */
7919     if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7920     {
7921         answer_count = (USHORT)(answer_count + authority_count);
7922 
7923         /* Include Additional section as well */
7924         answer_count = (USHORT)(answer_count + NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET));
7925     }
7926 
7927     /* Skip the Header. Point at the start of the question.  */
7928     data_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
7929 
7930     /* Process all the Question Section.  */
7931     for (index = 0; index < question_count; index++)
7932     {
7933 
7934         /* Check for data_ptr.  */
7935         if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
7936             break;
7937 
7938         if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7939         {
7940 
7941             /* Multicast DNS responses MUST NOT contain any question in the Question Section,
7942                Any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. RFC6762, Section6, Page14.  */
7943             data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
7944         }
7945         else
7946         {
7947 
7948 #ifndef NX_MDNS_DISABLE_CLIENT
7949 
7950             /* Step1, mDNS Client process the Duplicate Question Suppression, RFC6762, Section7.3, Page24.  */
7951             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
7952             {
7953 
7954                 /* Check the class top bit "QM".   */
7955                 if ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_RR_CLASS_TOP_BIT) != NX_MDNS_RR_CLASS_TOP_BIT)
7956                 {
7957 
7958                     /* Find the same resource record in remote buffer.  */
7959                     if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
7960                     {
7961 
7962                         /* Duplicate Question Suppression.  */
7963                         if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
7964                         {
7965 
7966                             if (_nx_mdns_known_answer_find(mdns_ptr, rr_search) == NX_MDNS_NO_KNOWN_ANSWER)
7967                             {
7968 
7969                                 /* Yes, set the duplicate flag. process this flag in timer event process function.  */
7970                                 rr_search -> nx_mdns_rr_word = rr_search -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DUPLICATE_QUERY;
7971                             }
7972                         }
7973 
7974 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
7975                         /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
7976                         if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
7977                             (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
7978                         {
7979                             rr_search -> nx_mdns_rr_poof_count ++;
7980 
7981                             /* After seeing two or more of these queries, and seeing no multicast response containing the expected anser within ten seconds, the record should be flushed from the cache.  */
7982                             if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
7983                                 (rr_search -> nx_mdns_rr_poof_count >= NX_MDNS_POOF_MIN_COUNT))
7984                             {
7985                                 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_POOF_DELETE;
7986                                 rr_search -> nx_mdns_rr_timer_count = NX_MDNS_POOF_TIMER_COUNT;
7987 
7988                                 /* Set the mDNS timer.  */
7989                                 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
7990                             }
7991                         }
7992 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
7993                     }
7994                 }
7995             }
7996 #endif /* NX_MDNS_DISABLE_CLIENT */
7997 
7998 #ifndef NX_MDNS_DISABLE_SERVER
7999 
8000             /* Step2, mDNS Server process the normal query.  */
8001             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8002             {
8003 
8004 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8005                 /* Set the match count.  */
8006                 match_count = 0;
8007                 nsec_rr = NX_NULL;
8008 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8009 
8010                 /* Get head. */
8011                 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8012                 head = (ULONG*)(*head);
8013 
8014                 /* Find the same record.  */
8015                 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
8016                 {
8017 
8018                     /* Check the interface index.  */
8019                     if (p -> nx_mdns_rr_interface_index != interface_index)
8020                         continue;
8021 
8022                     /* Check whether the resource record is valid. */
8023                     if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
8024                         continue;
8025 
8026                     /* Check whether the same record it is. RFC6762, Section6, Page13. */
8027                     /* The rules: rrname must match the question name.
8028                     rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
8029                     rrclass must match the question qclass unless the qclass is "ANY". */
8030                     if (p -> nx_mdns_rr_name != temp_resource_record.nx_mdns_rr_name)
8031                         continue;
8032 
8033 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8034 
8035                     /* Check the NSEC type.  */
8036                     if (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
8037                         nsec_rr = p;
8038 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8039 
8040                     if ((p -> nx_mdns_rr_type != temp_resource_record.nx_mdns_rr_type) &&
8041                         (temp_resource_record.nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
8042                         (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
8043                         continue;
8044 
8045                     /* Check the RR class, Ignore the top bit.  */
8046                     if ((p -> nx_mdns_rr_class != (temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
8047                         ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)!= NX_MDNS_RR_CLASS_ALL))
8048                         continue;
8049 
8050 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8051 
8052                     /* Update the match count.  */
8053                     match_count ++;
8054 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8055 
8056                     /* Check the state.  */
8057                     if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8058                         (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
8059                     {
8060 
8061                         /* Check the send flag, Flag is set indicate this resource record shoud be sent.  */
8062                         if (p -> nx_mdns_rr_send_flag)
8063                         {
8064 
8065                             /* Set the flag to send this Resource records via multicast.
8066                             Store the old flag into the top bits.
8067                             Store the new flag into the low bits.
8068                             Format: 0001 0001 */
8069                             p -> nx_mdns_rr_send_flag = ((NX_MDNS_RR_SEND_MULTICAST << 4) | NX_MDNS_RR_SEND_MULTICAST);
8070                         }
8071                         else
8072                         {
8073 
8074                             /* Set the flag to send this Resource records via multicast.*/
8075                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8076                         }
8077 
8078                         /* In the case where the query has the TC (truncated) bit set, indicating that subsequent Known-Answer packets will follow,
8079                            Responders SHOULD delay their responses by a random amount of time selected with uniform random distribution in the range 400-500ms. RFC6762, Section6, Page 15.  */
8080                         if (mdns_flags & NX_MDNS_TC_FLAG)
8081                         {
8082                             p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_TC_DELAY_RANGE));
8083                         }
8084                         else
8085                         {
8086 
8087                             /* A mDNS responder is only required to delay its transmission as necessary to ensure an interval of at least 250ms
8088                             since the last time the record was multicast on that interface.  RFC6762, Section6, Page16 */
8089                             if (authority_count)
8090                             {
8091                                 if (p -> nx_mdns_rr_response_interval > (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT))
8092                                     p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT));
8093                                 else
8094                                     p -> nx_mdns_rr_response_interval = 0;
8095                             }
8096 
8097                             /* Check the response interval.  */
8098                             if (p -> nx_mdns_rr_response_interval <= NX_MDNS_TIMER_COUNT_RANGE)
8099                             {
8100 
8101                                 /* Set the timer count according to the resource record set.RFC6762, Section6, Page14.  */
8102                                 if ((p ->nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) == NX_MDNS_RR_FLAG_UNIQUE)
8103                                 {
8104                                     p -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8105                                 }
8106                                 else
8107                                 {
8108                                     /* Set the timer count, delay 20-120ms.  */
8109                                     p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8110                                 }
8111                             }
8112                             else
8113                             {
8114                                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_response_interval;
8115                             }
8116                         }
8117 
8118                         /* Set the mDNS timer.  */
8119                         _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
8120                     }
8121                 }
8122 
8123 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8124                 /* Send this NSEC response as additional answer.  */
8125                 if ((match_count == 0) && (nsec_rr))
8126                 {
8127                     nsec_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_TRUE;
8128                     nsec_rr -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8129                     _nx_mdns_timer_set(mdns_ptr, nsec_rr, nsec_rr -> nx_mdns_rr_timer_count);
8130                 }
8131 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8132             }
8133 #endif /* NX_MDNS_DISABLE_SERVER */
8134 
8135             /* Update the data_ptr.  */
8136             data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
8137         }
8138     }
8139 
8140     /* Process all the Known-Answer records.  */
8141     for (index = 0; index < answer_count; index++)
8142     {
8143 
8144         /* Check for data_ptr.  */
8145         if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
8146             break;
8147 
8148         if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
8149         {
8150 
8151 #ifndef NX_MDNS_DISABLE_SERVER
8152             /* Step1, Cooperating Multicast DNS Responders, RFC6762, Section6.6, Page21. */
8153             /* Does the same rname and rdata name of resource record exist in the local buffer.  */
8154             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8155             {
8156 
8157                 /* Find the same rname, rrtype, rrclass of resource record in local buffer.  */
8158                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8159                 {
8160 
8161                     /* Probing state, conflict Resolution.  */
8162                     if ((rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) &&
8163                         (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING))
8164                     {
8165                         _nx_mdns_conflict_process(mdns_ptr, rr_search);
8166 
8167                         /* Update the data_ptr.  */
8168                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8169 
8170                         continue;
8171                     }
8172                 }
8173 
8174                 /* Find the same rname, rrtype, rrclass and identical rdata of resource record in local buffer.  */
8175                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8176                 {
8177 
8178                     /* If the TTL in this record(B) is less than half the true TTL in local record(A), A MUST announce local record via multicast. RFC6762, Section6.6,Page21.  */
8179                     if ((temp_resource_record.nx_mdns_rr_ttl << 1) < rr_search -> nx_mdns_rr_ttl)
8180                     {
8181 
8182                         /* Set the flag.  */
8183                         rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8184 
8185                         /* Set the timer count, delay 20-120ms.  */
8186                         rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8187 
8188                         /* Set the mDNS timer.  */
8189                         _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
8190                     }
8191 
8192                     /* Duplicate Answer Suppression, RFC6762, Section7.4,Page24.
8193                        The TTL in that record is not less than the TTL this host would have given. Host should not send this response again.  */
8194                     if (temp_resource_record.nx_mdns_rr_ttl >= rr_search -> nx_mdns_rr_ttl)
8195                     {
8196 
8197                         if (rr_search -> nx_mdns_rr_send_flag)
8198                         {
8199 
8200                             /* Clear the flag.  */
8201                             rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8202                         }
8203                     }
8204 
8205                     /* Check the resource records set.  */
8206                     if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8207                     {
8208 
8209                         /* Update the data_ptr.  */
8210                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8211 
8212                         continue;
8213                     }
8214                 }
8215             }
8216 
8217             /* Did the same name of resource record have existed in local buffer.  */
8218             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8219             {
8220 
8221                 /* Find the same name, rrtype, rrclass and different rdata of resource record in local buffer.  */
8222                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8223                 {
8224 
8225                     /* Check the resource records set. RFC6762, Section6.6, Page21.  */
8226                     if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8227                     {
8228                         _nx_mdns_conflict_process(mdns_ptr, rr_search);
8229 
8230                         /* Update the data_ptr.  */
8231                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8232 
8233                         continue;
8234                     }
8235                 }
8236             }
8237 #endif /* NX_MDNS_DISABLE_SERVER */
8238 
8239 #ifndef NX_MDNS_DISABLE_CLIENT
8240             /* Step2. Add the response resource records in remote buffer.  */
8241             _nx_mdns_packet_rr_process(mdns_ptr, packet_ptr, data_ptr, interface_index);
8242 #endif /* NX_MDNS_DISABLE_CLIENT */
8243         }
8244         else
8245         {
8246 #ifndef NX_MDNS_DISABLE_CLIENT
8247             /* Clear the record.  */
8248 
8249             /* Step1, mDNS Client process the Known-Answer about Duplicate Question Suppression.  */
8250             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8251             {
8252 
8253                 /* Find the same resource record in remote buffer.  */
8254                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8255                 {
8256 
8257                     /* Duplicate Question Suppression.  */
8258                     if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
8259                     {
8260 
8261                         /* Yes, the query includes the Known-Answer Section, clear the duplicate flag.  */
8262                         rr_search -> nx_mdns_rr_word = (USHORT)(rr_search -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
8263                     }
8264 
8265 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
8266                     /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
8267                     if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8268                         (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
8269                     {
8270                         rr_search -> nx_mdns_rr_poof_count --;
8271 
8272                         /* Check the count.  */
8273                         if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE) &&
8274                             (rr_search -> nx_mdns_rr_poof_count < NX_MDNS_POOF_MIN_COUNT))
8275                         {
8276                             rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
8277                             rr_search -> nx_mdns_rr_timer_count = 0;
8278                         }
8279                     }
8280 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
8281                 }
8282             }
8283 #endif /* NX_MDNS_DISABLE_CLIENT */
8284 
8285 #ifndef NX_MDNS_DISABLE_SERVER
8286 
8287             /* Step2. mDNS Server process the Known-Answer of normal query.  */
8288             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8289             {
8290 
8291                 /* Find the same resource record.  */
8292                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8293                 {
8294 
8295                     /* mDNS responder Must Not answer a mDNS query if the answer included the Answer Section with an RR TTL at least half the correct value.  RFC6762, Section7.1, Page23.  */
8296                     if ((!(rr_search -> nx_mdns_rr_send_flag & NX_MDNS_RR_SEND_FLAG_MASK)) &&
8297                         ((temp_resource_record.nx_mdns_rr_ttl << 1) >= rr_search -> nx_mdns_rr_ttl))
8298                     {
8299 
8300                         /* Top four bit is zero and this resource reocrd is Known answer.
8301                         Clear the send flag. */
8302                         rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8303                     }
8304                 }
8305             }
8306 #endif /* NX_MDNS_DISABLE_SERVER */
8307         }
8308 
8309         /* Update the data_ptr.  */
8310         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8311     }
8312 
8313     return(NX_MDNS_SUCCESS);
8314 }
8315 
8316 
8317 #ifndef NX_MDNS_DISABLE_SERVER
8318 /**************************************************************************/
8319 /*                                                                        */
8320 /*  FUNCTION                                               RELEASE        */
8321 /*                                                                        */
8322 /*    _nx_mdns_probing_send                               PORTABLE C      */
8323 /*                                                           6.1          */
8324 /*  AUTHOR                                                                */
8325 /*                                                                        */
8326 /*    Yuxin Zhou, Microsoft Corporation                                   */
8327 /*                                                                        */
8328 /*  DESCRIPTION                                                           */
8329 /*                                                                        */
8330 /*    This function sends mDNS probing message.                           */
8331 /*                                                                        */
8332 /*  INPUT                                                                 */
8333 /*                                                                        */
8334 /*    mdns_ptr                              Pointer to mDNS instance      */
8335 /*                                                                        */
8336 /*  OUTPUT                                                                */
8337 /*                                                                        */
8338 /*    none                                                                */
8339 /*                                                                        */
8340 /*  CALLS                                                                 */
8341 /*                                                                        */
8342 /*                                                                        */
8343 /*  CALLED BY                                                             */
8344 /*                                                                        */
8345 /*                                                                        */
8346 /*  RELEASE HISTORY                                                       */
8347 /*                                                                        */
8348 /*    DATE              NAME                      DESCRIPTION             */
8349 /*                                                                        */
8350 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8351 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8352 /*                                            resulting in version 6.1    */
8353 /*                                                                        */
8354 /**************************************************************************/
_nx_mdns_probing_send(NX_MDNS * mdns_ptr,UINT interface_index)8355 static VOID    _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8356 {
8357 
8358 UINT                status;
8359 NX_PACKET           *packet_ptr;
8360 ULONG               *head;
8361 NX_MDNS_RR          *p;
8362 USHORT              question_count = 0;
8363 USHORT              answer_count = 0;
8364 USHORT              authority_count = 0;
8365 USHORT              additional_count = 0;
8366 UCHAR               resend_flag = NX_FALSE;
8367 USHORT              total_size;
8368 USHORT              rr_size;
8369 UINT                name_size;
8370 NX_MDNS_RR          *p1;
8371 UINT                rr_name_length;
8372 
8373 
8374     /* Create the mdns packet and add the mDNS header.  */
8375     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8376 
8377     /* Check for errors. */
8378     if (status != NX_SUCCESS)
8379     {
8380         return;
8381     }
8382 
8383     /* Set the total size.  */
8384     total_size = (USHORT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
8385 
8386     /* Set the head pointer. */
8387     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8388 
8389     /* Add the answer resource record.  */
8390     for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8391     {
8392 
8393         /* Check the interface index.  */
8394         if (p -> nx_mdns_rr_interface_index != interface_index)
8395             continue;
8396 
8397         /* Check the send flag.  */
8398         if (p -> nx_mdns_rr_send_flag == 0)
8399             continue;
8400 
8401         /* Check the state. */
8402         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8403             continue;
8404 
8405         /* Add the resource record into packet.  */
8406 
8407         /* Calculate the question and answer size before sending the probing message, make sure the question and authority in one packet.  */
8408 
8409         /* Check string length.  */
8410         if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
8411         {
8412             continue;
8413         }
8414 
8415         /* Calculate the name size. The name should plus the '.' and '\0'. */
8416         name_size = rr_name_length + 2;
8417 
8418         /* Calculate the resource record size for question. QNAME, QTYPE, QCLASS.  */
8419         rr_size = (USHORT)(name_size + 4);
8420 
8421         /* Calcuate the resource record size for authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
8422         rr_size = (USHORT)(rr_size + (name_size + 10 + p -> nx_mdns_rr_rdata_length));
8423 
8424         /* Check if need add other authority answers for this same question.  */
8425         for(p1 = (NX_MDNS_RR*)(head + 1); (ULONG)p1 < *head; p1++)
8426         {
8427 
8428             /* Check the interface index.  */
8429             if (p1 -> nx_mdns_rr_interface_index != interface_index)
8430                 continue;
8431 
8432             /* Check the state.  */
8433             if (p1 -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8434                 continue;
8435 
8436             /* Check the name and flag.  */
8437             if ((p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name) &&
8438                 (p1 -> nx_mdns_rr_send_flag) &&
8439                 (p1 != p))
8440             {
8441 
8442                 /* Calculate the resource record size for other authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
8443                 rr_size = (USHORT)(rr_size + (name_size + 10 + p1 -> nx_mdns_rr_rdata_length));
8444 
8445                 /* Check the packet size.  */
8446                 if (rr_size <= total_size)
8447                 {
8448 
8449                     /* Set the authority answer flag.  */
8450                     p1 -> nx_mdns_rr_word = p1 -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8451 
8452                     /* Clear the send flag.  */
8453                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8454                 }
8455                 else
8456                 {
8457                     resend_flag = NX_TRUE;
8458                     break;
8459                 }
8460             }
8461         }
8462 
8463         /* Check the packet size.  */
8464         if (rr_size > total_size)
8465         {
8466             resend_flag = NX_TRUE;
8467             continue;
8468         }
8469         else
8470             total_size = (USHORT)(total_size - rr_size);
8471 
8472         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_PROBING);
8473 
8474         if (status)
8475         {
8476             resend_flag = NX_TRUE;
8477         }
8478         else
8479         {
8480 
8481             /* Set the authority answer flag.  */
8482             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8483 
8484             /* Update the question count.  */
8485             question_count ++;
8486 
8487             /* Clear the flag.  */
8488             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8489         }
8490     }
8491 
8492     /* Add the authority answer resource record.  */
8493     for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8494     {
8495 
8496         /* Check the interface index.  */
8497         if (p -> nx_mdns_rr_interface_index != interface_index)
8498             continue;
8499 
8500         /* Check whether set the resource record send flag. */
8501         if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING) &&
8502             (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_AUTHORIY_ANSWER))
8503         {
8504 
8505             /* Add the resource record into packet.  */
8506             status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_PROBING);
8507             if (status)
8508                 resend_flag = NX_TRUE;
8509             else
8510             {
8511 
8512                 /* Update the retransmit count.  */
8513                 p -> nx_mdns_rr_retransmit_count --;
8514 
8515                 /* Update the authority count.  */
8516                 authority_count ++;
8517 
8518                 /* Clear the additional flag.  */
8519                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_AUTHORIY_ANSWER));
8520             }
8521         }
8522 
8523         /* Clear the answer flag.  */
8524         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8525     }
8526 
8527     if (!question_count &&
8528         !answer_count &&
8529         !authority_count &&
8530         !additional_count)
8531     {
8532 
8533         /* Release the packet.  */
8534         nx_packet_release(packet_ptr);
8535         return;
8536     }
8537 
8538     /* Update the question count in header.  */
8539     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8540 
8541     /* Update the answer count in header.  */
8542     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8543     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8544     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8545 
8546     /* Send the mDNS packet.  */
8547     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8548 
8549     /* Resend the packet.  */
8550     if (resend_flag)
8551         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_PROBING_SEND_EVENT, TX_OR);
8552 }
8553 
8554 
8555 /**************************************************************************/
8556 /*                                                                        */
8557 /*  FUNCTION                                               RELEASE        */
8558 /*                                                                        */
8559 /*    _nx_mdns_announcing_send                            PORTABLE C      */
8560 /*                                                           6.1          */
8561 /*  AUTHOR                                                                */
8562 /*                                                                        */
8563 /*    Yuxin Zhou, Microsoft Corporation                                   */
8564 /*                                                                        */
8565 /*  DESCRIPTION                                                           */
8566 /*                                                                        */
8567 /*    This function sends mDNS announcing message.                        */
8568 /*                                                                        */
8569 /*  INPUT                                                                 */
8570 /*                                                                        */
8571 /*    mdns_ptr                              Pointer to mDNS instance      */
8572 /*                                                                        */
8573 /*  OUTPUT                                                                */
8574 /*                                                                        */
8575 /*    status                                Completion status             */
8576 /*                                                                        */
8577 /*  CALLS                                                                 */
8578 /*                                                                        */
8579 /*                                                                        */
8580 /*  CALLED BY                                                             */
8581 /*                                                                        */
8582 /*                                                                        */
8583 /*  RELEASE HISTORY                                                       */
8584 /*                                                                        */
8585 /*    DATE              NAME                      DESCRIPTION             */
8586 /*                                                                        */
8587 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8588 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8589 /*                                            resulting in version 6.1    */
8590 /*                                                                        */
8591 /**************************************************************************/
_nx_mdns_announcing_send(NX_MDNS * mdns_ptr,UINT interface_index)8592 static VOID    _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8593 {
8594 
8595 UINT                status;
8596 NX_PACKET           *packet_ptr;
8597 NX_PACKET           *new_packet_ptr;
8598 ULONG               *head;
8599 NX_MDNS_RR          *p;
8600 USHORT              question_count = 0;
8601 USHORT              answer_count = 0;
8602 USHORT              authority_count = 0;
8603 USHORT              additional_count = 0;
8604 UINT                i;
8605 UCHAR               resend_flag = NX_FALSE;
8606 
8607 
8608     /* Create the mdns packet and add the mDNS header.  */
8609     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8610 
8611     /* Check for errors. */
8612     if (status != NX_SUCCESS)
8613     {
8614         return;
8615     }
8616 
8617     /* Set the head pointer. */
8618     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8619 
8620     /* Add the answer resource record.  */
8621     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8622     {
8623 
8624         /* Check the interface index.  */
8625         if (p -> nx_mdns_rr_interface_index != interface_index)
8626             continue;
8627 
8628         if(p -> nx_mdns_rr_send_flag == 0)
8629             continue;
8630 
8631         /* Check valid state. */
8632         if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) ||
8633               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8634               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID))))
8635             continue;
8636 
8637         /* Add the resource record into packet.  */
8638         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8639 
8640         if (status)
8641         {
8642             resend_flag = NX_TRUE;
8643         }
8644         else
8645         {
8646 
8647             /* Update the retransmit count.  */
8648             p -> nx_mdns_rr_retransmit_count --;
8649 
8650             /* Update the count.  */
8651             answer_count++;
8652 
8653             /* Clear the flag.  */
8654             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8655         }
8656     }
8657 
8658     if (!question_count &&
8659         !answer_count &&
8660         !authority_count &&
8661         !additional_count)
8662     {
8663 
8664         /* Release the packet.  */
8665         nx_packet_release(packet_ptr);
8666         return;
8667     }
8668 
8669     /* Update the question count in header.  */
8670     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8671 
8672     /* Update the answer count in header.  */
8673     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8674     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8675     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8676 
8677     /* If the interval time is 0, repeat advertise.  */
8678     if (!mdns_ptr -> nx_mdns_announcing_retrans_interval)
8679     {
8680         for (i = 1; i < mdns_ptr -> nx_mdns_announcing_count; i ++)
8681         {
8682 
8683             /* Allocate new packet.  */
8684             status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
8685 
8686             /* Check for errors. */
8687             if (status)
8688             {
8689                 break;
8690             }
8691 
8692             /* Send the mDNS packet.  */
8693             _nx_mdns_packet_send(mdns_ptr, new_packet_ptr, interface_index);
8694         }
8695     }
8696 
8697     /* Send the mDNS packet.  */
8698     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8699 
8700     /* Resend the packet.  */
8701     if (resend_flag)
8702         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_ANNOUNCING_SEND_EVENT, TX_OR);
8703 
8704     return;
8705 }
8706 
8707 
8708 /**************************************************************************/
8709 /*                                                                        */
8710 /*  FUNCTION                                               RELEASE        */
8711 /*                                                                        */
8712 /*    _nx_mdns_response_send                              PORTABLE C      */
8713 /*                                                           6.1          */
8714 /*  AUTHOR                                                                */
8715 /*                                                                        */
8716 /*    Yuxin Zhou, Microsoft Corporation                                   */
8717 /*                                                                        */
8718 /*  DESCRIPTION                                                           */
8719 /*                                                                        */
8720 /*    This function sends mDNS response.                                  */
8721 /*                                                                        */
8722 /*  INPUT                                                                 */
8723 /*                                                                        */
8724 /*    mdns_ptr                              Pointer to mDNS instance      */
8725 /*                                                                        */
8726 /*  OUTPUT                                                                */
8727 /*                                                                        */
8728 /*    none                                                                */
8729 /*                                                                        */
8730 /*  CALLS                                                                 */
8731 /*                                                                        */
8732 /*                                                                        */
8733 /*  CALLED BY                                                             */
8734 /*                                                                        */
8735 /*                                                                        */
8736 /*  RELEASE HISTORY                                                       */
8737 /*                                                                        */
8738 /*    DATE              NAME                      DESCRIPTION             */
8739 /*                                                                        */
8740 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8741 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8742 /*                                            resulting in version 6.1    */
8743 /*                                                                        */
8744 /**************************************************************************/
_nx_mdns_response_send(NX_MDNS * mdns_ptr,UINT interface_index)8745 static VOID    _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index)
8746 {
8747 
8748 UINT                status;
8749 NX_PACKET           *packet_ptr;
8750 ULONG               *head;
8751 NX_MDNS_RR          *p;
8752 USHORT              question_count = 0;
8753 USHORT              answer_count = 0;
8754 USHORT              authority_count = 0;
8755 USHORT              additional_count = 0;
8756 UCHAR               resend_flag = NX_FALSE;
8757 
8758 
8759     /* Create the mdns packet and add the mDNS header.  */
8760     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8761 
8762     /* Check for errors. */
8763     if (status != NX_SUCCESS)
8764     {
8765         return;
8766     }
8767 
8768     /* Set the head pointer. */
8769     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8770 
8771     /* Add the answer resource record.  */
8772     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8773     {
8774 
8775         /* Check the interface index.  */
8776         if (p -> nx_mdns_rr_interface_index != interface_index)
8777             continue;
8778 
8779         if(p -> nx_mdns_rr_send_flag == 0)
8780             continue;
8781 
8782         /* Check valid state. */
8783         if ((p -> nx_mdns_rr_timer_count != 0) ||
8784              !((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8785                (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)))
8786             continue;
8787 
8788         /* Add the resource record into packet.  */
8789         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8790 
8791         if (status)
8792         {
8793             resend_flag = NX_TRUE;
8794         }
8795         else
8796         {
8797 
8798             /* Set the answer flag to skip the resource record which has been added in answer section when find the additional records.  */
8799             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ANSWER;
8800 
8801             /* When including a DNS-SD Service Instance Enumeration or Selective Instance Enumeration PTR record in a response packet,
8802                the server/responder SHOULD include the folowing additional records, SRV,TXT, A and AAAA.RFC3763, Section12.1, Page30.  */
8803             _nx_mdns_additional_resource_record_find(mdns_ptr, p);
8804 
8805             /* Update the count.  */
8806             answer_count++;
8807 
8808             /* Clear the flag.  */
8809             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8810         }
8811     }
8812 
8813     /* Add the additional answer resource record.  */
8814     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8815     {
8816 
8817         /* Check the interface index.  */
8818         if (p -> nx_mdns_rr_interface_index != interface_index)
8819             continue;
8820 
8821         /* Check whether set the resource record send flag. */
8822         if ((p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ADDITIONAL) &&
8823             ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8824              (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)))
8825         {
8826 
8827             /* Add the resource record into packet.  */
8828             status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8829             if (status)
8830             {
8831                 resend_flag = NX_TRUE;
8832             }
8833             else
8834             {
8835 
8836                 /* Update the additional count.  */
8837                 additional_count++;
8838 
8839                 /* Clear the additional flag.  */
8840                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ADDITIONAL));
8841             }
8842         }
8843 
8844         /* Clear the answer flag.  */
8845         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8846     }
8847 
8848     if (!question_count &&
8849         !answer_count &&
8850         !authority_count &&
8851         !additional_count)
8852     {
8853 
8854         /* Release the packet.  */
8855         nx_packet_release(packet_ptr);
8856         return;
8857     }
8858 
8859     /* Update the question count in header.  */
8860     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8861 
8862     /* Update the answer count in header.  */
8863     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8864     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8865     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8866 
8867     /* Send the mDNS packet.  */
8868     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8869 
8870     /* Resend the packet.  */
8871     if (resend_flag)
8872         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_RESPONSE_SEND_EVENT, TX_OR);
8873 }
8874 #endif /* NX_MDNS_DISABLE_SERVER */
8875 
8876 
8877 #ifndef NX_MDNS_DISABLE_CLIENT
8878 /**************************************************************************/
8879 /*                                                                        */
8880 /*  FUNCTION                                               RELEASE        */
8881 /*                                                                        */
8882 /*    _nx_mdns_query_send                                 PORTABLE C      */
8883 /*                                                           6.1          */
8884 /*  AUTHOR                                                                */
8885 /*                                                                        */
8886 /*    Yuxin Zhou, Microsoft Corporation                                   */
8887 /*                                                                        */
8888 /*  DESCRIPTION                                                           */
8889 /*                                                                        */
8890 /*    This function sends mDNS query message.                             */
8891 /*                                                                        */
8892 /*  INPUT                                                                 */
8893 /*                                                                        */
8894 /*    mdns_ptr                              Pointer to mDNS instance      */
8895 /*                                                                        */
8896 /*  OUTPUT                                                                */
8897 /*                                                                        */
8898 /*    none                                                                */
8899 /*                                                                        */
8900 /*  CALLS                                                                 */
8901 /*                                                                        */
8902 /*                                                                        */
8903 /*  CALLED BY                                                             */
8904 /*                                                                        */
8905 /*                                                                        */
8906 /*  RELEASE HISTORY                                                       */
8907 /*                                                                        */
8908 /*    DATE              NAME                      DESCRIPTION             */
8909 /*                                                                        */
8910 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8911 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8912 /*                                            resulting in version 6.1    */
8913 /*                                                                        */
8914 /**************************************************************************/
_nx_mdns_query_send(NX_MDNS * mdns_ptr,UINT interface_index)8915 static VOID    _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index)
8916 {
8917 
8918 UINT                status;
8919 NX_PACKET           *packet_ptr;
8920 ULONG               *head;
8921 NX_MDNS_RR          *p;
8922 USHORT              question_count = 0;
8923 USHORT              answer_count = 0;
8924 USHORT              authority_count = 0;
8925 USHORT              additional_count = 0;
8926 UCHAR               resend_flag = NX_FALSE;
8927 USHORT              tc_bit;
8928 UCHAR               more_known_answer = NX_FALSE;
8929 UINT                i;
8930 
8931 
8932     /* Create the mdns packet and add the mDNS header.  */
8933     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8934 
8935     /* Check for errors. */
8936     if (status != NX_SUCCESS)
8937     {
8938         return;
8939     }
8940 
8941     /* Set the head pointer. */
8942     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8943 
8944     /* Add the query resource record.  */
8945     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8946     {
8947 
8948         /* Check the interface index.  */
8949         if (p -> nx_mdns_rr_interface_index != interface_index)
8950             continue;
8951 
8952         if(p -> nx_mdns_rr_send_flag == 0)
8953             continue;
8954 
8955         /* Check valid state. */
8956         if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY) ||
8957               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING))))
8958             continue;
8959 
8960         /* Add the resource record into packet.  */
8961         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_QUERY);
8962 
8963         if (status)
8964         {
8965             resend_flag = NX_TRUE;
8966         }
8967         else
8968         {
8969 
8970             /* Update the retransmit count for UPDATING state.  */
8971             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
8972                 p -> nx_mdns_rr_retransmit_count --;
8973 
8974             /* Update the count.  */
8975             question_count++;
8976 
8977             /* Find the known answer resource records.  */
8978             _nx_mdns_known_answer_find(mdns_ptr, p);
8979 
8980             /* Clear the flag.  */
8981             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8982         }
8983     }
8984 
8985     /* Add the known answer resource record.  */
8986     for (i = 0; i < 2; i++)
8987     {
8988         if (i == 0)
8989         {
8990 #ifndef NX_MDNS_DISABLE_SERVER
8991             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8992 #else
8993             continue;
8994 #endif /* NX_MDNS_DISABLE_SERVER  */
8995         }
8996         else
8997         {
8998             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8999         }
9000 
9001         /* Add the peer resource code as known answer for query.  */
9002         for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
9003         {
9004 
9005             /* Check the interface index.  */
9006             if (p -> nx_mdns_rr_interface_index != interface_index)
9007                 continue;
9008 
9009             /* Check whether set the resource record send flag. */
9010             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
9011                 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_KNOWN_ANSWER))
9012             {
9013 
9014                 /* Add the resource record into packet.  */
9015                 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_QUERY);
9016                 if (status)
9017                 {
9018                     more_known_answer = NX_TRUE;
9019                     resend_flag = NX_TRUE;
9020                 }
9021                 else
9022                 {
9023                     /* Update the count.  */
9024                     answer_count ++;
9025 
9026                     /* Clear the additional flag.  */
9027                     p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_KNOWN_ANSWER));
9028                 }
9029             }
9030 
9031             /* Clear the answer flag.  */
9032             p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
9033         }
9034     }
9035 
9036     if (!question_count &&
9037         !answer_count &&
9038         !authority_count &&
9039         !additional_count)
9040     {
9041 
9042         /* Release the packet.  */
9043         nx_packet_release(packet_ptr);
9044         return;
9045     }
9046 
9047     /* Set the TC bit.  */
9048     if (more_known_answer)
9049     {
9050         tc_bit = NX_MDNS_TC_FLAG;
9051          *(USHORT *)(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) |= NX_CHANGE_USHORT_ENDIAN(tc_bit);
9052     }
9053 
9054     /* Update the question count in header.  */
9055     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
9056 
9057     /* Update the answer count in header.  */
9058     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
9059     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
9060     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
9061 
9062     /* Send the mDNS packet.  */
9063     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
9064 
9065     /* Resend the packet.  */
9066     if (resend_flag)
9067         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_QUERY_SEND_EVENT, TX_OR);
9068 }
9069 #endif /* NX_MDNS_DISABLE_CLIENT  */
9070 
9071 
9072 /**************************************************************************/
9073 /*                                                                        */
9074 /*  FUNCTION                                               RELEASE        */
9075 /*                                                                        */
9076 /*    _nx_mdns_packet_create                              PORTABLE C      */
9077 /*                                                           6.1          */
9078 /*  AUTHOR                                                                */
9079 /*                                                                        */
9080 /*    Yuxin Zhou, Microsoft Corporation                                   */
9081 /*                                                                        */
9082 /*  DESCRIPTION                                                           */
9083 /*                                                                        */
9084 /*    This function creates the mDNS packet and add the mDNS header data. */
9085 /*                                                                        */
9086 /*  INPUT                                                                 */
9087 /*                                                                        */
9088 /*    mdns_ptr                              Pointer to mDNS instance      */
9089 /*    packet_ptr                            Pointer to mDNS packet        */
9090 /*    is_query                              Query flag                    */
9091 /*                                                                        */
9092 /*  OUTPUT                                                                */
9093 /*                                                                        */
9094 /*    status                                Completion status             */
9095 /*                                                                        */
9096 /*  CALLS                                                                 */
9097 /*                                                                        */
9098 /*    nx_packet_allocate                    Allocate the mDNS packet      */
9099 /*    nx_packet_release                     Release the mDNS packet       */
9100 /*    _nx_mdns_short_to_network_convert     Add the data into the packet  */
9101 /*                                                                        */
9102 /*  CALLED BY                                                             */
9103 /*                                                                        */
9104 /*    _nx_mdns_announcing_send              Send announcing message       */
9105 /*    _nx_mdns_probing_send                 Send probing message          */
9106 /*    _nx_mdns_query_send                   Send query message            */
9107 /*    _nx_mdns_response_send                Send response message         */
9108 /*                                                                        */
9109 /*  RELEASE HISTORY                                                       */
9110 /*                                                                        */
9111 /*    DATE              NAME                      DESCRIPTION             */
9112 /*                                                                        */
9113 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9114 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9115 /*                                            resulting in version 6.1    */
9116 /*                                                                        */
9117 /**************************************************************************/
_nx_mdns_packet_create(NX_MDNS * mdns_ptr,NX_PACKET ** packet_ptr,UCHAR is_query)9118 static UINT    _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR is_query)
9119 {
9120 
9121 UINT        status;
9122 USHORT      flags;
9123 
9124 
9125     /* Allocate the mDNS packet.  */
9126 #ifdef NX_MDNS_ENABLE_IPV6
9127     status =  nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv6_UDP_PACKET, NX_NO_WAIT);
9128 #else
9129     status =  nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
9130 #endif /* NX_MDNS_ENABLE_IPV6  */
9131 
9132     /* Check for errors. */
9133     if (status)
9134     {
9135 
9136         /* Return error.  */
9137         return(status);
9138     }
9139 
9140     /* Check if there is enough room to fill with mDNS header.  */
9141     if ((UINT)((*packet_ptr) -> nx_packet_data_end - (*packet_ptr) -> nx_packet_append_ptr) < NX_MDNS_QDSECT_OFFSET)
9142     {
9143 
9144         /* Release the packet.  */
9145         nx_packet_release(*packet_ptr);
9146         return(NX_MDNS_PACKET_ERROR);
9147     }
9148 
9149     /* Add the mDNS header.  */
9150 
9151     /* Set the transaction ID.  */
9152     *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_ID_OFFSET) = 0;
9153 
9154     /* Set the flags and Command.  */
9155     if (is_query == NX_TRUE)
9156     {
9157         flags = NX_MDNS_QUERY_FLAG;
9158     }
9159     else
9160     {
9161         flags = (NX_MDNS_RESPONSE_FLAG | NX_MDNS_AA_FLAG);
9162     }
9163 
9164     /* Adjust for endianness. */
9165     NX_CHANGE_USHORT_ENDIAN(flags);
9166 
9167     /* Set the flags and Command.  */
9168     *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) = flags;
9169 
9170     /* Initialize counts to 0.  */
9171     *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET) = 0;
9172     *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET) = 0;
9173 
9174     /* Set the pointer.  */
9175     (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
9176     (*packet_ptr) -> nx_packet_length = NX_MDNS_QDSECT_OFFSET;
9177 
9178     return(NX_MDNS_SUCCESS);
9179 }
9180 
9181 
9182 /**************************************************************************/
9183 /*                                                                        */
9184 /*  FUNCTION                                               RELEASE        */
9185 /*                                                                        */
9186 /*    _nx_mdns_packet_send                                PORTABLE C      */
9187 /*                                                           6.1          */
9188 /*  AUTHOR                                                                */
9189 /*                                                                        */
9190 /*    Yuxin Zhou, Microsoft Corporation                                   */
9191 /*                                                                        */
9192 /*  DESCRIPTION                                                           */
9193 /*                                                                        */
9194 /*    This function sends the mDNS packet.                                */
9195 /*                                                                        */
9196 /*  INPUT                                                                 */
9197 /*                                                                        */
9198 /*    mdns_ptr                              Pointer to mDNS instance      */
9199 /*    packet_ptr                            Pointer to mDNS packet        */
9200 /*                                                                        */
9201 /*  OUTPUT                                                                */
9202 /*                                                                        */
9203 /*    status                                Completion status             */
9204 /*                                                                        */
9205 /*  CALLS                                                                 */
9206 /*                                                                        */
9207 /*    nx_packet_copy                        Copy the mDNS packet          */
9208 /*    nx_packet_release                     Release the mDNS packet       */
9209 /*    nx_udp_socket_send                    Send the udp packet           */
9210 /*    nxd_udp_socket_send                   Send the udp packet           */
9211 /*                                                                        */
9212 /*  CALLED BY                                                             */
9213 /*                                                                        */
9214 /*    _nx_mdns_announcing_send              Send announcing message       */
9215 /*    _nx_mdns_probing_send                 Send probing message          */
9216 /*    _nx_mdns_query_send                   Send query message            */
9217 /*    _nx_mdns_response_send                Send response message         */
9218 /*                                                                        */
9219 /*  RELEASE HISTORY                                                       */
9220 /*                                                                        */
9221 /*    DATE              NAME                      DESCRIPTION             */
9222 /*                                                                        */
9223 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9224 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9225 /*                                            resulting in version 6.1    */
9226 /*                                                                        */
9227 /**************************************************************************/
_nx_mdns_packet_send(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)9228 static VOID    _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
9229 {
9230 
9231 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
9232 UINT                status;
9233 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
9234 #ifdef NX_MDNS_ENABLE_IPV6
9235 UINT                ipv6_packet = NX_FALSE;
9236 NX_PACKET           *new_packet_ptr;
9237 UINT                address_index = mdns_ptr -> nx_mdns_ipv6_address_index[interface_index];
9238 #endif /*  NX_MDNS_ENABLE_IPV6  */
9239 
9240 
9241 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
9242     NX_PARAMETER_NOT_USED(mdns_ptr);
9243     NX_PARAMETER_NOT_USED(interface_index);
9244 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6  */
9245 
9246 #ifdef NX_MDNS_ENABLE_IPV6
9247     if (address_index != 0xFFFFFFFF)
9248     {
9249 
9250         /* Allocate new IPv6 packet.  */
9251         status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
9252 
9253         /* Check for errors. */
9254         if (!status)
9255         {
9256             ipv6_packet = NX_TRUE;
9257         }
9258     }
9259 #endif /* NX_MDNS_ENABLE_IPV6  */
9260 
9261 #ifndef NX_DISABLE_IPV4
9262     /* Send the IPv4 mDNS message.  */
9263     status =  nx_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, packet_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, interface_index);
9264 
9265     /* If an error is detected, the packet was not sent and we have to release the packet. */
9266     if (status != NX_SUCCESS)
9267     {
9268 
9269         /* Release the packet.  */
9270         nx_packet_release(packet_ptr);
9271     }
9272 #else
9273 
9274     /* Release the packet.  */
9275     nx_packet_release(packet_ptr);
9276 #endif /* NX_DISABLE_IPV4  */
9277 
9278 #ifdef NX_MDNS_ENABLE_IPV6
9279 
9280     /* Check if send IPv6 packet.  */
9281     if (ipv6_packet == NX_TRUE)
9282     {
9283 
9284         /* Send the IPv6 mDNS message.  */
9285         status =  nxd_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, new_packet_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, address_index);
9286 
9287         /* If an error is detected, the packet was not sent and we have to release the packet. */
9288         if (status != NX_SUCCESS)
9289         {
9290 
9291             /* Release the packet.  */
9292             nx_packet_release(new_packet_ptr);
9293         }
9294     }
9295 #endif /* NX_MDNS_ENABLE_IPV6  */
9296 }
9297 
9298 
9299 /**************************************************************************/
9300 /*                                                                        */
9301 /*  FUNCTION                                               RELEASE        */
9302 /*                                                                        */
9303 /*    _nx_mdns_packet_rr_add                              PORTABLE C      */
9304 /*                                                           6.1          */
9305 /*  AUTHOR                                                                */
9306 /*                                                                        */
9307 /*    Yuxin Zhou, Microsoft Corporation                                   */
9308 /*                                                                        */
9309 /*  DESCRIPTION                                                           */
9310 /*                                                                        */
9311 /*    This function adds the mDNS resource record into the packet.        */
9312 /*                                                                        */
9313 /*  INPUT                                                                 */
9314 /*                                                                        */
9315 /*    mdns_ptr                              Pointer to mDNS instance      */
9316 /*    packet_ptr                            Pointer to mDNS packet        */
9317 /*    rr                                    Pointer to mDNS record        */
9318 /*    op                                    RR adding Operation           */
9319 /*    packet_type                           Packet type                   */
9320 /*                                                                        */
9321 /*  OUTPUT                                                                */
9322 /*                                                                        */
9323 /*    status                                Completion status             */
9324 /*                                                                        */
9325 /*  CALLS                                                                 */
9326 /*                                                                        */
9327 /*    _nx_mdns_name_string_encode           Encode the name string        */
9328 /*    _nx_mdns_short_to_network_convert     Convert and add the data      */
9329 /*    _nx_mdns_txt_string_encode            Encode the txt string         */
9330 /*                                                                        */
9331 /*  CALLED BY                                                             */
9332 /*                                                                        */
9333 /*    _nx_mdns_announcing_send              Send announcing message       */
9334 /*    _nx_mdns_probing_send                 Send probing message          */
9335 /*    _nx_mdns_query_send                   Send query message            */
9336 /*    _nx_mdns_response_send                Send response message         */
9337 /*                                                                        */
9338 /*  RELEASE HISTORY                                                       */
9339 /*                                                                        */
9340 /*    DATE              NAME                      DESCRIPTION             */
9341 /*                                                                        */
9342 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9343 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9344 /*                                            verified memcpy use cases,  */
9345 /*                                            resulting in version 6.1    */
9346 /*                                                                        */
9347 /**************************************************************************/
_nx_mdns_packet_rr_add(NX_PACKET * packet_ptr,NX_MDNS_RR * rr,UINT op,UINT packet_type)9348 static UINT    _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type)
9349 {
9350 
9351 USHORT      size = 0;
9352 USHORT      index = 0;
9353 USHORT      rr_size = 0;
9354 USHORT      rdata_length_index = 0;
9355 UCHAR       *data_ptr = packet_ptr -> nx_packet_append_ptr;
9356 UINT        rr_name_length;
9357 
9358 
9359     /* Check string length.  */
9360     if (_nx_utility_string_length_check((CHAR *)rr -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9361     {
9362         return (NX_MDNS_DATA_SIZE_ERROR);
9363     }
9364 
9365     /* Check whether set the resource record send flag. */
9366     if(op ==  NX_MDNS_PACKET_ADD_RR_QUESTION)
9367     {
9368 
9369         /* The name size is should add the '.' and '\0',  Calcuate the resource record size. QNAME, QTYPE, QCLASS.  */
9370         rr_size = (USHORT)(rr_name_length + 2 + 4);
9371 
9372         if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9373         {
9374             return(NX_MDNS_PACKET_ERROR);
9375         }
9376 
9377         /* Encode and add the name.  */
9378         size = (USHORT)_nx_mdns_name_string_encode(data_ptr, rr -> nx_mdns_rr_name);
9379 
9380         /* Updat the index.  */
9381         index = (USHORT)(index + size);
9382 
9383         /* Add the type.  */
9384         if(packet_type == NX_MDNS_PACKET_PROBING)
9385         {
9386             _nx_mdns_short_to_network_convert(data_ptr + index, NX_MDNS_RR_TYPE_ALL);
9387         }
9388         else
9389         {
9390             _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9391         }
9392         index = (USHORT)(index + 2);
9393 
9394         /* Add the class.  */
9395         _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9396         index = (USHORT)(index + 2);
9397     }
9398 
9399     /* Check whether set the resource record send flag. */
9400     else
9401     {
9402 
9403         /* Calcuate the resource record size. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
9404         rr_size = (USHORT)(rr_name_length + 2 + 10 + rr -> nx_mdns_rr_rdata_length);
9405 
9406         if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9407         {
9408             return(NX_MDNS_PACKET_ERROR);
9409         }
9410 
9411         /* Encode and add the name.  */
9412         size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_name);
9413 
9414         /* Updat the index.  */
9415         index = (USHORT)(index + size);
9416 
9417         /* Add the type and class.  */
9418         _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9419         index = (USHORT)(index + 2);
9420 
9421         /* Add the class.  */
9422         if ((!(rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)) &&
9423             (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE))
9424         {
9425             _nx_mdns_short_to_network_convert(data_ptr + index, ((rr -> nx_mdns_rr_class) | NX_MDNS_RR_CLASS_TOP_BIT));
9426         }
9427         else
9428         {
9429 
9430             _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9431         }
9432         index = (USHORT)(index + 2);
9433 
9434         /* Add the ttl.  */
9435         /* Check the resource record owner.  */
9436         if (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)
9437         {
9438             /* Add the remaining ttl of peer resource reocrd.  */
9439             _nx_mdns_long_to_network_convert(data_ptr + index, (rr -> nx_mdns_rr_remaining_ticks / NX_IP_PERIODIC_RATE));
9440         }
9441         else
9442         {
9443             if (rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE)
9444             {
9445                 _nx_mdns_long_to_network_convert(data_ptr + index, 0);
9446             }
9447             else
9448             {
9449                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_ttl);
9450             }
9451         }
9452         index = (USHORT)(index + 4);
9453 
9454         /* Compare the RDATA. */
9455         switch (rr -> nx_mdns_rr_type)
9456         {
9457 
9458             case NX_MDNS_RR_TYPE_A:
9459             {
9460 
9461                 /* Add the rdata length.  */
9462                 _nx_mdns_short_to_network_convert(data_ptr + index, 4);
9463                 index = (USHORT)(index + 2);
9464 
9465                 /* Add the rdata.  */
9466                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address);
9467                 index = (USHORT)(index + 4);
9468 
9469                 break;
9470             }
9471             case NX_MDNS_RR_TYPE_AAAA:
9472             {
9473 
9474                 /* Add the rdata length.  */
9475                 _nx_mdns_short_to_network_convert(data_ptr + index, 16);
9476                 index = (USHORT)(index + 2);
9477 
9478                 /* Add the rdata.  */
9479                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0]);
9480                 index = (USHORT)(index + 4);
9481                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1]);
9482                 index = (USHORT)(index + 4);
9483                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2]);
9484                 index = (USHORT)(index + 4);
9485                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3]);
9486                 index = (USHORT)(index + 4);
9487 
9488                 break;
9489             }
9490             case NX_MDNS_RR_TYPE_PTR:
9491             {
9492 
9493                 /* Record the rdata length index then skip the rdata length.  */
9494                 rdata_length_index = index;
9495                 index = (USHORT)(index + 2);
9496 
9497                 /* Encode and add the name.  */
9498                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name);
9499                 index = (USHORT)(index + size);
9500 
9501                 /* Add the rdata length.  */
9502                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9503 
9504                 break;
9505             }
9506             case NX_MDNS_RR_TYPE_SRV:
9507             {
9508 
9509                 /* Record the rdata length index then skip the rdata length.  */
9510                 rdata_length_index = index;
9511                 index = (USHORT)(index + 2);
9512 
9513                 /* Add the prority.  */
9514                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority);
9515                 index = (USHORT)(index + 2);
9516 
9517                 /* Add the weights.  */
9518                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights);
9519                 index = (USHORT)(index + 2);
9520 
9521                 /* Add the port.  */
9522                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port);
9523                 index = (USHORT)(index + 2);
9524 
9525                 /* Encode and add the name.  */
9526                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target);
9527                 index = (USHORT)(index + size);
9528 
9529                 /* Add the rdata length.  */
9530                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 6));
9531 
9532                 break;
9533             }
9534             case NX_MDNS_RR_TYPE_TXT:
9535             {
9536 
9537                 /* Record the rdata length index then skip the rdata length.  */
9538                 rdata_length_index = index;
9539                 index = (USHORT)(index + 2);
9540 
9541                 if (rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
9542                 {
9543 
9544                     /* Encode and add the text.  */
9545                     size = (USHORT)_nx_mdns_txt_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data);
9546                 }
9547                 else
9548                 {
9549 
9550                     /* Encode the null.  */
9551                     *(data_ptr + index) = 0;
9552                     size = 1;
9553                 }
9554                 index = (USHORT)(index + size);
9555 
9556                 /* Add the rdata length.  */
9557                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9558 
9559                 break;
9560             }
9561 
9562 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
9563             case NX_MDNS_RR_TYPE_CNAME:
9564             {
9565 
9566                 /* Record the rdata length index then skip the rdata length.  */
9567                 rdata_length_index = index;
9568                 index = (USHORT)(index + 2);
9569 
9570                 /* Encode and add the name.  */
9571                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_cname.nx_mdns_rr_cname_name);
9572                 index = (USHORT)(index + size);
9573 
9574                 /* Add the rdata length.  */
9575                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9576 
9577                 break;
9578             }
9579             case NX_MDNS_RR_TYPE_NS:
9580             {
9581 
9582                 /* Record the rdata length index then skip the rdata length.  */
9583                 rdata_length_index = index;
9584                 index = (USHORT)(index + 2);
9585 
9586                 /* Encode and add the name.  */
9587                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ns.nx_mdns_rr_ns_name);
9588                 index = (USHORT)(index + size);
9589 
9590                 /* Add the rdata length.  */
9591                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9592 
9593                 break;
9594             }
9595             case NX_MDNS_RR_TYPE_MX:
9596             {
9597 
9598                 /* Record the rdata length index then skip the rdata length.  */
9599                 rdata_length_index = index;
9600                 index = (USHORT)(index + 2);
9601 
9602                 /* Add the preference.  */
9603                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference);
9604                 index = (USHORT)(index + 2);
9605 
9606                 /* Encode and add the name.  */
9607                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name);
9608                 index = (USHORT)(index + size);
9609 
9610                 /* Add the rdata length.  */
9611                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2));
9612 
9613                 break;
9614             }
9615 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
9616 
9617 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
9618             case NX_MDNS_RR_TYPE_NSEC:
9619             {
9620 
9621                 /* Record the rdata length index then skip the rdata length.  */
9622                 rdata_length_index = index;
9623                 index = (USHORT)(index + 2);
9624 
9625                 /* Encode and add the next domain name.  */
9626                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain);
9627                 index = (USHORT)(index + size);
9628 
9629                 /* Add the window block.  */
9630                 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block;
9631                 index++;
9632 
9633                 /* Add the bitmap length.  */
9634                 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length;
9635                 index++;
9636 
9637                 /* Add the type bit maps.  */
9638                 memcpy(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length); /* Use case of memcpy is verified. */
9639                 index = (USHORT)(index + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length);
9640 
9641                 /* Add the rdata length.  */
9642                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2 + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length));
9643 
9644                 break;
9645             }
9646 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
9647         }
9648     }
9649 
9650     /* Update the append pointer and packet length.  */
9651     packet_ptr -> nx_packet_append_ptr += index;
9652     packet_ptr -> nx_packet_length += index;
9653 
9654     return(NX_MDNS_SUCCESS);
9655 }
9656 
9657 
9658 /**************************************************************************/
9659 /*                                                                        */
9660 /*  FUNCTION                                               RELEASE        */
9661 /*                                                                        */
9662 /*    _nx_mdns_packet_rr_set                              PORTABLE C      */
9663 /*                                                           6.1.11       */
9664 /*  AUTHOR                                                                */
9665 /*                                                                        */
9666 /*    Yuxin Zhou, Microsoft Corporation                                   */
9667 /*                                                                        */
9668 /*  DESCRIPTION                                                           */
9669 /*                                                                        */
9670 /*    This function sets the resource record info from packet.            */
9671 /*                                                                        */
9672 /*  INPUT                                                                 */
9673 /*                                                                        */
9674 /*    mdns_ptr                              Pointer to mDNS instance.     */
9675 /*    packet_ptr                            Pointer to the packet.        */
9676 /*    data_ptr                              Pointer to the data.          */
9677 /*    rr_ptr                                Pointer to the record         */
9678 /*    op                                    Operation:                    */
9679 /*                                            set question or set answer. */
9680 /*                                                                        */
9681 /*  OUTPUT                                                                */
9682 /*                                                                        */
9683 /*    status                                Completion status             */
9684 /*                                                                        */
9685 /*  CALLS                                                                 */
9686 /*                                                                        */
9687 /*    _nx_mdns_name_string_decode           Decode the name string        */
9688 /*    _nx_mdns_cache_add_string             Add the name string           */
9689 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
9690 /*                                                                        */
9691 /*  CALLED BY                                                             */
9692 /*                                                                        */
9693 /*    _nx_mdns_packet_process               Process mDNS packet           */
9694 /*                                                                        */
9695 /*  RELEASE HISTORY                                                       */
9696 /*                                                                        */
9697 /*    DATE              NAME                      DESCRIPTION             */
9698 /*                                                                        */
9699 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9700 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9701 /*                                            resulting in version 6.1    */
9702 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
9703 /*                                            buffer length verification, */
9704 /*                                            resulting in version 6.1.3  */
9705 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
9706 /*                                            packet length verification, */
9707 /*                                            resulting in version 6.1.4  */
9708 /*  04-25-2022     Yuxin Zhou               Modified comment(s), improved */
9709 /*                                            fixed the issue of timer,   */
9710 /*                                            resulting in version 6.1.11 */
9711 /*                                                                        */
9712 /**************************************************************************/
_nx_mdns_packet_rr_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op,UINT interface_index)9713 static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index)
9714 {
9715 
9716 UCHAR          *cache_ptr;
9717 UINT            cache_size;
9718 UINT            cache_type;
9719 USHORT          record_class;
9720 UINT            status;
9721 UINT            temp_string_length;
9722 
9723 
9724     /* Initialize.  */
9725     memset(rr_ptr, 0, sizeof(NX_MDNS_RR));
9726 
9727     /* Get cache type and size. */
9728     if ((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) ||
9729         (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER))
9730     {
9731         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
9732         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
9733         cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
9734     }
9735     else
9736     {
9737         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
9738         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
9739         cache_type = NX_MDNS_CACHE_TYPE_PEER;
9740     }
9741 
9742     /* Check cache pointer and cache size.  */
9743     if ((cache_ptr == NX_NULL) || (cache_size == 0))
9744     {
9745         return(NX_MDNS_ERROR);
9746     }
9747 
9748     /* Set the interface.  */
9749     rr_ptr -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
9750 
9751     /* Process the name string.  */
9752     if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9753                                     (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9754                                     packet_ptr -> nx_packet_length,
9755                                     temp_string_buffer, NX_MDNS_NAME_MAX))
9756     {
9757 
9758         /* Check string length.  */
9759         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9760         {
9761             return(NX_MDNS_DATA_SIZE_ERROR);
9762         }
9763 
9764          /* Add the string .  */
9765         if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
9766                                     (VOID **)(&rr_ptr -> nx_mdns_rr_name), NX_TRUE, NX_TRUE) != NX_MDNS_SUCCESS)
9767         {
9768             return(NX_MDNS_ERROR);
9769         }
9770     }
9771     else
9772     {
9773         return(NX_MDNS_ERROR);
9774     }
9775 
9776     /* Plus 4 for 2 bytes type and 2 bytes class. */
9777     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9778     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9779     {
9780         return(NX_MDNS_ERROR);
9781     }
9782 
9783     /* Set the resource record type. */
9784     rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9785 
9786     /* Get the resource record class.*/
9787     record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9788 
9789     /* Remote RR, set the RR owner flag.*/
9790     if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
9791         rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9792 
9793     /* Unique RR, Set the RR set flag.  */
9794     if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9795     {
9796         rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9797     }
9798 
9799     /* Check the operation and update the record class.  */
9800     if((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) || (op == NX_MDNS_RR_OP_PEER_SET_QUESTION))
9801     {
9802         rr_ptr -> nx_mdns_rr_class = record_class;
9803         return(NX_MDNS_SUCCESS);
9804     }
9805     else
9806     {
9807         rr_ptr -> nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9808     }
9809 
9810     /* Set the rdata information for answer record.  */
9811     status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, rr_ptr, op);
9812 
9813     /* Return success.  */
9814     return (status);
9815 }
9816 
9817 
9818 #ifndef NX_MDNS_DISABLE_CLIENT
9819 /**************************************************************************/
9820 /*                                                                        */
9821 /*  FUNCTION                                               RELEASE        */
9822 /*                                                                        */
9823 /*    _nx_mdns_packet_rr_process                          PORTABLE C      */
9824 /*                                                           6.1.11       */
9825 /*  AUTHOR                                                                */
9826 /*                                                                        */
9827 /*    Yuxin Zhou, Microsoft Corporation                                   */
9828 /*                                                                        */
9829 /*  DESCRIPTION                                                           */
9830 /*                                                                        */
9831 /*    This function processes the resource record of packet, and add the  */
9832 /*    record into peer cache.                                             */
9833 /*                                                                        */
9834 /*  INPUT                                                                 */
9835 /*                                                                        */
9836 /*    mdns_ptr                              Pointer to mDNS instance.     */
9837 /*    packet_ptr                            Pointer to the packet.        */
9838 /*    data_ptr                              Pointer to the data.          */
9839 /*    insert_ptr                            Pointer to the insert record  */
9840 /*    op                                    Operation: add answer, set    */
9841 /*                                            question or set answer.     */
9842 /*    cache_ptr                             The record buffer.            */
9843 /*                                                                        */
9844 /*  OUTPUT                                                                */
9845 /*                                                                        */
9846 /*    status                                Completion status             */
9847 /*                                                                        */
9848 /*  CALLS                                                                 */
9849 /*                                                                        */
9850 /*    _nx_mdns_name_string_decode           Decode the name string        */
9851 /*    _nx_mdns_cache_add_string             Add the name string           */
9852 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
9853 /*                                                                        */
9854 /*  CALLED BY                                                             */
9855 /*                                                                        */
9856 /*    _nx_mdns_packet_process               Process mDNS packet           */
9857 /*                                                                        */
9858 /*  RELEASE HISTORY                                                       */
9859 /*                                                                        */
9860 /*    DATE              NAME                      DESCRIPTION             */
9861 /*                                                                        */
9862 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9863 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9864 /*                                            verified memcpy use cases,  */
9865 /*                                            resulting in version 6.1    */
9866 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
9867 /*                                            buffer length verification, */
9868 /*                                            resulting in version 6.1.3  */
9869 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
9870 /*                                            packet length verification, */
9871 /*                                            resulting in version 6.1.4  */
9872 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
9873 /*                                            corrected the random value, */
9874 /*                                            fixed the issue of timer,   */
9875 /*                                            resulting in version 6.1.11 */
9876 /*                                                                        */
9877 /**************************************************************************/
_nx_mdns_packet_rr_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,UINT interface_index)9878 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index)
9879 {
9880 
9881 UINT            status;
9882 USHORT          record_class;
9883 UCHAR           is_present;
9884 NX_MDNS_RR      rr_ptr;
9885 NX_MDNS_RR     *insert_ptr;
9886 NX_MDNS_RR     *p;
9887 ULONG          *head;
9888 UCHAR          *service_name,*service_type,*service_domain;
9889 UINT            temp_string_length;
9890 UINT            rr_name_length;
9891 
9892 
9893     /* Check the peer cache.  */
9894     if ((mdns_ptr -> nx_mdns_peer_service_cache == NX_NULL) ||
9895         (mdns_ptr -> nx_mdns_peer_service_cache_size == 0))
9896     {
9897         return(NX_MDNS_ERROR);
9898     }
9899 
9900     /* Initialize.  */
9901     memset(&rr_ptr, 0, sizeof(NX_MDNS_RR));
9902 
9903     /* Process the name string.  */
9904     if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9905                                     (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9906                                     packet_ptr -> nx_packet_length,
9907                                     temp_string_buffer, NX_MDNS_NAME_MAX))
9908     {
9909 
9910         /* Check string length.  */
9911         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9912         {
9913             return(NX_MDNS_DATA_SIZE_ERROR);
9914         }
9915 
9916          /* Add the string .  */
9917         if(_nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_string_buffer, temp_string_length,
9918                                      (VOID **)(&rr_ptr.nx_mdns_rr_name), NX_FALSE, NX_TRUE))
9919         {
9920             return(NX_MDNS_ERROR);
9921         }
9922     }
9923     else
9924     {
9925         return(NX_MDNS_ERROR);
9926     }
9927 
9928     /* Plus 4 for 2 bytes type and 2 bytes class. */
9929     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9930     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9931     {
9932         return(NX_MDNS_ERROR);
9933     }
9934 
9935     /* Set the resource record type. */
9936     rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9937 
9938     /* Get the resource record class.*/
9939     record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9940 
9941     /* Set the resource record class.  */
9942     rr_ptr.nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9943 
9944     /* Remote RR, set the RR owner flag.*/
9945     rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9946 
9947     /* Unique RR, Set the RR set flag.  */
9948     if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9949     {
9950         rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9951     }
9952 
9953     /* Set the interface index.  */
9954     rr_ptr.nx_mdns_rr_interface_index = (UCHAR)interface_index;
9955 
9956     /* Set the rdata information for answer record.  */
9957     status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, &rr_ptr, NX_MDNS_RR_OP_PEER_ADD_ANSWER);
9958 
9959     /* Check status.  */
9960     if(status)
9961     {
9962 
9963         /* Delete the name strings. */
9964         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, rr_ptr.nx_mdns_rr_name, 0);
9965         return (NX_MDNS_ERROR);
9966     }
9967 
9968     /* Check if need to ignore this source reocrd.  */
9969     if ((mdns_ptr -> nx_mdns_service_ignore_mask) &&
9970         ((rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
9971          (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
9972          (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)))
9973     {
9974 
9975         /* Get the service.  */
9976         if (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
9977         {
9978 
9979             /* Check string length.  */
9980             if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9981             {
9982                 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
9983                 return(NX_MDNS_DATA_SIZE_ERROR);
9984             }
9985             memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9986         }
9987         else
9988         {
9989 
9990             /* Check string length.  */
9991             if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9992             {
9993                 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
9994                 return(NX_MDNS_DATA_SIZE_ERROR);
9995             }
9996             memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9997         }
9998 
9999         /* Resolve the service type.  */
10000         if (_nx_mdns_service_name_resolve(temp_string_buffer, &service_name, &service_type, &service_domain))
10001         {
10002             _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
10003             return (status);
10004         }
10005 
10006         /* Check if this service type should be ignored.  */
10007         if (_nx_mdns_service_mask_match(mdns_ptr, service_type, mdns_ptr -> nx_mdns_service_ignore_mask) == NX_MDNS_SUCCESS)
10008         {
10009             _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
10010             return (NX_MDNS_ERROR);
10011         }
10012     }
10013 
10014     /* Add the resource record into remote buffer.  */
10015     if (_nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr, &insert_ptr, &is_present))
10016     {
10017 
10018         /* Delete the name strings. */
10019         _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10020         return (NX_MDNS_ERROR);
10021     }
10022 
10023     /* Check the ttl.  */
10024     if (insert_ptr -> nx_mdns_rr_ttl)
10025     {
10026 
10027         /* Step1. Process answer record.  */
10028         /* Update the state.  */
10029         insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
10030 
10031         /* Update the timer count. The querier should not include records in the Known-Answer list whose remaining TTL is less than half of their original TTL.  */
10032         insert_ptr -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
10033 
10034         /* Record the remaining ticks of resource record. */
10035         if (insert_ptr -> nx_mdns_rr_ttl >= NX_MDNS_RR_MAX_TTL)
10036         {
10037             /* If the ttl of resource resource record is outside the range, set as 0xFFFFFFFF.  */
10038             insert_ptr -> nx_mdns_rr_remaining_ticks = 0xFFFFFFFF;
10039         }
10040         else
10041         {
10042             /* Convert units(seconds to ticks). */
10043             insert_ptr -> nx_mdns_rr_remaining_ticks = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE;
10044         }
10045 
10046         /* Step2. Process query record.  */
10047         /* Set the pointer.  */
10048         head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
10049         head = (ULONG*)(*head);
10050 
10051         /* Check the remote resource record state.  */
10052         for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10053         {
10054 
10055             /* Check the state.  */
10056             if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
10057                 continue;
10058 
10059             /* Check the interface index.  */
10060             if (p -> nx_mdns_rr_interface_index != insert_ptr -> nx_mdns_rr_interface_index)
10061                 continue;
10062 
10063             /* Check the name.  */
10064             if (p -> nx_mdns_rr_name != insert_ptr -> nx_mdns_rr_name)
10065                 continue;
10066 
10067             /* Check the type.  */
10068             if ((p -> nx_mdns_rr_type != insert_ptr -> nx_mdns_rr_type) &&
10069                 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL))
10070                 continue;
10071 
10072             /* Check the class.  */
10073             if (p -> nx_mdns_rr_class != insert_ptr -> nx_mdns_rr_class)
10074                 continue;
10075 
10076             /* Check the query type.  */
10077             if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_CONTINUOUS_QUERY))
10078             {
10079 
10080                 /* Determine if we need to wake a thread suspended.  */
10081                 if (mdns_ptr -> nx_mdns_rr_receive_suspension_list)
10082                 {
10083 
10084                     /* Resume suspended thread.  */
10085                     _nx_mdns_query_thread_resume(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), mdns_ptr, insert_ptr);
10086                 }
10087 
10088                 /* Get the answer, we need not send the question again. Delete the resource record.  */
10089                 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
10090 
10091             }
10092             else
10093             {
10094 
10095                 /* There is no need for the querier to continue issuing a stream of queries when a mDNS response
10096                     is received containing a unique answer.  mDNS querier should send the next query at 80%-82% of the
10097                     record's TTL. RFC6762, Section5.2,Page11.  */
10098                 if ((insert_ptr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) && (insert_ptr -> nx_mdns_rr_ttl))
10099                 {
10100 
10101                     /* Set the timer count. */
10102                     p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (((ULONG)NX_RAND()) % 3)) / 100;
10103 
10104                     /* Set the mDNS timer.  */
10105                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10106                 }
10107 
10108                 /* Set the updating flag to update the resource record at 80% of the record's TTL.  */
10109                 insert_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UPDATING;
10110             }
10111         }
10112     }
10113     else
10114     {
10115 
10116         /* Update the state to delete this record from peer cache. .  */
10117         insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_DELETE;
10118 
10119         /* Delete the resource record one second later.  */
10120         insert_ptr -> nx_mdns_rr_timer_count = NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT;
10121     }
10122 
10123     /* Set the mDNS timer for insert RR.  */
10124     _nx_mdns_timer_set(mdns_ptr, insert_ptr, insert_ptr -> nx_mdns_rr_timer_count);
10125 
10126     /* Service name registered success, invoke the notify function.  */
10127     if (mdns_ptr -> nx_mdns_service_change_notify)
10128     {
10129 
10130         /* Process the service notify function.  */
10131         _nx_mdns_service_change_notify_process(mdns_ptr, insert_ptr, is_present);
10132     }
10133 
10134     /* Return success.  */
10135     return (NX_MDNS_SUCCESS);
10136 }
10137 #endif /* NX_MDNS_DISABLE_CLIENT  */
10138 
10139 
10140 /**************************************************************************/
10141 /*                                                                        */
10142 /*  FUNCTION                                               RELEASE        */
10143 /*                                                                        */
10144 /*    _nx_mdns_packet_rr_data_set                         PORTABLE C      */
10145 /*                                                           6.1.4        */
10146 /*  AUTHOR                                                                */
10147 /*                                                                        */
10148 /*    Yuxin Zhou, Microsoft Corporation                                   */
10149 /*                                                                        */
10150 /*  DESCRIPTION                                                           */
10151 /*                                                                        */
10152 /*    This function processes the packet, and sets the data of            */
10153 /*    resource record.                                                    */
10154 /*                                                                        */
10155 /*  INPUT                                                                 */
10156 /*                                                                        */
10157 /*    mdns_ptr                              Pointer to mDNS instance.     */
10158 /*    packet_ptr                            Pointer to the packet.        */
10159 /*    data_ptr                              Pointer to the data.          */
10160 /*    rr_ptr                                Pointer to the record         */
10161 /*    op                                    Operation:                    */
10162 /*                                            set answer in local cache.  */
10163 /*                                            or add answer in peer cache.*/
10164 /*    cache_ptr                             The record buffer.            */
10165 /*                                                                        */
10166 /*  OUTPUT                                                                */
10167 /*                                                                        */
10168 /*    status                                Completion status             */
10169 /*                                                                        */
10170 /*  CALLS                                                                 */
10171 /*                                                                        */
10172 /*    _nx_mdns_name_string_decode           Decode the name string        */
10173 /*    _nx_mdns_cache_add_string             Add the name string           */
10174 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
10175 /*                                                                        */
10176 /*  CALLED BY                                                             */
10177 /*                                                                        */
10178 /*    _nx_mdns_packet_process               Process mDNS packet           */
10179 /*                                                                        */
10180 /*  RELEASE HISTORY                                                       */
10181 /*                                                                        */
10182 /*    DATE              NAME                      DESCRIPTION             */
10183 /*                                                                        */
10184 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10185 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10186 /*                                            resulting in version 6.1    */
10187 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
10188 /*                                            buffer length verification, */
10189 /*                                            resulting in version 6.1.3  */
10190 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
10191 /*                                            packet length verification, */
10192 /*                                            resulting in version 6.1.4  */
10193 /*                                                                        */
10194 /**************************************************************************/
_nx_mdns_packet_rr_data_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op)10195 static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op)
10196 {
10197 
10198 UCHAR          *string_search = NX_NULL;
10199 UINT            cache_type;
10200 UCHAR           find_string;
10201 UCHAR           continue_process = NX_FALSE;
10202 UINT            status = NX_MDNS_UNSUPPORTED_TYPE;
10203 UINT            temp_string_length;
10204 
10205 
10206     /* Get cache type and size. */
10207     if (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER)
10208     {
10209         cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
10210         find_string = NX_TRUE;
10211     }
10212     else
10213     {
10214         cache_type = NX_MDNS_CACHE_TYPE_PEER;
10215         find_string = NX_FALSE;
10216     }
10217 
10218     /* Plus 10 for 2 bytes type, 2 bytes class, 4 bytes ttl and 2 bytes rdata length. */
10219     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
10220     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 10) > packet_ptr -> nx_packet_append_ptr))
10221     {
10222         return(NX_MDNS_ERROR);
10223     }
10224 
10225     /* Set the resource record time to live.*/
10226     rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + temp_string_length + 4);
10227 
10228     /* Set the resource record rdata length.  */
10229     rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 8);;
10230 
10231     /* Update the pointer to point at the resource data.  */
10232     data_ptr = data_ptr + temp_string_length + 10;
10233 
10234     /* Check the type.  */
10235     switch (rr_ptr -> nx_mdns_rr_type)
10236     {
10237         case NX_MDNS_RR_TYPE_A:
10238         {
10239 
10240             /* 4 bytes IP address. */
10241             if (data_ptr + 4 > packet_ptr -> nx_packet_append_ptr)
10242             {
10243                 return(NX_MDNS_ERROR);
10244             }
10245 
10246             /* Get the rdata.  */
10247             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = NX_MDNS_GET_ULONG_DATA(data_ptr);
10248             rr_ptr -> nx_mdns_rr_rdata_length = 4;
10249 
10250             /* Update the status.  */
10251             status = NX_MDNS_SUCCESS;
10252             break;
10253         }
10254         case NX_MDNS_RR_TYPE_AAAA:
10255         {
10256 
10257             /* 16 bytes IPv6 address. */
10258             if (data_ptr + 16 > packet_ptr -> nx_packet_append_ptr)
10259             {
10260                 return(NX_MDNS_ERROR);
10261             }
10262 
10263             /* Get the rdata.  */
10264             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = NX_MDNS_GET_ULONG_DATA(data_ptr);
10265             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = NX_MDNS_GET_ULONG_DATA(data_ptr + 4);
10266             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = NX_MDNS_GET_ULONG_DATA(data_ptr + 8);
10267             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = NX_MDNS_GET_ULONG_DATA(data_ptr + 12);
10268             rr_ptr -> nx_mdns_rr_rdata_length = 16;
10269 
10270             /* Update the status.  */
10271             status = NX_MDNS_SUCCESS;
10272             break;
10273         }
10274         case NX_MDNS_RR_TYPE_TXT:
10275         {
10276 
10277             /* Process the txt string. An empty TXT record contaning zero strings is not allowed. RFC6763, Page12.  */
10278             if (rr_ptr -> nx_mdns_rr_rdata_length == 1)
10279             {
10280 
10281                 /* Update the status.  */
10282                 status = NX_MDNS_SUCCESS;
10283             }
10284             else if (rr_ptr -> nx_mdns_rr_rdata_length > 1)
10285             {
10286 
10287                 if (data_ptr + rr_ptr -> nx_mdns_rr_rdata_length > packet_ptr -> nx_packet_append_ptr)
10288                 {
10289                     return(NX_MDNS_ERROR);
10290                 }
10291 
10292                 /* Add the txt string.  */
10293                 if (_nx_mdns_txt_string_decode(data_ptr, rr_ptr -> nx_mdns_rr_rdata_length, temp_string_buffer, NX_MDNS_NAME_MAX) == NX_MDNS_SUCCESS)
10294                 {
10295 
10296                     /* Check string length.  */
10297                     if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10298                     {
10299                         return(NX_MDNS_DATA_SIZE_ERROR);
10300                     }
10301 
10302                     /* Find the same string .  */
10303                     if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10304                                                  (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10305                     {
10306 
10307                         /* Update the name pointer.  */
10308                         rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = string_search;
10309 
10310                         /* Calculate the text string.inlcude the one byte label.  */
10311                         rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(temp_string_length + 1);
10312 
10313                         /* Update the status.  */
10314                         status = NX_MDNS_SUCCESS;
10315                     }
10316                 }
10317             }
10318 
10319             break;
10320         }
10321         case NX_MDNS_RR_TYPE_SRV:
10322         {
10323 
10324             /* Plus 6 bytes for 2 bytes priority, 2 bytes weights and 2 bytes port. */
10325             if (data_ptr + 6 > packet_ptr -> nx_packet_append_ptr)
10326             {
10327                 return(NX_MDNS_ERROR);
10328             }
10329 
10330             /* Get the priority.  */
10331             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = NX_MDNS_GET_USHORT_DATA(data_ptr);
10332             data_ptr += 2;
10333 
10334             /* Get the weights.  */
10335             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = NX_MDNS_GET_USHORT_DATA(data_ptr);
10336             data_ptr += 2;
10337 
10338             /* Get the port.  */
10339             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = NX_MDNS_GET_USHORT_DATA(data_ptr);
10340             data_ptr += 2;
10341 
10342             /* Update the rdata length.  */
10343             rr_ptr -> nx_mdns_rr_rdata_length = 6;
10344 
10345             /* Continue to process target name.  */
10346             continue_process = NX_TRUE;
10347             break;
10348         }
10349         case NX_MDNS_RR_TYPE_PTR:
10350 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10351         case NX_MDNS_RR_TYPE_CNAME:
10352         case NX_MDNS_RR_TYPE_NS:
10353 #endif
10354         {
10355 
10356             /* Update the rdata length.  */
10357             rr_ptr -> nx_mdns_rr_rdata_length = 0;
10358 
10359             /* Continue to process the domain name.  */
10360             continue_process = NX_TRUE;
10361             break;
10362         }
10363 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10364         case NX_MDNS_RR_TYPE_MX:
10365         {
10366 
10367             /* Plus 2 bytes for preference. */
10368             if (data_ptr + 2 > packet_ptr -> nx_packet_append_ptr)
10369             {
10370                 return(NX_MDNS_ERROR);
10371             }
10372 
10373             /* Set the preference.  */
10374             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference = NX_MDNS_GET_USHORT_DATA(data_ptr);
10375             data_ptr += 2;
10376 
10377             /* Update the rdata length.  */
10378             rr_ptr ->  nx_mdns_rr_rdata_length = 2;
10379 
10380             /* Continue to process the domain name.  */
10381             continue_process = NX_TRUE;
10382             break;
10383         }
10384 #endif
10385     }
10386 
10387     /* Check if need to continue process rdata.  */
10388     if(continue_process == NX_TRUE)
10389     {
10390 
10391         /* Process the target/domain name string.  */
10392         if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
10393                                        (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
10394                                         packet_ptr -> nx_packet_length,
10395                                        temp_string_buffer, NX_MDNS_NAME_MAX))
10396         {
10397 
10398             /* Check string length.  */
10399             if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10400             {
10401                 return(NX_MDNS_DATA_SIZE_ERROR);
10402             }
10403 
10404             /* Add the string.  */
10405             if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10406                                          (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10407             {
10408 
10409                 /* Update the name pointer for SRV, PTR, etc.  */
10410                 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target = string_search;
10411 
10412                 /* Calculate the text string. Inlcude the one byte label '.' and null '\0'.  */
10413                 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(rr_ptr -> nx_mdns_rr_rdata_length + (temp_string_length + 2));
10414 
10415                 /* Update the status.  */
10416                 status = NX_MDNS_SUCCESS;
10417             }
10418         }
10419     }
10420 
10421     /* Return success.  */
10422     return (status);
10423 }
10424 
10425 
10426 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
10427 /**************************************************************************/
10428 /*                                                                        */
10429 /*  FUNCTION                                               RELEASE        */
10430 /*                                                                        */
10431 /*    _nx_mdns_packet_address_check                       PORTABLE C      */
10432 /*                                                           6.1.4        */
10433 /*  AUTHOR                                                                */
10434 /*                                                                        */
10435 /*    Yuxin Zhou, Microsoft Corporation                                   */
10436 /*                                                                        */
10437 /*  DESCRIPTION                                                           */
10438 /*                                                                        */
10439 /*    This function checks the IP address and port of received packet.    */
10440 /*                                                                        */
10441 /*  INPUT                                                                 */
10442 /*                                                                        */
10443 /*    packet_ptr                            Pointer to mDNS packet        */
10444 /*                                                                        */
10445 /*  OUTPUT                                                                */
10446 /*                                                                        */
10447 /*    status                                Completion status             */
10448 /*                                                                        */
10449 /*  CALLS                                                                 */
10450 /*                                                                        */
10451 /*    none                                                                */
10452 /*                                                                        */
10453 /*  CALLED BY                                                             */
10454 /*                                                                        */
10455 /*    _nx_mdns_packet_process               Process mDNS packet           */
10456 /*                                                                        */
10457 /*  RELEASE HISTORY                                                       */
10458 /*                                                                        */
10459 /*    DATE              NAME                      DESCRIPTION             */
10460 /*                                                                        */
10461 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10462 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10463 /*                                            resulting in version 6.1    */
10464 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
10465 /*                                            packet length verification, */
10466 /*                                            resulting in version 6.1.4  */
10467 /*                                                                        */
10468 /**************************************************************************/
_nx_mdns_packet_address_check(NX_PACKET * packet_ptr)10469 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr)
10470 {
10471 
10472 USHORT              mdns_flags;
10473 UINT                src_port;
10474 ULONG              *udp_header;
10475 
10476 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
10477 NXD_ADDRESS         src_address;
10478 NXD_ADDRESS         des_address;
10479 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
10480 
10481 #ifndef NX_DISABLE_IPV4
10482 NX_IPV4_HEADER     *ipv4_header;
10483 #endif /* NX_DISABLE_IPV4  */
10484 
10485 #ifdef NX_MDNS_ENABLE_IPV6
10486 NX_IPV6_HEADER     *ipv6_header;
10487 #endif /* NX_MDNS_ENABLE_IPV6  */
10488 
10489 
10490     /* 2 bytes ID and 2 bytes flags. */
10491     if (packet_ptr -> nx_packet_length < 4)
10492     {
10493         return(NX_MDNS_ERROR);
10494     }
10495 
10496     /* Extract the message type which should be the first byte.  */
10497     mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
10498 
10499 #ifndef NX_DISABLE_IPV4
10500     /* Get the ip address.  */
10501     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10502     {
10503 
10504         /* Set the IPv4 header.  */
10505         ipv4_header = (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
10506 
10507         /* Set the source address.  */
10508         src_address.nxd_ip_version = NX_IP_VERSION_V4;
10509         src_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_source_ip;
10510 
10511         /* Set the destination address.  */
10512         des_address.nxd_ip_version = NX_IP_VERSION_V4;
10513         des_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_destination_ip;
10514     }
10515     else
10516 #endif /* NX_DISABLE_IPV4  */
10517 
10518 #ifdef NX_MDNS_ENABLE_IPV6
10519     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10520     {
10521 
10522         /* Set the IPv6 header.  */
10523         ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
10524 
10525         /* Set the source address.  */
10526         src_address.nxd_ip_version = NX_IP_VERSION_V6;
10527         COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_address.nxd_ip_address.v6);
10528 
10529         /* Set the destination address.  */
10530         des_address.nxd_ip_version = NX_IP_VERSION_V6;
10531         COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, des_address.nxd_ip_address.v6);
10532     }
10533     else
10534 #endif /* NX_MDNS_ENABLE_IPV6  */
10535     {
10536 
10537         /* Invalid IP version . */
10538         return(NX_MDNS_ERROR);
10539     }
10540 
10541     /* Pickup the pointer to the head of the UDP packet.  */
10542     udp_header =  (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 8);
10543 
10544     /* Get the source port and destination port.  */
10545     src_port = (UINT) ((*udp_header) >> NX_SHIFT_BY_16);
10546 
10547     /* Check the source UDP port.  RFC6762, Section6, Page15.  */
10548     if (src_port != NX_MDNS_UDP_PORT)
10549     {
10550         return(NX_MDNS_UDP_PORT_ERROR);
10551     }
10552 
10553     /* Check the QR bit. */
10554     if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
10555     {
10556 
10557         /* Check the response code.  */
10558         if (mdns_flags & NX_MDNS_ERROR_MASK)
10559         {
10560 
10561             /* Release the source packet.  */
10562             return(NX_MDNS_AUTH_ERROR);
10563         }
10564 
10565         /* In response messages for Multicast domains, the AA bit Must be set to one, RFC6762, Page48. */
10566         if ((mdns_flags & NX_MDNS_AA_FLAG) != NX_MDNS_AA_FLAG)
10567         {
10568             return (NX_MDNS_ERROR);
10569         }
10570 
10571 #ifndef NX_DISABLE_IPV4
10572         /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10573         if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10574         {
10575 
10576             /* Local link check, Multicast Address or (I & M) == (P & M).  */
10577             if ((des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS) &&
10578                 (packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address & packet_ptr ->nx_packet_ip_interface -> nx_interface_ip_network_mask) !=
10579                 (src_address.nxd_ip_address.v4 & packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_network_mask))
10580             {
10581                 return (NX_MDNS_NOT_LOCAL_LINK);
10582             }
10583         }
10584         else
10585 #endif /* NX_DISABLE_IPV4  */
10586 
10587 #ifdef NX_MDNS_ENABLE_IPV6
10588         if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10589         {
10590 
10591             /* Destination address is not FF02::FB address or source address not on link, RFC6762, Section 11, Page39. */
10592             /* Not check the source address.  */
10593             if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10594                 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10595                 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10596                 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10597             {
10598                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10599             }
10600         }
10601         else
10602 #endif /* NX_MDNS_ENABLE_IPV6  */
10603         {
10604 
10605             /* Invalid IP version. */
10606             return(NX_MDNS_ERROR);
10607         }
10608     }
10609     else
10610     {
10611 
10612 #ifndef NX_DISABLE_IPV4
10613         /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10614         if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10615         {
10616             if (des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS)
10617             {
10618                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10619             }
10620         }
10621         else
10622 #endif /* NX_DISABLE_IPV4  */
10623 
10624 #ifdef NX_MDNS_ENABLE_IPV6
10625         if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10626         {
10627             if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10628                 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10629                 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10630                 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10631             {
10632                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10633             }
10634         }
10635         else
10636 #endif /* NX_MDNS_ENABLE_IPV6  */
10637         {
10638 
10639             /* Invalid IP version . */
10640             return(NX_MDNS_ERROR);
10641         }
10642     }
10643 
10644     return(NX_MDNS_SUCCESS);
10645 }
10646 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
10647 
10648 
10649 #ifndef NX_MDNS_DISABLE_SERVER
10650 /**************************************************************************/
10651 /*                                                                        */
10652 /*  FUNCTION                                               RELEASE        */
10653 /*                                                                        */
10654 /*    _nx_mdns_address_change_process                     PORTABLE C      */
10655 /*                                                           6.1          */
10656 /*  AUTHOR                                                                */
10657 /*                                                                        */
10658 /*    Yuxin Zhou, Microsoft Corporation                                   */
10659 /*                                                                        */
10660 /*  DESCRIPTION                                                           */
10661 /*                                                                        */
10662 /*    This function process the address change event.                     */
10663 /*                                                                        */
10664 /*  INPUT                                                                 */
10665 /*                                                                        */
10666 /*    mdns_ptr                              Pointer to mDNS instance      */
10667 /*                                                                        */
10668 /*  OUTPUT                                                                */
10669 /*                                                                        */
10670 /*    status                                Completion status             */
10671 /*                                                                        */
10672 /*  CALLS                                                                 */
10673 /*                                                                        */
10674 /*    nx_packet_copy                        Copy the mDNS packet          */
10675 /*    nx_packet_release                     Release the mDNS packet       */
10676 /*    nx_udp_socket_send                    Send the udp packet           */
10677 /*    nxd_udp_socket_send                   Send the udp packet           */
10678 /*                                                                        */
10679 /*  CALLED BY                                                             */
10680 /*                                                                        */
10681 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
10682 /*                                                                        */
10683 /*  RELEASE HISTORY                                                       */
10684 /*                                                                        */
10685 /*    DATE              NAME                      DESCRIPTION             */
10686 /*                                                                        */
10687 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10688 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10689 /*                                            resulting in version 6.1    */
10690 /*                                                                        */
10691 /**************************************************************************/
_nx_mdns_address_change_process(NX_MDNS * mdns_ptr)10692 static VOID    _nx_mdns_address_change_process(NX_MDNS *mdns_ptr)
10693 {
10694 
10695 ULONG       *head;
10696 NX_MDNS_RR  *p;
10697 UINT        i;
10698 
10699 
10700     /* Register the host name.  */
10701     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
10702     {
10703 
10704         /* Check if the interface is enabled.  */
10705         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
10706             continue;
10707 
10708         /* Get the local buffer head. */
10709         head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10710 
10711         if (head)
10712         {
10713 
10714             /* Set the pointer.  */
10715             head = (ULONG*)(*head);
10716 
10717             /* Check the resource record.  */
10718             for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10719             {
10720 
10721                 /* Check whether the resource record is valid. */
10722                 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
10723                     continue;
10724 
10725                 /* Check the interface index.  */
10726                 if (p -> nx_mdns_rr_interface_index != i)
10727                     continue;
10728 
10729                 /* If any of a host's IP addresses change, it MUST re-announce those address records. RFC6762, Section8.4, Page31.  */
10730                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10731                     (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10732                 {
10733 
10734                     /* Send the "goodbye " announcement with RR TTL zero. RFC6762, Section8.4, Page31.  */
10735                     p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
10736 
10737                     /* Clear the retransmit count.  */
10738                     p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
10739 
10740                     /* Set the timer count. 250ms.  */
10741                     p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
10742 
10743                     /* Set the delete flag.  */
10744                     p -> nx_mdns_rr_word = (p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
10745 
10746                     /* Set the mDNS timer.  */
10747                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10748                 }
10749 
10750 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
10751                 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
10752                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
10753 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
10754             }
10755         }
10756 
10757         /* Second register the host name, the host does not need to repeat the Probing step, Only Announcing the A/AAAA.  */
10758         _nx_mdns_host_name_register(mdns_ptr, NX_FALSE, i);
10759     }
10760 }
10761 
10762 
10763 /**************************************************************************/
10764 /*                                                                        */
10765 /*  FUNCTION                                               RELEASE        */
10766 /*                                                                        */
10767 /*    _nx_mdns_conflict_process                           PORTABLE C      */
10768 /*                                                           6.1          */
10769 /*  AUTHOR                                                                */
10770 /*                                                                        */
10771 /*    Yuxin Zhou, Microsoft Corporation                                   */
10772 /*                                                                        */
10773 /*  DESCRIPTION                                                           */
10774 /*                                                                        */
10775 /*    This function process the mDNS conflict. RFC6762, Section9, Page31  */
10776 /*                                                                        */
10777 /*  INPUT                                                                 */
10778 /*                                                                        */
10779 /*    mdns_ptr                              Pointer to mDNS instance      */
10780 /*    record_rr                             The resource record           */
10781 /*                                                                        */
10782 /*  OUTPUT                                                                */
10783 /*                                                                        */
10784 /*    status                                Completion status             */
10785 /*                                                                        */
10786 /*  CALLS                                                                 */
10787 /*                                                                        */
10788 /*    _nx_mdns_cache_add_string             Add the string                */
10789 /*    _nx_mdns_cache_delete_string          Delete the string             */
10790 /*    _nx_mdns_srv_name_resolve             Reslove the service name      */
10791 /*    nx_mdns_rr_change_notify              Resource record notify        */
10792 /*                                                                        */
10793 /*  CALLED BY                                                             */
10794 /*                                                                        */
10795 /*    _nx_mdns_packet_process               Process mDNS packet           */
10796 /*                                                                        */
10797 /*  RELEASE HISTORY                                                       */
10798 /*                                                                        */
10799 /*    DATE              NAME                      DESCRIPTION             */
10800 /*                                                                        */
10801 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10802 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
10803 /*                                            buffer length verification, */
10804 /*                                            verified memcpy use cases,  */
10805 /*                                            resulting in version 6.1    */
10806 /*                                                                        */
10807 /**************************************************************************/
_nx_mdns_conflict_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)10808 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
10809 {
10810 
10811 UINT        status;
10812 UCHAR       *old_name;
10813 UCHAR       *name;
10814 UCHAR       *type = NX_NULL;
10815 UCHAR       *domain = NX_NULL;
10816 UINT        i;
10817 ULONG       *head;
10818 NX_MDNS_RR  *p;
10819 UCHAR       is_host_type;
10820 UINT        temp_string_length;
10821 UINT        rr_name_length;
10822 
10823 
10824     /* Initialize the value.  */
10825     i = 0;
10826     memset(&temp_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10827     memset(&target_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10828 
10829     /* Get rr type. */
10830     if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10831        (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT))
10832     {
10833         is_host_type = NX_FALSE;
10834 
10835         /* Check string length.  */
10836         if (_nx_utility_string_length_check((CHAR *)(record_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
10837         {
10838             return(NX_MDNS_DATA_SIZE_ERROR);
10839         }
10840 
10841         /* Store the service name.  */
10842         memcpy((CHAR *)&target_string_buffer[0], (const char*)(record_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
10843 
10844         /* Get Name, Type, Domain.  */
10845         _nx_mdns_service_name_resolve(&target_string_buffer[0], &name, &type, &domain);
10846     }
10847     else if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10848             (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10849     {
10850         is_host_type = NX_TRUE;
10851         name = mdns_ptr -> nx_mdns_host_name;
10852     }
10853     else
10854     {
10855 
10856         /* This is an unsupported or unknown type. */
10857         return(NX_MDNS_UNSUPPORTED_TYPE);
10858     }
10859 
10860     /* Check the conflict count.  */
10861     if (record_rr -> nx_mdns_rr_conflict_count >= NX_MDNS_CONFLICT_COUNT)
10862     {
10863 
10864         /* Yes, Receive the confilictiong mDNS, Probing failure.  */
10865         if ((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10866             (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A))
10867         {
10868 
10869             /* Service name has been registered , invoke the notify function.  */
10870             if (mdns_ptr -> nx_mdns_probing_notify)
10871             {
10872                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, name, NX_MDNS_LOCAL_SERVICE_REGISTERED_FAILURE);
10873             }
10874         }
10875 
10876         /* Return.  */
10877         return (NX_MDNS_ERROR);
10878     }
10879 
10880     /* Record the old name.  */
10881     old_name = record_rr -> nx_mdns_rr_name;
10882 
10883     /* Set the new name and probing it.  */
10884     while ((*name) != '\0')
10885     {
10886         temp_string_buffer[i++] = *name++;
10887     }
10888 
10889     /* The first conflict, only add the " (2)".  */
10890     if (record_rr -> nx_mdns_rr_conflict_count == 0)
10891     {
10892         temp_string_buffer[i++] = ' ';
10893         temp_string_buffer[i++] = '(';
10894         temp_string_buffer[i++] = '2';
10895         temp_string_buffer[i++] = ')';
10896     }
10897 
10898     /* Modify the count, eg: " (2)" change to " (3)".  */
10899     else
10900     {
10901         temp_string_buffer[i-2] = (UCHAR)(temp_string_buffer[i-2] + 1);
10902     }
10903 
10904 
10905     if(is_host_type == NX_TRUE)
10906     {
10907 
10908         /* Check string length.  */
10909         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_HOST_NAME_MAX))
10910         {
10911             return(NX_MDNS_DATA_SIZE_ERROR);
10912         }
10913 
10914         /* Construct the target host.  */
10915         memcpy((CHAR *)(mdns_ptr -> nx_mdns_host_name), (CHAR *)(temp_string_buffer), temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h. */
10916 
10917         temp_string_buffer[i++] = '.';
10918 
10919         /* Check string length.  */
10920         if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &temp_string_length, NX_MDNS_DOMAIN_NAME_MAX))
10921         {
10922             return(NX_MDNS_DATA_SIZE_ERROR);
10923         }
10924 
10925         /* Add the domain.  */
10926         memcpy((CHAR *)(&temp_string_buffer[i]), (CHAR *)mdns_ptr -> nx_mdns_domain_name, temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_DOMAIN_NAME_MAX is limited in nxd_mdns.h. */
10927     }
10928     else
10929     {
10930         temp_string_buffer[i++] = '.';
10931 
10932         /* Set the Type.  */
10933         while ((*type) != '\0')
10934         {
10935             temp_string_buffer[i++] = *type++;
10936         }
10937 
10938         temp_string_buffer[i++] = '.';
10939 
10940         /* Set the Domain.  */
10941         while ((*domain) != '\0')
10942         {
10943             temp_string_buffer[i++] = *domain++;
10944         }
10945     }
10946 
10947     /* Check string length.  */
10948     if (_nx_utility_string_length_check((CHAR *)&temp_string_buffer[0], &temp_string_length, NX_MDNS_NAME_MAX))
10949     {
10950         return(NX_MDNS_DATA_SIZE_ERROR);
10951     }
10952 
10953     /* Add the new resource records. */
10954     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL,
10955                                        &temp_string_buffer[0], temp_string_length,
10956                                        (VOID **)(&record_rr -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
10957 
10958     if (status )
10959     {
10960 
10961         /* No, return error status.  */
10962         return(status);
10963     }
10964 
10965     /* Update the state.  */
10966     record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
10967     record_rr -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
10968     record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
10969     record_rr -> nx_mdns_rr_conflict_count ++;
10970 
10971     /* Set the mDNS timer.  */
10972     _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
10973 
10974     /* Update the PTR/SRV data name.  */
10975     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10976     head = (ULONG*)(*head);
10977 
10978     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10979     {
10980         if ((((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) && (is_host_type == NX_FALSE)) ||
10981              ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) && (is_host_type == NX_TRUE))) &&
10982             (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == old_name))
10983         {
10984 
10985             /* Add the new resource records. */
10986             status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_string_buffer[0], temp_string_length,
10987                                                (VOID **)(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)), NX_FALSE, NX_TRUE);
10988 
10989             /* Delete the rdata name.  */
10990             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10991         }
10992     }
10993 
10994     /* Delete the old name.  */
10995     _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10996 
10997     return(NX_MDNS_SUCCESS);
10998 }
10999 #endif /* NX_MDNS_DISABLE_SERVER  */
11000 
11001 
11002 #ifndef NX_MDNS_DISABLE_CLIENT
11003 /**************************************************************************/
11004 /*                                                                        */
11005 /*  FUNCTION                                               RELEASE        */
11006 /*                                                                        */
11007 /*    _nx_mdns_service_change_notify_process              PORTABLE C      */
11008 /*                                                           6.1          */
11009 /*  AUTHOR                                                                */
11010 /*                                                                        */
11011 /*    Yuxin Zhou, Microsoft Corporation                                   */
11012 /*                                                                        */
11013 /*  DESCRIPTION                                                           */
11014 /*                                                                        */
11015 /*    This function processes the mDNS service change operation, when the */
11016 /*    service information change, notify the application.                 */
11017 /*                                                                        */
11018 /*  INPUT                                                                 */
11019 /*                                                                        */
11020 /*    mdns_ptr                              Pointer to mDNS instance      */
11021 /*    record_rr                             The resource record           */
11022 /*    is_present                            The service type              */
11023 /*                                                                        */
11024 /*  OUTPUT                                                                */
11025 /*                                                                        */
11026 /*    status                                Completion status             */
11027 /*                                                                        */
11028 /*  CALLS                                                                 */
11029 /*                                                                        */
11030 /*    tx_mutex_get                          Get the mDNS mutex            */
11031 /*    tx_mutex_put                          Put the mDNS mutex            */
11032 /*                                                                        */
11033 /*  CALLED BY                                                             */
11034 /*                                                                        */
11035 /*    Application Code                                                    */
11036 /*                                                                        */
11037 /*  RELEASE HISTORY                                                       */
11038 /*                                                                        */
11039 /*    DATE              NAME                      DESCRIPTION             */
11040 /*                                                                        */
11041 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11042 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11043 /*                                            verified memcpy use cases,  */
11044 /*                                            resulting in version 6.1    */
11045 /*                                                                        */
11046 /**************************************************************************/
_nx_mdns_service_change_notify_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * new_rr,UCHAR is_present)11047 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present)
11048 {
11049 
11050 UINT            notify_status = 0;
11051 ULONG           *head;
11052 NX_MDNS_RR      *p;
11053 NX_MDNS_SERVICE temp_service;
11054 UINT            rr_name_length;
11055 
11056 
11057     /* Initialize the struct.  */
11058     memset(&temp_service, 0, sizeof(NX_MDNS_SERVICE));
11059 
11060     /* Compare the RDATA. */
11061     switch (new_rr -> nx_mdns_rr_type)
11062     {
11063         case NX_MDNS_RR_TYPE_A:
11064         case NX_MDNS_RR_TYPE_AAAA:
11065         {
11066 
11067             /* Get the remote buffer head. */
11068             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11069             head = (ULONG*)(*head);
11070 
11071             /* Check the resource record.  */
11072             for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
11073             {
11074 
11075                 /* Check whether the resource record is valid. */
11076                 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11077                     (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11078                     continue;
11079 
11080                 /* Check the interface.  */
11081                 if (p -> nx_mdns_rr_interface_index != new_rr -> nx_mdns_rr_interface_index)
11082                     continue;
11083 
11084                 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
11085                 {
11086                     if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == new_rr -> nx_mdns_rr_name)
11087                     {
11088 
11089                         /* Check string length.  */
11090                         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11091                         {
11092                             break;
11093                         }
11094 
11095                         /* Store the Service name.  */
11096                         memcpy((CHAR *)(&temp_string_buffer[0]), (CHAR *)(p -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11097 
11098                         /* Check if the address is updated.  */
11099                         if (((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0)) ||
11100                             (((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))))
11101                         {
11102                             notify_status = NX_MDNS_PEER_SERVICE_UPDATED;
11103                         }
11104                         break;
11105                     }
11106                 }
11107             }
11108 
11109             break;
11110         }
11111         case NX_MDNS_RR_TYPE_SRV:
11112         {
11113 
11114             /* Check string length.  */
11115             if (_nx_utility_string_length_check((CHAR *)(new_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11116             {
11117                 break;
11118             }
11119 
11120             /* Store the Service name.  */
11121             memcpy((CHAR *)&temp_string_buffer[0], (CHAR *)(new_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11122 
11123             /* Check if the service is new.  */
11124             if ((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0))
11125             {
11126                 notify_status = NX_MDNS_PEER_SERVICE_RECEIVED;
11127             }
11128             else if ((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))
11129             {
11130                 notify_status = NX_MDNS_PEER_SERVICE_DELETED;
11131             }
11132             break;
11133         }
11134         default:
11135         {
11136 
11137             /* This is an unsupported or unknown type. */
11138             return;
11139         }
11140     }
11141 
11142     /* Check if need to call then notify function.  */
11143     if (notify_status == 0)
11144         return;
11145 
11146     /* Store the service name.  */
11147     memcpy((CHAR *)(&temp_service.buffer[0]), (CHAR *)(&temp_string_buffer[0]), rr_name_length); /* Use case of memcpy is verified. */
11148 
11149     /* Reslove the service name.  */
11150     if (_nx_mdns_service_name_resolve(&temp_service.buffer[0], &(temp_service.service_name), &(temp_service.service_type), &(temp_service.service_domain)))
11151         return;
11152 
11153     /* Compare the service change type.  */
11154     if (_nx_mdns_service_mask_match(mdns_ptr, temp_service.service_type, mdns_ptr -> nx_mdns_service_notify_mask))
11155         return;
11156 
11157     /* Get the additional information.  */
11158     _nx_mdns_service_addition_info_get(mdns_ptr, &temp_string_buffer[0], &temp_service, new_rr -> nx_mdns_rr_interface_index);
11159 
11160     /* Call the notify function.  */
11161     (mdns_ptr -> nx_mdns_service_change_notify)(mdns_ptr, &temp_service, notify_status);
11162 }
11163 
11164 
11165 /**************************************************************************/
11166 /*                                                                        */
11167 /*  FUNCTION                                               RELEASE        */
11168 /*                                                                        */
11169 /*    _nx_mdns_service_addition_info_get                  PORTABLE C      */
11170 /*                                                           6.1          */
11171 /*  AUTHOR                                                                */
11172 /*                                                                        */
11173 /*    Yuxin Zhou, Microsoft Corporation                                   */
11174 /*                                                                        */
11175 /*  DESCRIPTION                                                           */
11176 /*                                                                        */
11177 /*    This function adds the mDNS resource record into remote buffer,     */
11178 /*    mDNS thread send the query message using continuous type.           */
11179 /*                                                                        */
11180 /*  INPUT                                                                 */
11181 /*                                                                        */
11182 /*    mdns_ptr                              Pointer to mDNS instance      */
11183 /*    name                                  The service instance          */
11184 /*    type                                  The service type              */
11185 /*    domain                                The domain name               */
11186 /*                                                                        */
11187 /*  OUTPUT                                                                */
11188 /*                                                                        */
11189 /*    status                                Completion status             */
11190 /*                                                                        */
11191 /*  CALLS                                                                 */
11192 /*                                                                        */
11193 /*    tx_mutex_get                          Get the mDNS mutex            */
11194 /*    tx_mutex_put                          Put the mDNS mutex            */
11195 /*    _nx_mdns_query_check                  Check the query RR            */
11196 /*    _nx_mdns_cache_add_string             Add the string into buffer    */
11197 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11198 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
11199 /*                                            into buffer                 */
11200 /*                                                                        */
11201 /*  CALLED BY                                                             */
11202 /*                                                                        */
11203 /*    Application Code                                                    */
11204 /*                                                                        */
11205 /*  RELEASE HISTORY                                                       */
11206 /*                                                                        */
11207 /*    DATE              NAME                      DESCRIPTION             */
11208 /*                                                                        */
11209 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11210 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11211 /*                                            verified memcpy use cases,  */
11212 /*                                            resulting in version 6.1    */
11213 /*                                                                        */
11214 /**************************************************************************/
_nx_mdns_service_addition_info_get(NX_MDNS * mdns_ptr,UCHAR * srv_name,NX_MDNS_SERVICE * service,UINT interface_index)11215 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index)
11216 {
11217 
11218 UINT        index = 0;
11219 ULONG       current_time;
11220 ULONG       *head, *tail;
11221 UCHAR       i;
11222 NX_MDNS_RR  *p;
11223 NX_MDNS_RR  *p1;
11224 UINT        srv_name_length;
11225 UINT        temp_length;
11226 
11227 
11228     /* Check string length.  */
11229     if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
11230     {
11231         return(NX_MDNS_ERROR);
11232     }
11233 
11234     /* Get the current time.  */
11235     current_time = tx_time_get();
11236 
11237     for(i = 0; i < 2; i++)
11238     {
11239 
11240         /* Set the pointer. */
11241         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
11242         {
11243 #ifndef NX_MDNS_DISABLE_SERVER
11244             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
11245 #else
11246             continue;
11247 #endif /* NX_MDNS_DISABLE_SERVER */
11248         }
11249         else
11250         {
11251 #ifndef NX_MDNS_DISABLE_CLIENT
11252             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11253 #else
11254             continue;
11255 #endif /* NX_MDNS_DISABLE_CLIENT  */
11256         }
11257 
11258         if(head == NX_NULL)
11259             continue;
11260 
11261         /* Set the pointer.  */
11262         tail = (ULONG*)(*head);
11263 
11264         /* Check the resource record.  */
11265         for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
11266         {
11267 
11268             /* Check whether the resource record is valid. */
11269             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11270                 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11271                 continue;
11272 
11273             /* Check the interface index.  */
11274             if (p -> nx_mdns_rr_interface_index != interface_index)
11275                 continue;
11276 
11277             /* Check the type and name. */
11278             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
11279                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11280             {
11281 
11282                 /* Update the elasped timer.  */
11283                 p -> nx_mdns_rr_elapsed_time = current_time;
11284 
11285                 /* Set the service priority, weight, port and target. */
11286                 service -> service_priority = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority;
11287                 service -> service_weight = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights;
11288                 service -> service_port = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port;
11289 
11290                 /* Check string length.  */
11291                 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target), &temp_length, NX_MDNS_HOST_NAME_MAX))
11292                 {
11293                     return(NX_MDNS_ERROR);
11294                 }
11295 
11296                 /* Store the target host.  */
11297                 memcpy((CHAR *)(service -> service_host), /* Use case of memcpy is verified. */
11298                        (CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
11299                        temp_length + 1);
11300 
11301                 /* All address records (type "A" and "AAAA") named in the SRV rdata */
11302                 for (p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
11303                 {
11304 
11305                     /* Update the elasped timer.  */
11306                     p1 -> nx_mdns_rr_elapsed_time = current_time;
11307 
11308                     /* Check the interface index.  */
11309                     if (p1 -> nx_mdns_rr_interface_index != interface_index)
11310                         continue;
11311 
11312                     /* Find the "A" records.  */
11313                     if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) &&
11314                         (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11315                     {
11316 
11317                         /* Set the IPv4 address.  */
11318                         service -> service_ipv4 = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
11319                     }
11320 
11321                     /* Find the "AAAA" records.  */
11322                     if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA) &&
11323                         (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11324                     {
11325                         if (index < NX_MDNS_IPV6_ADDRESS_COUNT)
11326                         {
11327 
11328                             /* Set the IPv6 address.  */
11329                             service -> service_ipv6[index][0] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0];
11330                             service -> service_ipv6[index][1] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1];
11331                             service -> service_ipv6[index][2] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2];
11332                             service -> service_ipv6[index][3] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3];
11333                             index ++;
11334                         }
11335                     }
11336                 }
11337             }
11338 
11339             /* Check the type and name. */
11340             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) &&
11341                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11342             {
11343 
11344                 /* Update the elasped timer.  */
11345                 p -> nx_mdns_rr_elapsed_time = current_time;
11346 
11347                 /* Set the text valid flag.  */
11348                 service -> service_text_valid = 1;
11349 
11350                 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
11351                 {
11352 
11353                     /* Check string length.  */
11354                     if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), &temp_length, NX_MDNS_NAME_MAX))
11355                     {
11356                         continue;
11357                     }
11358 
11359                     /* Store the txt.  */
11360                     memcpy((CHAR *)(service -> service_text), (const char*)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), temp_length + 1); /* Use case of memcpy is verified. */
11361                 }
11362             }
11363         }
11364     }
11365 
11366     /* Set the interface index.  */
11367     service -> interface_index = (UCHAR)interface_index;
11368 
11369     /* Return a error status.  */
11370     return(NX_MDNS_SUCCESS);
11371 }
11372 #endif /* NX_MDNS_DISABLE_CLIENT */
11373 
11374 
11375 /**************************************************************************/
11376 /*                                                                        */
11377 /*  FUNCTION                                               RELEASE        */
11378 /*                                                                        */
11379 /*    _nx_mdns_cache_initialize                         PORTABLE C       */
11380 /*                                                           6.1          */
11381 /*  AUTHOR                                                                */
11382 /*                                                                        */
11383 /*    Yuxin Zhou, Microsoft Corporation                                   */
11384 /*                                                                        */
11385 /*  DESCRIPTION                                                           */
11386 /*                                                                        */
11387 /*    This function initializes the mDNS remote buffer and local buffer.  */
11388 /*                                                                        */
11389 /*  INPUT                                                                 */
11390 /*                                                                        */
11391 /*    mdns_ptr                              Pointer to mDNS instance      */
11392 /*    local_cache_ptr                       Pointer to local cache        */
11393 /*    local_cache_size                      The size of local cache       */
11394 /*    peer_cache_ptr                        Pointer to peer cache         */
11395 /*    peer_cache_size                       The size of peer cache        */
11396 /*                                                                        */
11397 /*  OUTPUT                                                                */
11398 /*                                                                        */
11399 /*    status                                Completion status             */
11400 /*                                                                        */
11401 /*  CALLS                                                                 */
11402 /*                                                                        */
11403 /*    tx_mutex_get                          Get the mDNS mutex            */
11404 /*    tx_mutex_put                          Put the mDNS mutex            */
11405 /*                                                                        */
11406 /*  CALLED BY                                                             */
11407 /*                                                                        */
11408 /*    _nx_mdns_create                       Initialize the mDNS structure */
11409 /*    _nx_mdns_disable                      Disable the mDNS function     */
11410 /*    _nx_mdns_peer_cache_clear             Clear the peer cache          */
11411 /*                                                                        */
11412 /*  RELEASE HISTORY                                                       */
11413 /*                                                                        */
11414 /*    DATE              NAME                      DESCRIPTION             */
11415 /*                                                                        */
11416 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11417 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11418 /*                                            resulting in version 6.1    */
11419 /*                                                                        */
11420 /**************************************************************************/
_nx_mdns_cache_initialize(NX_MDNS * mdns_ptr,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size)11421 UINT _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size,
11422                                VOID *peer_cache_ptr, UINT peer_cache_size)
11423 {
11424 
11425 ULONG *head;
11426 ULONG *tail;
11427 
11428 
11429 #ifndef NX_MDNS_DISABLE_SERVER
11430     /* Check the cache.  */
11431     if (local_cache_ptr)
11432     {
11433 
11434         /* Zero out the cache. */
11435         memset(local_cache_ptr, 0, local_cache_size);
11436 
11437         /* Set the head. */
11438         head = (ULONG*)local_cache_ptr;
11439         *head = (ULONG)((ULONG*)local_cache_ptr + 1);
11440 
11441         /* Set the tail. */
11442         tail = (ULONG*)local_cache_ptr + (local_cache_size >> 2) - 1;
11443         *tail = (ULONG)tail;
11444 
11445         /* Record the info.  */
11446         mdns_ptr -> nx_mdns_local_service_cache = (UCHAR*)local_cache_ptr;
11447         mdns_ptr -> nx_mdns_local_service_cache_size = local_cache_size;
11448 
11449         /* Clear the count.  */
11450         mdns_ptr -> nx_mdns_local_rr_count = 0;
11451         mdns_ptr -> nx_mdns_local_string_count = 0;
11452         mdns_ptr -> nx_mdns_local_string_bytes = 0;
11453     }
11454 #else
11455     NX_PARAMETER_NOT_USED(local_cache_ptr);
11456     NX_PARAMETER_NOT_USED(local_cache_size);
11457 #endif /* NX_MDNS_DISABLE_SERVER */
11458 
11459 #ifndef NX_MDNS_DISABLE_CLIENT
11460     /* Check the cache.  */
11461     if (peer_cache_ptr)
11462     {
11463 
11464         /* Zero out the cache. */
11465         memset(peer_cache_ptr, 0, peer_cache_size);
11466 
11467         /* Set the head. */
11468         head = (ULONG*)peer_cache_ptr;
11469         *head = (ULONG)((ULONG*)peer_cache_ptr + 1);
11470 
11471         /* Set the tail. */
11472         tail = (ULONG*)peer_cache_ptr + (peer_cache_size >> 2) - 1;
11473         *tail = (ULONG)tail;
11474 
11475         /* Record the info.  */
11476         mdns_ptr -> nx_mdns_peer_service_cache = (UCHAR*)peer_cache_ptr;
11477         mdns_ptr -> nx_mdns_peer_service_cache_size = peer_cache_size;
11478 
11479         /* Clear the count.  */
11480         mdns_ptr -> nx_mdns_peer_rr_count = 0;
11481         mdns_ptr -> nx_mdns_peer_string_count = 0;
11482         mdns_ptr -> nx_mdns_peer_string_bytes = 0;
11483     }
11484 #else
11485     NX_PARAMETER_NOT_USED(peer_cache_ptr);
11486     NX_PARAMETER_NOT_USED(peer_cache_size);
11487 #endif /* NX_MDNS_DISABLE_CLIENT */
11488 
11489     return(NX_SUCCESS);
11490 }
11491 
11492 
11493 /**************************************************************************/
11494 /*                                                                        */
11495 /*  FUNCTION                                               RELEASE        */
11496 /*                                                                        */
11497 /*    _nx_mdns_cache_add_resource_record                  PORTABLE C      */
11498 /*                                                           6.1          */
11499 /*  AUTHOR                                                                */
11500 /*                                                                        */
11501 /*    Yuxin Zhou, Microsoft Corporation                                   */
11502 /*                                                                        */
11503 /*  DESCRIPTION                                                           */
11504 /*                                                                        */
11505 /*    This function adds the mDNS  resource record into record buffer.    */
11506 /*                                                                        */
11507 /*  INPUT                                                                 */
11508 /*                                                                        */
11509 /*    mdns_ptr                              Pointer to mDNS instance      */
11510 /*    cache_type                            Cache type: local or peer     */
11511 /*    record_ptr                            Pointer to resource record    */
11512 /*    insert_rr                             Pointer to insert resource    */
11513 /*                                            record                      */
11514 /*                                                                        */
11515 /*  OUTPUT                                                                */
11516 /*                                                                        */
11517 /*    status                                Completion status             */
11518 /*                                                                        */
11519 /*  CALLS                                                                 */
11520 /*                                                                        */
11521 /*    _nx_mdns_cache_find_resource_record   Find the resource record      */
11522 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11523 /*                                                                        */
11524 /*  CALLED BY                                                             */
11525 /*                                                                        */
11526 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
11527 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
11528 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
11529 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
11530 /*    _nx_mdns_query                        Send query                    */
11531 /*    _nx_mdns_cache_delete_rr_string       Delete the rr string          */
11532 /*    _nx_mdns_packet_rr_process            Process resource record       */
11533 /*                                                                        */
11534 /*  RELEASE HISTORY                                                       */
11535 /*                                                                        */
11536 /*    DATE              NAME                      DESCRIPTION             */
11537 /*                                                                        */
11538 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11539 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11540 /*                                            verified memcpy use cases,  */
11541 /*                                            resulting in version 6.1    */
11542 /*                                                                        */
11543 /**************************************************************************/
_nx_mdns_cache_add_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,NX_MDNS_RR ** insert_ptr,UCHAR * is_present)11544 UINT _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present)
11545 {
11546 
11547 UCHAR       *cache_ptr;
11548 UINT        cache_size;
11549 ULONG       *tail;
11550 ULONG       *head;
11551 NX_MDNS_RR  *p;
11552 NX_MDNS_RR  *rr;
11553 UINT        rr_name_length;
11554 
11555 #ifndef NX_MDNS_DISABLE_CLIENT
11556 ULONG       elapsed_time;
11557 ULONG       current_time;
11558 ULONG       min_elapsed_time;
11559 #endif /* NX_MDNS_DISABLE_CLIENT  */
11560 
11561 
11562 #ifndef NX_MDNS_DISABLE_CLIENT
11563     /* Initialize the parameters.  */
11564     min_elapsed_time = 0;
11565     current_time = tx_time_get();
11566 #endif /* NX_MDNS_DISABLE_CLIENT  */
11567 
11568     /* Initialize.  */
11569     if (is_present)
11570         *is_present = NX_FALSE;
11571 
11572     /* Check the RR with same rname, rtype, rclass and rdata.  */
11573     if (_nx_mdns_cache_find_resource_record(mdns_ptr, cache_type, record_ptr, NX_MDNS_RR_MATCH_ALL, &rr) == NX_MDNS_SUCCESS)
11574     {
11575 
11576         /* Check string length.  */
11577         if (_nx_utility_string_length_check((CHAR *)(rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11578         {
11579             return(NX_MDNS_DATA_SIZE_ERROR);
11580         }
11581 
11582         /* Copy other informations of record_ptr into insert_rr resource record.  */
11583         memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11584 
11585         /* Special process for _services._dns-sd._udp.local which pointer to same service type.  */
11586         if ((rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
11587             (!_nx_mdns_name_match(rr -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
11588         {
11589             rr -> nx_mdns_rr_count ++;
11590         }
11591 
11592         /* Delete the resource record same strings. */
11593         _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, rr);
11594 
11595         /* Set the insert ptr.  */
11596         if(insert_ptr != NX_NULL)
11597             *insert_ptr = rr;
11598 
11599         /* Set the flag.  */
11600         if (is_present)
11601             *is_present = NX_TRUE;
11602 
11603         return(NX_MDNS_SUCCESS);
11604     }
11605 
11606     /* Check the cache type.  */
11607     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11608     {
11609         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11610         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
11611     }
11612     else
11613     {
11614         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11615         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
11616     }
11617 
11618     /* Check cache pointer and cache size.  */
11619     if ((cache_ptr == NX_NULL) || (cache_size == 0))
11620     {
11621         return(NX_MDNS_ERROR);
11622     }
11623 
11624     /* Get head and tail. */
11625     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
11626     tail = (ULONG*)(*tail);
11627     head = (ULONG*)cache_ptr;
11628     head = (ULONG*)(*head);
11629 
11630     /* Set the pointer.  */
11631     rr = NX_NULL;
11632 
11633     /* Find an empty entry before head. */
11634     for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11635     {
11636         if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11637         {
11638             rr = p;
11639             break;
11640         }
11641     }
11642 
11643     if (!rr)
11644     {
11645 
11646         /* Check whether the cache is full. */
11647         if((head + (sizeof(NX_MDNS_RR) >> 2)) > tail)
11648         {
11649             if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11650             {
11651                 return(NX_MDNS_CACHE_ERROR);
11652             }
11653             else
11654             {
11655 
11656 #ifndef NX_MDNS_DISABLE_CLIENT
11657                 /* Find an aging resource reocrd and repalce it.  */
11658                 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11659                 {
11660 
11661                     if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11662                         continue;
11663 
11664                     /* Calculate the elapsed time.  */
11665                     elapsed_time = current_time - p -> nx_mdns_rr_elapsed_time;
11666 
11667                     /* Check the elapsed time to find the aging resource record.  */
11668                     if (elapsed_time >= min_elapsed_time)
11669                     {
11670                         rr = p;
11671                         min_elapsed_time = elapsed_time;
11672                     }
11673                 }
11674 
11675                 if (rr)
11676                 {
11677 
11678                     /* Delete this record.  */
11679                     _nx_mdns_cache_delete_resource_record(mdns_ptr, cache_type, rr);
11680 
11681                     /* Update the head.  */
11682                     head = (ULONG*)cache_ptr;
11683                     head = (ULONG*)(*head);
11684                 }
11685                 else
11686                 {
11687                     return(NX_MDNS_CACHE_ERROR);
11688                 }
11689 #endif /* NX_MDNS_DISABLE_CLIENT */
11690             }
11691         }
11692         else
11693         {
11694             rr = (NX_MDNS_RR*)head;
11695         }
11696     }
11697 
11698     /* Just copy it to cache_ptr. */
11699     memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11700 
11701     /* Check the type.  */
11702     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11703     {
11704 
11705         /* Increase the count.  */
11706         mdns_ptr -> nx_mdns_local_rr_count ++;
11707     }
11708     else
11709     {
11710 
11711         /* Increase the count.  */
11712         mdns_ptr -> nx_mdns_peer_rr_count ++;
11713     }
11714 
11715 #ifndef NX_MDNS_DISABLE_CLIENT
11716     /* Update the peer resource record elapsed time.  */
11717     if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
11718     {
11719 
11720         /* Get the current time to set the elapsed time.  */
11721         rr -> nx_mdns_rr_elapsed_time = current_time;
11722     }
11723 #endif /* NX_MDNS_DISABLE_CLIENT */
11724 
11725     /* Set the insert ptr.  */
11726     if(insert_ptr != NX_NULL)
11727         *insert_ptr = rr;
11728 
11729     if((ULONG*)rr >= head)
11730     {
11731 
11732         /* Update HEAD when new record is added. */
11733         head = (ULONG*)cache_ptr;
11734         *head = (ULONG)(rr + 1);
11735     }
11736 
11737     return(NX_MDNS_SUCCESS);
11738 }
11739 
11740 
11741 /**************************************************************************/
11742 /*                                                                        */
11743 /*  FUNCTION                                               RELEASE        */
11744 /*                                                                        */
11745 /*    _nx_mdns_cache_delete_resource_record               PORTABLE C      */
11746 /*                                                           6.1          */
11747 /*  AUTHOR                                                                */
11748 /*                                                                        */
11749 /*    Yuxin Zhou, Microsoft Corporation                                   */
11750 /*                                                                        */
11751 /*  DESCRIPTION                                                           */
11752 /*                                                                        */
11753 /*    This function deletes the mDNS resource record from record buffer.  */
11754 /*                                                                        */
11755 /*  INPUT                                                                 */
11756 /*                                                                        */
11757 /*    mdns_ptr                              Pointer to mDNS instance.     */
11758 /*    cache_type                            Cache type: local or peer     */
11759 /*    record_ptr                            Pointer to resource record.   */
11760 /*                                                                        */
11761 /*  OUTPUT                                                                */
11762 /*                                                                        */
11763 /*    status                                Completion status             */
11764 /*                                                                        */
11765 /*  CALLS                                                                 */
11766 /*                                                                        */
11767 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11768 /*                                                                        */
11769 /*  CALLED BY                                                             */
11770 /*                                                                        */
11771 /*    _nx_mdns_rr_delete                    Delete the resource record    */
11772 /*    _nx_mdns_query                        Send the one-shot query       */
11773 /*    _nx_mdns_timer_event_process          Process the timer event       */
11774 /*    _nx_mdns_packet_process               Process mDNS packet           */
11775 /*    _nx_mdns_cache_delete_rr_string       Delete the rr string          */
11776 /*                                                                        */
11777 /*  RELEASE HISTORY                                                       */
11778 /*                                                                        */
11779 /*    DATE              NAME                      DESCRIPTION             */
11780 /*                                                                        */
11781 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11782 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11783 /*                                            resulting in version 6.1    */
11784 /*                                                                        */
11785 /**************************************************************************/
_nx_mdns_cache_delete_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr)11786 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr)
11787 {
11788 
11789 UCHAR       *cache_ptr;
11790 ULONG       *head;
11791 
11792 
11793     /* Delete the resource record strings. */
11794     _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, record_ptr);
11795 
11796     /* Zero out the record. */
11797     memset(record_ptr, 0, sizeof(NX_MDNS_RR));
11798 
11799     /* Check the type.  */
11800     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11801     {
11802 
11803         /* Decrease the count.  */
11804         mdns_ptr -> nx_mdns_local_rr_count --;
11805 
11806         /* Set the cache.  */
11807         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11808     }
11809     else
11810     {
11811 
11812         /* Decrease the count.  */
11813         mdns_ptr -> nx_mdns_peer_rr_count --;
11814 
11815         /* Set the cache.  */
11816         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11817     }
11818 
11819     if (cache_ptr == NX_NULL)
11820     {
11821         return(NX_MDNS_CACHE_ERROR);
11822     }
11823 
11824     /* Get head. */
11825     head = (ULONG*)cache_ptr;
11826     head = (ULONG*)(*head);
11827 
11828     /* Move HEAD if the last RR is deleted. */
11829     if(record_ptr == ((NX_MDNS_RR*)head - 1))
11830     {
11831         while(record_ptr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11832         {
11833             record_ptr--;
11834             if(record_ptr < (NX_MDNS_RR*)cache_ptr)
11835                 break;
11836         }
11837         *((ULONG*)cache_ptr) = (ULONG)(record_ptr + 1);
11838     }
11839 
11840     return(NX_MDNS_SUCCESS);
11841 }
11842 
11843 
11844 /**************************************************************************/
11845 /*                                                                        */
11846 /*  FUNCTION                                               RELEASE        */
11847 /*                                                                        */
11848 /*    _nx_mdns_cache_find_resource_record                 PORTABLE C      */
11849 /*                                                           6.1          */
11850 /*  AUTHOR                                                                */
11851 /*                                                                        */
11852 /*    Yuxin Zhou, Microsoft Corporation                                   */
11853 /*                                                                        */
11854 /*  DESCRIPTION                                                           */
11855 /*                                                                        */
11856 /*    This function finds the mDNS resource record in record buffer.      */
11857 /*                                                                        */
11858 /*  INPUT                                                                 */
11859 /*                                                                        */
11860 /*    mdns_ptr                              Pointer to mDNS instance.     */
11861 /*    cache_type                            Cache type: local or peer     */
11862 /*    record_ptr                            Resource record.              */
11863 /*    match_type                            Match type.                   */
11864 /*    search_rr                             The search resource record.   */
11865 /*                                                                        */
11866 /*  OUTPUT                                                                */
11867 /*                                                                        */
11868 /*    status                                Completion status             */
11869 /*                                                                        */
11870 /*  CALLS                                                                 */
11871 /*                                                                        */
11872 /*    None                                                                */
11873 /*                                                                        */
11874 /*  CALLED BY                                                             */
11875 /*                                                                        */
11876 /*    _nx_mdns_packet_process               Process mDNS packet           */
11877 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
11878 /*                                                                        */
11879 /*  RELEASE HISTORY                                                       */
11880 /*                                                                        */
11881 /*    DATE              NAME                      DESCRIPTION             */
11882 /*                                                                        */
11883 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11884 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11885 /*                                            resulting in version 6.1    */
11886 /*                                                                        */
11887 /**************************************************************************/
_nx_mdns_cache_find_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,UINT match_type,NX_MDNS_RR ** search_rr)11888 UINT _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_rr)
11889 {
11890 
11891 UCHAR       *cache_ptr;
11892 ULONG       *head;
11893 NX_MDNS_RR  *p;
11894 UINT        same_rdata;
11895 
11896 
11897     /* Check the cache type.  */
11898     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11899     {
11900         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11901     }
11902     else
11903     {
11904         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11905     }
11906 
11907     /* Get head. */
11908     head = (ULONG*)cache_ptr;
11909     head = (ULONG*)(*head);
11910 
11911     /* Find the same record.  */
11912     for(p = (NX_MDNS_RR*)((UCHAR*)cache_ptr + sizeof(ULONG)); (ULONG*)p < head; p++)
11913     {
11914 
11915         /* Check the interface index.  */
11916         if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
11917             continue;
11918 
11919         /* Check whether the resource record is valid. */
11920         if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11921             continue;
11922 
11923         /* Check whether the same record it is. RFC6762, Section6, Page13. */
11924         /* The rules: rrname must match the question name.
11925                       rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
11926                       rrclass must match the question qclass unless the qclass is "ANY". */
11927         if (p -> nx_mdns_rr_name != record_ptr -> nx_mdns_rr_name)
11928             continue;
11929 
11930         /* In the probing state, we need not match the type.  */
11931         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
11932         {
11933             if ((p -> nx_mdns_rr_type != record_ptr -> nx_mdns_rr_type) &&
11934                 (record_ptr -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
11935                 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
11936                 continue;
11937         }
11938 
11939         /* Check the RR class, Ignore the top bit.  */
11940         if ((p -> nx_mdns_rr_class != (record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
11941             ((record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK) != NX_MDNS_RR_CLASS_ALL))
11942             continue;
11943 
11944         /* Check if just match the basic info.  */
11945         if (match_type == NX_MDNS_RR_MATCH_EXCEPT_RDATA)
11946         {
11947 
11948             /* Find the same record.  */
11949             *search_rr = p;
11950             return(NX_MDNS_SUCCESS);
11951         }
11952         else
11953         {
11954 
11955             /* Yes, match all information of resource record.  */
11956 
11957             /* Check the state.  */
11958             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11959                 continue;
11960 
11961             /* Reset the value.  */
11962             same_rdata = NX_FALSE;
11963 
11964             /* Compare the RDATA. */
11965             switch (p -> nx_mdns_rr_type)
11966             {
11967                 case NX_MDNS_RR_TYPE_A:
11968                 {
11969                     if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address)
11970                     {
11971                         same_rdata = NX_TRUE;
11972                     }
11973                     break;
11974                 }
11975                 case NX_MDNS_RR_TYPE_SRV:
11976                 {
11977                     if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority) &&
11978                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights)   &&
11979                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port)         &&
11980                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11981                     {
11982                         same_rdata = NX_TRUE;
11983                     }
11984                     break;
11985                 }
11986                 case NX_MDNS_RR_TYPE_AAAA:
11987                 {
11988                     if(!memcmp(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, 16))
11989                     {
11990                         same_rdata = NX_TRUE;
11991                     }
11992                     break;
11993                 }
11994                 case NX_MDNS_RR_TYPE_PTR:
11995                 case NX_MDNS_RR_TYPE_TXT:
11996 
11997 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
11998                 case NX_MDNS_RR_TYPE_CNAME:
11999                 case NX_MDNS_RR_TYPE_NS:
12000 #endif
12001                 {
12002 
12003                     /* Check the rdata. */
12004                     if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
12005                     {
12006                         same_rdata = NX_TRUE;
12007                     }
12008                     break;
12009                 }
12010 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12011                 case NX_MDNS_RR_TYPE_MX:
12012                 {
12013                     if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name) &&
12014                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference))
12015                     {
12016                         same_rdata = NX_TRUE;
12017                     }
12018                     break;
12019                 }
12020 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
12021 
12022 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12023                 case NX_MDNS_RR_TYPE_NSEC:
12024                 {
12025                     if ((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain == record_ptr ->nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain) &&
12026                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block) &&
12027                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length) &&
12028                         (!memcmp(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12029                                  &(record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12030                                  record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length)))
12031                     {
12032                         same_rdata = NX_TRUE;
12033                     }
12034                     break;
12035                 }
12036 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12037                 default:
12038                 {
12039 
12040                     /* This is an unsupported or unknown type. */
12041                     return(NX_MDNS_UNSUPPORTED_TYPE);
12042                 }
12043             }
12044 
12045             /* Check the same RR.  */
12046             if (same_rdata == NX_TRUE)
12047             {
12048 
12049                 /* Find the same record.  */
12050                 *search_rr = p;
12051                 return(NX_MDNS_SUCCESS);
12052             }
12053         }
12054     }
12055 
12056     return(NX_MDNS_ERROR);
12057 }
12058 
12059 
12060 /**************************************************************************/
12061 /*                                                                        */
12062 /*  FUNCTION                                               RELEASE        */
12063 /*                                                                        */
12064 /*    _nx_mdns_cache_add_string                           PORTABLE C      */
12065 /*                                                           6.1          */
12066 /*  AUTHOR                                                                */
12067 /*                                                                        */
12068 /*    Yuxin Zhou, Microsoft Corporation                                   */
12069 /*                                                                        */
12070 /*  DESCRIPTION                                                           */
12071 /*                                                                        */
12072 /*    This function adds or finds the mDNS string in the record buffer.   */
12073 /*                                                                        */
12074 /*  INPUT                                                                 */
12075 /*                                                                        */
12076 /*    mdns_ptr                              Pointer to mDNS instance      */
12077 /*    cache_type                            Cache type: local or peer     */
12078 /*    memory_ptr                            Pointer to the string         */
12079 /*    memory_size                           The size of string.           */
12080 /*    insert_rr                             Pointer to insert string.     */
12081 /*    find_string                           If set, just find the existed */
12082 /*                                            string, otherwise, insert   */
12083 /*                                            this string if it does not  */
12084 /*                                            exist.                      */
12085 /*    add_name                              If set, use name match        */
12086 /*                                            to check the string,        */
12087 /*                                            otherwise, use memcmp.      */
12088 /*                                                                        */
12089 /*  OUTPUT                                                                */
12090 /*                                                                        */
12091 /*    status                                Completion status             */
12092 /*                                                                        */
12093 /*  CALLS                                                                 */
12094 /*                                                                        */
12095 /*    none                                                                */
12096 /*                                                                        */
12097 /*  CALLED BY                                                             */
12098 /*                                                                        */
12099 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
12100 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
12101 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
12102 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
12103 /*    _nx_mdns_query                        Send query                    */
12104 /*    _nx_mdns_conflict_process             Process the conflict          */
12105 /*    _nx_mdns_packet_rr_process            Process resource record       */
12106 /*                                                                        */
12107 /*  RELEASE HISTORY                                                       */
12108 /*                                                                        */
12109 /*    DATE              NAME                      DESCRIPTION             */
12110 /*                                                                        */
12111 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12112 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
12113 /*                                            verified memcpy use cases,  */
12114 /*                                            resulting in version 6.1    */
12115 /*                                                                        */
12116 /**************************************************************************/
_nx_mdns_cache_add_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * memory_ptr,UINT memory_size,VOID ** insert_ptr,UCHAR find_string,UCHAR add_name)12117 UINT _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *memory_ptr, UINT memory_size, VOID **insert_ptr, UCHAR find_string, UCHAR add_name)
12118 {
12119 
12120 UCHAR   *cache_ptr;
12121 UINT    cache_size;
12122 ULONG   *tail;
12123 ULONG   *head;
12124 UINT    memory_len;
12125 UINT    used_cache_size;
12126 USHORT  len, cnt;
12127 USHORT  min_len = 0xFFFF;
12128 UCHAR   *p, *available, *start;
12129 
12130 
12131     /* Check the cache type.  */
12132     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12133     {
12134         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12135         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12136     }
12137     else
12138     {
12139         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12140         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12141     }
12142 
12143     /* Check cache pointer and cache size.  */
12144     if ((cache_ptr == NX_NULL) || (cache_size == 0))
12145     {
12146         return(NX_MDNS_ERROR);
12147     }
12148 
12149     /* Get head and tail. */
12150     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12151     p = (UCHAR*)tail;
12152     tail = (ULONG*)(*tail);
12153     head = (ULONG*)cache_ptr;
12154     head = (ULONG*)(*head);
12155 
12156     /* Calculate the amount of memory needed to store this string, including CNT and LEN fields. */
12157 
12158     /* Make the length 4 bytes align. */
12159     memory_len = memory_size;
12160 
12161     /* Add the length of CNT and LEN fields.  */
12162     memory_len = ((memory_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12163 
12164     available = (UCHAR*)tail;
12165     while(p > (UCHAR*)tail)
12166     {
12167 
12168         /* Get len and cnt. */
12169         len = *((USHORT*)(p - 2));
12170         cnt = *((USHORT*)(p - 4));
12171         start = p - len;
12172 
12173         if((len == memory_len) &&
12174            (((add_name == NX_TRUE) &&
12175              (!_nx_mdns_name_match(start, memory_ptr, memory_size))) ||
12176             ((add_name == NX_FALSE) &&
12177              (!memcmp(start, memory_ptr, memory_size)))))
12178         {
12179 
12180             /* The same string exists in the string table. */
12181             if(insert_ptr)
12182                 *insert_ptr = start;
12183 
12184             if(find_string == NX_FALSE)
12185             {
12186 
12187                 /* Increase the use count CNT. */
12188                 cnt++;
12189                 *((USHORT*)(p - 4)) = cnt;
12190             }
12191 
12192             return(NX_MDNS_SUCCESS);
12193         }
12194 
12195         /* This slot is not being used. The size of the slot is a smaller
12196            fit for this string. */
12197         if((cnt == 0) && (len >= memory_len) && (len < min_len))
12198         {
12199 
12200             /* This place is better to insert. */
12201             available = p;
12202             min_len = len;
12203         }
12204 
12205         /* Move to the next string. */
12206         p = start;
12207     }
12208 
12209     if(find_string == NX_TRUE)
12210         return(NX_MDNS_ERROR);
12211 
12212     /* If we reach this point, the string needs to be added to the string table. */
12213     if(available == (UCHAR*)tail)
12214     {
12215 
12216         /* Make sure the service cache still has room to add this string
12217            (without overwriting the RR area.) */
12218         if(((UCHAR*)tail - memory_len) < (UCHAR*)head )
12219         {
12220 
12221             /* This service cache does not have room for the string table to grow. */
12222             /* Invoke user-installed cache full notify function .*/
12223             if(mdns_ptr -> nx_mdns_cache_full_notify)
12224             {
12225 
12226                 /* Calculate the fragment size, RR size, string size, Head and Tail. */
12227                 if(cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12228                 {
12229                     used_cache_size = mdns_ptr -> nx_mdns_local_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_local_string_bytes + 2 * sizeof(ULONG);
12230                 }
12231                 else
12232                 {
12233                     used_cache_size = mdns_ptr -> nx_mdns_peer_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_peer_string_bytes + 2 * sizeof(ULONG);
12234                 }
12235 
12236                 /* Check the cache.  */
12237                 if ((used_cache_size + memory_len) <= cache_size)
12238                 {
12239                     (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FRAGMENTED, cache_type);
12240                 }
12241                 else
12242                 {
12243                     (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FULL, cache_type);
12244                 }
12245             }
12246 
12247             /* The buffer is full. */
12248             return(NX_MDNS_CACHE_ERROR);
12249         }
12250 
12251         /* Update TAIL. */
12252         *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)(available - memory_len);
12253 
12254     }
12255     else if(memory_len < min_len)
12256     {
12257 
12258         /* Set the LEN for remaining space. */
12259         *((USHORT*)(available - 2 - memory_len)) = (USHORT)(min_len - memory_len);
12260     }
12261 
12262     /* Set LEN and CNT. */
12263     *((USHORT*)(available - 2)) = (USHORT)memory_len;
12264     *((USHORT*)(available - 4)) = 1;
12265 
12266     /* Clear last 4 bytes. */
12267     *((ULONG*)(available - 8)) = 0;
12268 
12269     /* Insert string to cache. */
12270     memcpy(available - memory_len, memory_ptr, memory_size); /* Use case of memcpy is verified. */
12271 
12272     /* Set end character 0. */
12273     *(available - memory_len + memory_size) = 0;
12274 
12275 
12276     /* Check the type.  */
12277     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12278     {
12279 
12280         /* Increase the count and bytes.  */
12281         mdns_ptr -> nx_mdns_local_string_count ++;
12282         mdns_ptr -> nx_mdns_local_string_bytes += memory_len;
12283     }
12284     else
12285     {
12286 
12287         /* Increase the count and bytes.  */
12288         mdns_ptr -> nx_mdns_peer_string_count ++;
12289         mdns_ptr -> nx_mdns_peer_string_bytes += memory_len;
12290     }
12291 
12292     if(insert_ptr)
12293         *insert_ptr = available - memory_len;
12294 
12295     return(NX_MDNS_SUCCESS);
12296 }
12297 
12298 
12299 /**************************************************************************/
12300 /*                                                                        */
12301 /*  FUNCTION                                               RELEASE        */
12302 /*                                                                        */
12303 /*    _nx_mdns_cache_delete_string                        PORTABLE C      */
12304 /*                                                           6.1          */
12305 /*  AUTHOR                                                                */
12306 /*                                                                        */
12307 /*    Yuxin Zhou, Microsoft Corporation                                   */
12308 /*                                                                        */
12309 /*  DESCRIPTION                                                           */
12310 /*                                                                        */
12311 /*    This function deletes the mDNS string from the record buffer.       */
12312 /*                                                                        */
12313 /*  INPUT                                                                 */
12314 /*                                                                        */
12315 /*    mdns_ptr                              Pointer to mDNS instance      */
12316 /*    cache_type                            Cache type: local or peer     */
12317 /*    string_ptr                            Pointer to the string         */
12318 /*    string_len                            The length of string          */
12319 /*                                                                        */
12320 /*  OUTPUT                                                                */
12321 /*                                                                        */
12322 /*    status                                Completion status             */
12323 /*                                                                        */
12324 /*  CALLS                                                                 */
12325 /*                                                                        */
12326 /*    None                                                                */
12327 /*                                                                        */
12328 /*  CALLED BY                                                             */
12329 /*                                                                        */
12330 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
12331 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
12332 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
12333 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
12334 /*    _nx_mdns_query                        Send query                    */
12335 /*    _nx_mdns_conflict_process             Process the conflict          */
12336 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
12337 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
12338 /*    _nx_mdns_packet_rr_process            Process resource record       */
12339 /*                                                                        */
12340 /*  RELEASE HISTORY                                                       */
12341 /*                                                                        */
12342 /*    DATE              NAME                      DESCRIPTION             */
12343 /*                                                                        */
12344 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12345 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12346 /*                                            resulting in version 6.1    */
12347 /*                                                                        */
12348 /**************************************************************************/
_nx_mdns_cache_delete_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * string_ptr,UINT string_len)12349 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len)
12350 {
12351 
12352 UCHAR   *cache_ptr;
12353 UINT    cache_size;
12354 ULONG   *tail;
12355 ULONG   *end;
12356 USHORT  cnt;
12357 
12358 
12359     /* Check the cache type.  */
12360     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12361     {
12362         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12363         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12364     }
12365     else
12366     {
12367         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12368         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12369     }
12370 
12371     /* Check cache pointer and cache size.  */
12372     if ((cache_ptr == NX_NULL) || (cache_size == 0))
12373     {
12374         return(NX_MDNS_ERROR);
12375     }
12376 
12377     /* Validate input parameter. */
12378     if(string_ptr == NX_NULL)
12379         return(NX_MDNS_PARAM_ERROR);
12380 
12381     /* Check if input the string length.  */
12382     if (string_len == 0)
12383     {
12384 
12385         /* Check string length.  */
12386         if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12387         {
12388             return(NX_MDNS_DATA_SIZE_ERROR);
12389         }
12390     }
12391 
12392     /* Add the length of CNT and LEN fields.  */
12393     /* Also make the total length 4 bytes align. */
12394     string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12395 
12396     end = (ULONG*)((UCHAR*)string_ptr + string_len);
12397 
12398     /* Get tail. */
12399 
12400     /* Validate the string table. */
12401     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12402     if(end > tail)
12403     {
12404 
12405         /* The end of string exceeds cache_ptr. */
12406         return(NX_MDNS_CACHE_ERROR);
12407     }
12408     tail = (ULONG*)(*tail);
12409     if((UCHAR*)string_ptr < (UCHAR*)tail)
12410     {
12411 
12412         /* The end of string exceeds cache_ptr. */
12413         return(NX_MDNS_CACHE_ERROR);
12414     }
12415 
12416     /* Decrease the usage counter value. */
12417     cnt = *((USHORT*)((UCHAR*)end - 4));
12418     cnt--;
12419     *((USHORT*)((UCHAR*)end - 4)) = cnt;
12420 
12421     /* Clear the memory if cnt is zero. */
12422     if(cnt == 0)
12423     {
12424         memset(string_ptr, 0, string_len - 2);
12425 
12426         /* Check the type.  */
12427         if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12428         {
12429 
12430             /* Increase the count and bytes.  */
12431             mdns_ptr -> nx_mdns_local_string_count --;
12432             mdns_ptr -> nx_mdns_local_string_bytes -= string_len;
12433         }
12434         else
12435         {
12436 
12437             /* Increase the count and bytes.  */
12438             mdns_ptr -> nx_mdns_peer_string_count --;
12439             mdns_ptr -> nx_mdns_peer_string_bytes -= string_len;
12440         }
12441 
12442         /* Update the tail pointer if the string at the tail is deleted. */
12443         if(string_ptr == tail)
12444         {
12445             tail = end;
12446 
12447             while((end < ((ULONG*)cache_ptr + (cache_size >> 2) - 1)))
12448             {
12449 
12450                 /* Set the string pt and string length.  */
12451                 string_ptr = end;
12452 
12453                 /* Check string length.  */
12454                 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12455                 {
12456                     return(NX_MDNS_DATA_SIZE_ERROR);
12457                 }
12458 
12459                 /* Check the string length.  */
12460                 if(string_len == 0)
12461                 {
12462 
12463                     /* This slot is cleared. */
12464                     while(*((ULONG*)string_ptr) == 0)
12465                         string_ptr = (UCHAR*)string_ptr + 4;
12466 
12467                     end = (ULONG*)string_ptr + 1;
12468                     cnt = *((USHORT*)string_ptr);
12469                 }
12470                 else
12471                 {
12472 
12473                     /* Make the length 4 bytes align and add the length of CNT and LEN fields.  */
12474                     string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12475 
12476                     end = (ULONG*)((UCHAR*)string_ptr + string_len);
12477                     cnt = *((USHORT*)((UCHAR*)end - 4));
12478                 }
12479 
12480                 /* Check whether this slot is never referenced. */
12481                 if(cnt == 0)
12482                     tail = end;
12483                 else
12484                     break;
12485             }
12486             *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)tail;
12487         }
12488     }
12489 
12490     return(NX_MDNS_SUCCESS);
12491 }
12492 
12493 
12494 /**************************************************************************/
12495 /*                                                                        */
12496 /*  FUNCTION                                               RELEASE        */
12497 /*                                                                        */
12498 /*    _nx_mdns_cache_delete_rr_string                     PORTABLE C      */
12499 /*                                                           6.1          */
12500 /*  AUTHOR                                                                */
12501 /*                                                                        */
12502 /*    Yuxin Zhou, Microsoft Corporation                                   */
12503 /*                                                                        */
12504 /*  DESCRIPTION                                                           */
12505 /*                                                                        */
12506 /*    This function deletes the mDNS string from the record buffer.       */
12507 /*                                                                        */
12508 /*  INPUT                                                                 */
12509 /*                                                                        */
12510 /*    mdns_ptr                              Pointer to mDNS instance      */
12511 /*    cache_type                            Cache type: local or peer     */
12512 /*    string_ptr                            Pointer to the string         */
12513 /*                                                                        */
12514 /*  OUTPUT                                                                */
12515 /*                                                                        */
12516 /*    None                                                                */
12517 /*                                                                        */
12518 /*  CALLS                                                                 */
12519 /*                                                                        */
12520 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
12521 /*                                                                        */
12522 /*  CALLED BY                                                             */
12523 /*                                                                        */
12524 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
12525 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
12526 /*                                                                        */
12527 /*  RELEASE HISTORY                                                       */
12528 /*                                                                        */
12529 /*    DATE              NAME                      DESCRIPTION             */
12530 /*                                                                        */
12531 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12532 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12533 /*                                            resulting in version 6.1    */
12534 /*                                                                        */
12535 /**************************************************************************/
_nx_mdns_cache_delete_rr_string(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_rr)12536 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr)
12537 {
12538 
12539     /* Delete the  name strings. */
12540     _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_name, 0);
12541 
12542     /* Check if need to release the rdata string.  */
12543     if (record_rr -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
12544     {
12545 
12546         if (((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
12547              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12548              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
12549 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12550              ||
12551              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
12552 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12553 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12554              ||
12555              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_CNAME) ||
12556              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NS) ||
12557              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_MX)
12558 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
12559             ) &&
12560             (record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
12561         {
12562 
12563             /* Delete the same strings. */
12564             _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
12565         }
12566     }
12567 }
12568 
12569 
12570 #ifndef NX_MDNS_DISABLE_SERVER
12571 /**************************************************************************/
12572 /*                                                                        */
12573 /*  FUNCTION                                               RELEASE        */
12574 /*                                                                        */
12575 /*    _nx_mdns_additional_resource_record_find            PORTABLE C      */
12576 /*                                                           6.1          */
12577 /*  AUTHOR                                                                */
12578 /*                                                                        */
12579 /*    Yuxin Zhou, Microsoft Corporation                                   */
12580 /*                                                                        */
12581 /*  DESCRIPTION                                                           */
12582 /*                                                                        */
12583 /*    This function find the mDNS additional resource record.             */
12584 /*                                                                        */
12585 /*  INPUT                                                                 */
12586 /*                                                                        */
12587 /*    mdns_ptr                              Pointer to mDNS instance      */
12588 /*    record_ptr                            Pointer to record instance    */
12589 /*                                                                        */
12590 /*  OUTPUT                                                                */
12591 /*                                                                        */
12592 /*    status                                Completion status             */
12593 /*                                                                        */
12594 /*  CALLS                                                                 */
12595 /*                                                                        */
12596 /*    None                                                                */
12597 /*                                                                        */
12598 /*  CALLED BY                                                             */
12599 /*                                                                        */
12600 /*    _nx_mdns_response_send                Send response message         */
12601 /*                                                                        */
12602 /*  RELEASE HISTORY                                                       */
12603 /*                                                                        */
12604 /*    DATE              NAME                      DESCRIPTION             */
12605 /*                                                                        */
12606 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12607 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12608 /*                                            resulting in version 6.1    */
12609 /*                                                                        */
12610 /**************************************************************************/
_nx_mdns_additional_resource_record_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12611 UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12612 {
12613 
12614 ULONG           *head;
12615 NX_MDNS_RR      *p;
12616 
12617     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12618     head = (ULONG*)(*head);
12619 
12620     /* Find the additional resource records according to the type.  */
12621     switch (record_ptr -> nx_mdns_rr_type )
12622     {
12623 
12624         case NX_MDNS_RR_TYPE_A:
12625         case NX_MDNS_RR_TYPE_AAAA:
12626         {
12627 
12628             /* Recommends AAAA records in the additional section when responding
12629                to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51.  */
12630             _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_interface_index);
12631 
12632             break;
12633         }
12634 
12635         case NX_MDNS_RR_TYPE_PTR:
12636         {
12637 
12638             /* Find the additional resource record.  */
12639             for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12640             {
12641 
12642                 /* Check the interface.  */
12643                 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12644                     continue;
12645 
12646                 /* The SRV record(s) named in the PTR rdata.
12647                    The TXT record(s) named in the PTR rdata.
12648                    All address records (type "A" and "AAAA") named in the SRV rdata. RFC6763, Section12.1, Page30.*/
12649 
12650                 /* The SRV records named in the PTR rdata */
12651                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
12652                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12653                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12654                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12655                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12656                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12657                 {
12658 
12659                     /* Set the flag to add this resource records into additional records.  */
12660                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12661 
12662                     /* All address records (type "A" and "AAAA") named in the SRV rdata */
12663                     _nx_mdns_additional_a_aaaa_find(mdns_ptr, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12664                 }
12665 
12666                 /* The TXT records named in the PTR rdata */
12667                 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12668                      (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)) &&
12669                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12670                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12671                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12672                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12673                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12674                 {
12675 
12676                     /* Set the flag to add this resource records into additional records.  */
12677                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12678                 }
12679             }
12680 
12681             break;
12682         }
12683 
12684         case NX_MDNS_RR_TYPE_SRV:
12685         case NX_MDNS_RR_TYPE_TXT:
12686         {
12687 
12688 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12689             /* Find the additional resource record.  */
12690             for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12691             {
12692 
12693                 /* Check the interface.  */
12694                 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12695                     continue;
12696 
12697                 /* The NSEC records named same as SRV/TXT name.  */
12698                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
12699                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_name) &&
12700                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12701                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12702                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12703                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12704                 {
12705 
12706                     /* Set the flag to add this resource records into additional records.  */
12707                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12708                 }
12709             }
12710 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12711 
12712             /* All address records (type "A" and "AAAA") named in the SRV rdata */
12713             if (record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
12714                 _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12715             break;
12716         }
12717     }
12718 
12719     return(NX_MDNS_SUCCESS);
12720 }
12721 
12722 
12723 /**************************************************************************/
12724 /*                                                                        */
12725 /*  FUNCTION                                               RELEASE        */
12726 /*                                                                        */
12727 /*    _nx_mdns_additional_a_aaaa_find                     PORTABLE C      */
12728 /*                                                           6.1          */
12729 /*  AUTHOR                                                                */
12730 /*                                                                        */
12731 /*    Yuxin Zhou, Microsoft Corporation                                   */
12732 /*                                                                        */
12733 /*  DESCRIPTION                                                           */
12734 /*                                                                        */
12735 /*    This function find the mDNS additional A/AAAA resource record.      */
12736 /*                                                                        */
12737 /*  INPUT                                                                 */
12738 /*                                                                        */
12739 /*    mdns_ptr                              Pointer to mDNS instance      */
12740 /*    record_ptr                            Pointer to record instance    */
12741 /*                                                                        */
12742 /*  OUTPUT                                                                */
12743 /*                                                                        */
12744 /*    status                                Completion status             */
12745 /*                                                                        */
12746 /*  CALLS                                                                 */
12747 /*                                                                        */
12748 /*    None                                                                */
12749 /*                                                                        */
12750 /*  CALLED BY                                                             */
12751 /*                                                                        */
12752 /*    _nx_mdns_additional_resource_record_find                            */
12753 /*                                          Find additional record        */
12754 /*                                                                        */
12755 /*  RELEASE HISTORY                                                       */
12756 /*                                                                        */
12757 /*    DATE              NAME                      DESCRIPTION             */
12758 /*                                                                        */
12759 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12760 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12761 /*                                            resulting in version 6.1    */
12762 /*                                                                        */
12763 /**************************************************************************/
_nx_mdns_additional_a_aaaa_find(NX_MDNS * mdns_ptr,UCHAR * name,UINT interface_index)12764 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index)
12765 {
12766 
12767 ULONG           *head;
12768 NX_MDNS_RR      *p;
12769 
12770     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12771     head = (ULONG*)(*head);
12772 
12773     /* Recommends AAAA records in the additional section when responding
12774        to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51.  */
12775     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12776     {
12777 
12778         /* Check the interface index.  */
12779         if (p -> nx_mdns_rr_interface_index != interface_index)
12780             continue;
12781 
12782         /* Find the "A" records.  */
12783         if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
12784              (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA ||
12785              (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))) &&
12786             (p -> nx_mdns_rr_name == name) &&
12787             ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12788             (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12789             (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12790             (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12791         {
12792 
12793             /* Set the flag to add this resource records into additional records.  */
12794             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12795         }
12796     }
12797 }
12798 #endif /* NX_MDNS_DISABLE_SERVER */
12799 
12800 
12801 #ifndef NX_MDNS_DISABLE_CLIENT
12802 /**************************************************************************/
12803 /*                                                                        */
12804 /*  FUNCTION                                               RELEASE        */
12805 /*                                                                        */
12806 /*    _nx_mdns_known_answer_find                          PORTABLE C      */
12807 /*                                                           6.1          */
12808 /*  AUTHOR                                                                */
12809 /*                                                                        */
12810 /*    Yuxin Zhou, Microsoft Corporation                                   */
12811 /*                                                                        */
12812 /*  DESCRIPTION                                                           */
12813 /*                                                                        */
12814 /*    This function finds the mDNS known answer.                          */
12815 /*                                                                        */
12816 /*  INPUT                                                                 */
12817 /*                                                                        */
12818 /*    mdns_ptr                              Pointer to mDNS instance      */
12819 /*    record_ptr                            Pointer to record instance    */
12820 /*                                                                        */
12821 /*  OUTPUT                                                                */
12822 /*                                                                        */
12823 /*    status                                Completion status             */
12824 /*                                                                        */
12825 /*  CALLS                                                                 */
12826 /*                                                                        */
12827 /*    None                                                                */
12828 /*                                                                        */
12829 /*  CALLED BY                                                             */
12830 /*                                                                        */
12831 /*    _nx_mdns_query_send                   Send query message            */
12832 /*    _nx_mdns_packet_process               Process mDNS packet           */
12833 /*                                                                        */
12834 /*  RELEASE HISTORY                                                       */
12835 /*                                                                        */
12836 /*    DATE              NAME                      DESCRIPTION             */
12837 /*                                                                        */
12838 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12839 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12840 /*                                            resulting in version 6.1    */
12841 /*                                                                        */
12842 /**************************************************************************/
_nx_mdns_known_answer_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12843 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12844 {
12845 
12846 UINT            status = NX_MDNS_NO_KNOWN_ANSWER;
12847 ULONG           *head, *tail;
12848 NX_MDNS_RR      *p;
12849 UINT            i;
12850 UINT            name_length;
12851 #ifndef NX_MDNS_DISABLE_SERVER
12852 UINT            cache_count = 2;
12853 #else
12854 UINT            cache_count = 1;
12855 #endif
12856 
12857     /* Check string length.  */
12858     if (_nx_utility_string_length_check((CHAR *)(record_ptr -> nx_mdns_rr_name), &name_length, NX_MDNS_NAME_MAX))
12859     {
12860         return(NX_MDNS_DATA_SIZE_ERROR);
12861     }
12862 
12863     /* Loop to find the known answer in cache.  */
12864     for (i = 0; i < cache_count; i++)
12865     {
12866 
12867         /* Set the pointer. */
12868         if (i == 0)
12869         {
12870             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12871         }
12872 #ifndef NX_MDNS_DISABLE_SERVER
12873         else
12874         {
12875             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12876         }
12877 #endif /* NX_MDNS_DISABLE_SERVER  */
12878         tail = (ULONG*)(*head);
12879 
12880         /* Whether this mDNS message response to query. */
12881         for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
12882         {
12883 
12884             /* Check the state.  */
12885             if(p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_VALID)
12886                 continue;
12887 
12888             /* Check the interface index.  */
12889             if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12890                 continue;
12891 
12892             /* Check whether the Known Answer record it is. */
12893             if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_name, name_length)) &&
12894                 (p -> nx_mdns_rr_class == record_ptr -> nx_mdns_rr_class))
12895             {
12896 
12897                 if ((record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) ||
12898                     (p -> nx_mdns_rr_type == record_ptr -> nx_mdns_rr_type))
12899                 {
12900 
12901                     /* Set the additional flag.  */
12902                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_KNOWN_ANSWER;
12903 
12904                     /* Yes, find the known answer.  */
12905                     status = NX_MDNS_SUCCESS;
12906                 }
12907             }
12908         }
12909     }
12910 
12911     return(status);
12912 }
12913 #endif /* NX_MDNS_DISABLE_CLIENT */
12914 
12915 
12916 #ifndef NX_MDNS_DISABLE_CLIENT
12917 /**************************************************************************/
12918 /*                                                                        */
12919 /*  FUNCTION                                               RELEASE        */
12920 /*                                                                        */
12921 /*    _nx_mdns_query_check                                PORTABLE C      */
12922 /*                                                           6.1.11       */
12923 /*  AUTHOR                                                                */
12924 /*                                                                        */
12925 /*    Yuxin Zhou, Microsoft Corporation                                   */
12926 /*                                                                        */
12927 /*  DESCRIPTION                                                           */
12928 /*                                                                        */
12929 /*    This function checks whether mDNS querier already has one Unique    */
12930 /*    record in the local buffer/remote buffer or one same query in the   */
12931 /*    remote buffer.                                                      */
12932 /*                                                                        */
12933 /*  INPUT                                                                 */
12934 /*                                                                        */
12935 /*    mdns_ptr                              Pointer to mDNS instance      */
12936 /*    name                                  The resource record name      */
12937 /*    type                                  The resource record type      */
12938 /*    interface_index                       The interface index           */
12939 /*                                                                        */
12940 /*  OUTPUT                                                                */
12941 /*                                                                        */
12942 /*    status                                Completion status             */
12943 /*                                                                        */
12944 /*  CALLS                                                                 */
12945 /*                                                                        */
12946 /*    None                                                                */
12947 /*                                                                        */
12948 /*  CALLED BY                                                             */
12949 /*                                                                        */
12950 /*    _nx_mdns_query                        Send the query                */
12951 /*                                                                        */
12952 /*  RELEASE HISTORY                                                       */
12953 /*                                                                        */
12954 /*    DATE              NAME                      DESCRIPTION             */
12955 /*                                                                        */
12956 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12957 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12958 /*                                            resulting in version 6.1    */
12959 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
12960 /*                                            corrected the random value, */
12961 /*                                            resulting in version 6.1.11 */
12962 /*                                                                        */
12963 /**************************************************************************/
_nx_mdns_query_check(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT one_shot,NX_MDNS_RR ** search_rr,UINT interface_index)12964 static UINT _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index)
12965 {
12966 
12967 ULONG       *head;
12968 NX_MDNS_RR  *p;
12969 UCHAR       i;
12970 UCHAR       same_query = NX_FALSE;
12971 NX_MDNS_RR  *rr = NX_NULL;
12972 UCHAR       srv_flag = NX_FALSE;
12973 UCHAR       txt_flag = NX_FALSE;
12974 UINT        name_length;
12975 
12976 
12977     /* Check string length.  */
12978     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
12979     {
12980         return(NX_MDNS_DATA_SIZE_ERROR);
12981     }
12982 
12983     for(i = 0; i < 2; i++)
12984     {
12985         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
12986             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12987         else
12988             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12989 
12990         if(head)
12991         {
12992             for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
12993             {
12994 
12995                 /* Check whether the resource record is valid. */
12996                 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
12997                     continue;
12998 
12999                 /* Check the interface index.  */
13000                 if (p -> nx_mdns_rr_interface_index != interface_index)
13001                     continue;
13002 
13003                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, name, name_length))
13004                 {
13005                     if ((p -> nx_mdns_rr_type == type) && (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
13006                     {
13007 
13008                         /* Set the query.  */
13009                         same_query = NX_TRUE;
13010 
13011                         /* Record the RR potiner.  */
13012                         rr = p;
13013                     }
13014 
13015                     /* Check the rr type.  */
13016                     if (p -> nx_mdns_rr_type  == NX_MDNS_RR_TYPE_SRV)
13017                         srv_flag = NX_TRUE;
13018                     if (p -> nx_mdns_rr_type  == NX_MDNS_RR_TYPE_TXT)
13019                         txt_flag = NX_TRUE;
13020 
13021                     if ((p -> nx_mdns_rr_type == type) ||
13022                         ((type == NX_MDNS_RR_TYPE_ALL) && (srv_flag == NX_TRUE) && (txt_flag == NX_TRUE)))
13023                     {
13024                         if (search_rr)
13025                             *search_rr = p;
13026 
13027                         /* Check the query type.  */
13028                         if (one_shot == NX_TRUE)
13029                             return(NX_MDNS_EXIST_SHARED_RR);
13030 
13031                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
13032                             return(NX_MDNS_EXIST_UNIQUE_RR);
13033                     }
13034                 }
13035             }
13036         }
13037     }
13038 
13039     /* Check the same query.  */
13040     if (same_query == NX_TRUE)
13041     {
13042 
13043         /* A multicast DNS querier should also delay the first query of the series by
13044            a randomly chosen amount in the range 20-120ms.  */
13045         rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
13046         rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
13047 
13048         /* Set the mDNS timer.  */
13049         _nx_mdns_timer_set(mdns_ptr, rr, rr -> nx_mdns_rr_timer_count);
13050 
13051         return (NX_MDNS_EXIST_SAME_QUERY);
13052     }
13053 
13054     /* Return a successful status.  */
13055     return(NX_SUCCESS);
13056 }
13057 
13058 
13059 /**************************************************************************/
13060 /*                                                                        */
13061 /*  FUNCTION                                               RELEASE        */
13062 /*                                                                        */
13063 /*    _nx_mdns_query_cleanup                              PORTABLE C      */
13064 /*                                                           6.1          */
13065 /*  AUTHOR                                                                */
13066 /*                                                                        */
13067 /*    Yuxin Zhou, Microsoft Corporation                                   */
13068 /*                                                                        */
13069 /*  DESCRIPTION                                                           */
13070 /*                                                                        */
13071 /*    This function processes mDNS One-shot query timeout and thread      */
13072 /*    terminate actions that require the mDNS data structures to be       */
13073 /*    cleaned up.                                                         */
13074 /*                                                                        */
13075 /*  INPUT                                                                 */
13076 /*                                                                        */
13077 /*    thread_ptr                            Pointer to suspended thread's */
13078 /*                                            control block               */
13079 /*                                                                        */
13080 /*  OUTPUT                                                                */
13081 /*                                                                        */
13082 /*    None                                                                */
13083 /*                                                                        */
13084 /*  CALLS                                                                 */
13085 /*                                                                        */
13086 /*    _tx_thread_system_resume              Resume thread service         */
13087 /*                                                                        */
13088 /*  CALLED BY                                                             */
13089 /*                                                                        */
13090 /*    _tx_thread_timeout                    Thread timeout processing     */
13091 /*    _tx_thread_terminate                  Thread terminate processing   */
13092 /*                                                                        */
13093 /*  RELEASE HISTORY                                                       */
13094 /*                                                                        */
13095 /*    DATE              NAME                      DESCRIPTION             */
13096 /*                                                                        */
13097 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13098 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13099 /*                                            resulting in version 6.1    */
13100 /*                                                                        */
13101 /**************************************************************************/
_nx_mdns_query_cleanup(TX_THREAD * thread_ptr NX_CLEANUP_PARAMETER)13102 VOID  _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER)
13103 {
13104 
13105 TX_INTERRUPT_SAVE_AREA
13106 
13107 NX_MDNS     *mdns_ptr;
13108 
13109 
13110     NX_CLEANUP_EXTENSION
13111 
13112     /* Setup pointer to UDP socket control block.  */
13113     mdns_ptr =  (NX_MDNS *) thread_ptr -> tx_thread_suspend_control_block;
13114 
13115     /* Disable interrupts to remove the suspended thread from the UDP socket.  */
13116     TX_DISABLE
13117 
13118     /* Determine if the cleanup is still required.  */
13119     if ((thread_ptr -> tx_thread_suspend_cleanup) && (mdns_ptr) &&
13120         (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
13121     {
13122 
13123         /* Yes, we still have thread suspension!  */
13124 
13125         /* Clear the suspension cleanup flag.  */
13126         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
13127 
13128         /* Remove the suspended thread from the list.  */
13129 
13130         /* See if this is the only suspended thread on the list.  */
13131         if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13132         {
13133 
13134             /* Yes, the only suspended thread.  */
13135 
13136             /* Update the head pointer.  */
13137             mdns_ptr -> nx_mdns_rr_receive_suspension_list =  NX_NULL;
13138         }
13139         else
13140         {
13141 
13142             /* At least one more thread is on the same suspension list.  */
13143 
13144             /* Update the list head pointer.  */
13145             mdns_ptr -> nx_mdns_rr_receive_suspension_list =  thread_ptr -> tx_thread_suspended_next;
13146 
13147             /* Update the links of the adjacent threads.  */
13148             (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13149             (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13150         }
13151 
13152         /* Decrement the suspension count.  */
13153         mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13154 
13155         /* Now we need to determine if this cleanup is from a terminate, timeout,
13156            or from a wait abort.  */
13157         if (thread_ptr -> tx_thread_state == TX_TCP_IP)
13158         {
13159 
13160             /* Thread still suspended on the UDP socket.  Setup return error status and
13161                resume the thread.  */
13162 
13163             /* Setup return status.  */
13164             thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13165 
13166             /* Temporarily disable preemption.  */
13167             _tx_thread_preempt_disable++;
13168 
13169             /* Restore interrupts.  */
13170             TX_RESTORE
13171 
13172             /* Resume the thread!  Check for preemption even though we are executing
13173                from the system timer thread right now which normally executes at the
13174                highest priority.  */
13175             _tx_thread_system_resume(thread_ptr);
13176 
13177             /* Finished, just return.  */
13178             return;
13179         }
13180     }
13181 
13182     /* Restore interrupts.  */
13183     TX_RESTORE
13184 }
13185 
13186 
13187 /**************************************************************************/
13188 /*                                                                        */
13189 /*  FUNCTION                                               RELEASE        */
13190 /*                                                                        */
13191 /*    _nx_mdns_query_thread_suspend                       PORTABLE C      */
13192 /*                                                           6.1          */
13193 /*  AUTHOR                                                                */
13194 /*                                                                        */
13195 /*    Yuxin Zhou, Microsoft Corporation                                   */
13196 /*                                                                        */
13197 /*  DESCRIPTION                                                           */
13198 /*                                                                        */
13199 /*    This function suspends a thread on a mDNS client query service      */
13200 /*                                                                        */
13201 /*  INPUT                                                                 */
13202 /*                                                                        */
13203 /*    suspension_list_head                  Pointer to the suspension list*/
13204 /*    mutex_ptr                             Pointer to mutex to release   */
13205 /*    suspend_cleanup                       Suspension cleanup routine    */
13206 /*    wait_option                           Optional timeout value        */
13207 /*                                                                        */
13208 /*  OUTPUT                                                                */
13209 /*                                                                        */
13210 /*    None                                                                */
13211 /*                                                                        */
13212 /*  CALLS                                                                 */
13213 /*                                                                        */
13214 /*    tx_mutex_put                          Release protection            */
13215 /*    _tx_thread_system_suspend             Suspend thread                */
13216 /*                                                                        */
13217 /*  CALLED BY                                                             */
13218 /*                                                                        */
13219 /*                                                                        */
13220 /*  RELEASE HISTORY                                                       */
13221 /*                                                                        */
13222 /*    DATE              NAME                      DESCRIPTION             */
13223 /*                                                                        */
13224 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13225 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13226 /*                                            resulting in version 6.1    */
13227 /*                                                                        */
13228 /**************************************************************************/
_nx_mdns_query_thread_suspend(TX_THREAD ** suspension_list_head,VOID (* suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),NX_MDNS * mdns_ptr,NX_MDNS_RR ** rr,ULONG wait_option)13229 VOID  _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
13230                                     NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option)
13231 {
13232 
13233 TX_INTERRUPT_SAVE_AREA
13234 
13235 TX_THREAD *thread_ptr;
13236 
13237 
13238     /* Lockout interrupts.  */
13239     TX_DISABLE
13240 
13241     /* Pickup thread pointer.  */
13242     thread_ptr =  _tx_thread_current_ptr;
13243 
13244     /* Setup suspension list.  */
13245     if (*suspension_list_head)
13246     {
13247 
13248         /* This list is not NULL, add current thread to the end. */
13249         thread_ptr -> tx_thread_suspended_next = *suspension_list_head;
13250         thread_ptr -> tx_thread_suspended_previous = (*suspension_list_head) -> tx_thread_suspended_previous;
13251         ((*suspension_list_head) -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr;
13252         (*suspension_list_head) -> tx_thread_suspended_previous = thread_ptr;
13253     }
13254     else
13255     {
13256 
13257         /* No other threads are suspended.  Setup the head pointer and
13258             just setup this threads pointers to itself.  */
13259         *suspension_list_head = thread_ptr;
13260         thread_ptr -> tx_thread_suspended_next = thread_ptr;
13261         thread_ptr -> tx_thread_suspended_previous = thread_ptr;
13262     }
13263 
13264     /* Setup return status.  */
13265     thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13266 
13267     /* Setup cleanup routine pointer.  */
13268     thread_ptr -> tx_thread_suspend_cleanup = suspend_cleanup;
13269 
13270     /* Setup cleanup information, i.e. this pool control block.  */
13271     thread_ptr -> tx_thread_suspend_control_block = (void *)mdns_ptr;
13272 
13273     /* Save the return RR pointer address as well.  */
13274     thread_ptr -> tx_thread_additional_suspend_info = (void *)rr;
13275 
13276     /* Increment the suspended thread count.  */
13277     mdns_ptr -> nx_mdns_rr_receive_suspended_count++;
13278 
13279     /* Set the state to suspended.  */
13280     thread_ptr -> tx_thread_state = TX_TCP_IP;
13281 
13282     /* Set the suspending flag.  */
13283     thread_ptr -> tx_thread_suspending = TX_TRUE;
13284 
13285     /* Temporarily disable preemption.  */
13286     _tx_thread_preempt_disable++;
13287 
13288     /* Save the timeout value.  */
13289     thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
13290 
13291     /* Restore interrupts.  */
13292     TX_RESTORE
13293 
13294     /* Call actual thread suspension routine.  */
13295     _tx_thread_system_suspend(thread_ptr);
13296 }
13297 
13298 
13299 /**************************************************************************/
13300 /*                                                                        */
13301 /*  FUNCTION                                               RELEASE        */
13302 /*                                                                        */
13303 /*    _nx_mdns_query_thread_resume                        PORTABLE C      */
13304 /*                                                           6.1          */
13305 /*  AUTHOR                                                                */
13306 /*                                                                        */
13307 /*    Yuxin Zhou, Microsoft Corporation                                   */
13308 /*                                                                        */
13309 /*  DESCRIPTION                                                           */
13310 /*                                                                        */
13311 /*    This function resumes a thread suspended on a mDNS Client query     */
13312 /*    service.                                                            */
13313 /*                                                                        */
13314 /*  INPUT                                                                 */
13315 /*                                                                        */
13316 /*    thread_ptr                            Pointer to suspended thread's */
13317 /*                                            control block               */
13318 /*                                                                        */
13319 /*  OUTPUT                                                                */
13320 /*                                                                        */
13321 /*    None                                                                */
13322 /*                                                                        */
13323 /*  CALLS                                                                 */
13324 /*                                                                        */
13325 /*    _tx_thread_system_resume              Resume thread service         */
13326 /*                                                                        */
13327 /*  CALLED BY                                                             */
13328 /*                                                                        */
13329 /*    _tx_thread_timeout                    Thread timeout processing     */
13330 /*    _tx_thread_terminate                  Thread terminate processing   */
13331 /*                                                                        */
13332 /*  RELEASE HISTORY                                                       */
13333 /*                                                                        */
13334 /*    DATE              NAME                      DESCRIPTION             */
13335 /*                                                                        */
13336 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13337 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13338 /*                                            resulting in version 6.1    */
13339 /*                                                                        */
13340 /**************************************************************************/
_nx_mdns_query_thread_resume(TX_THREAD ** suspension_list_head,NX_MDNS * mdns_ptr,NX_MDNS_RR * rr)13341 VOID  _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr)
13342 {
13343 
13344 TX_INTERRUPT_SAVE_AREA
13345 
13346 TX_THREAD *thread_ptr;
13347 
13348 
13349     /* Disable interrupts.  */
13350     TX_DISABLE
13351 
13352     /* Pickup the thread pointer.  */
13353     thread_ptr =  *suspension_list_head;
13354 
13355     /* Determine if there still is a thread suspended.  */
13356     if (thread_ptr)
13357     {
13358 
13359         /* Remove the suspended thread from the list.  */
13360 
13361         /* See if this is the only suspended thread on the list.  */
13362         if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13363         {
13364 
13365             /* Yes, the only suspended thread.  */
13366 
13367             /* Update the head pointer.  */
13368             *suspension_list_head = TX_NULL;
13369         }
13370         else
13371         {
13372 
13373             /* At least one more thread is on the same expiration list.  */
13374 
13375             /* Update the list head pointer.  */
13376             *suspension_list_head = thread_ptr -> tx_thread_suspended_next;
13377 
13378             /* Update the links of the adjacent threads.  */
13379             (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13380             (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13381         }
13382 
13383         /* Decrement the suspension count.  */
13384         mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13385 
13386         /* Prepare for resumption of the first thread.  */
13387 
13388         /* Clear cleanup routine to avoid timeout.  */
13389         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
13390 
13391         /* Temporarily disable preemption.  */
13392         _tx_thread_preempt_disable++;
13393 
13394         /* Return this block pointer to the suspended thread waiting for
13395            a block.  */
13396         *((NX_MDNS_RR **) thread_ptr -> tx_thread_additional_suspend_info) =  rr;
13397 
13398         /* Restore interrupts.  */
13399         TX_RESTORE
13400 
13401         /* Put return status into the thread control block.  */
13402         thread_ptr -> tx_thread_suspend_status =  NX_MDNS_SUCCESS;
13403 
13404         /* Resume thread.  */
13405         _tx_thread_system_resume(thread_ptr);
13406     }
13407     else
13408     {
13409 
13410         /* Restore interrupts.  */
13411         TX_RESTORE
13412     }
13413 }
13414 
13415 
13416 /**************************************************************************/
13417 /*                                                                        */
13418 /*  FUNCTION                                               RELEASE        */
13419 /*                                                                        */
13420 /*    _nx_mdns_service_mask_match                         PORTABLE C      */
13421 /*                                                           6.1          */
13422 /*  AUTHOR                                                                */
13423 /*                                                                        */
13424 /*    Yuxin Zhou, Microsoft Corporation                                   */
13425 /*                                                                        */
13426 /*  DESCRIPTION                                                           */
13427 /*                                                                        */
13428 /*    This function matchs the mDNS service mask to listen the service    */
13429 /*    and notify the application, or ignore the service.                  */
13430 /*                                                                        */
13431 /*  INPUT                                                                 */
13432 /*                                                                        */
13433 /*    mdns_ptr                              Pointer to mDNS instance      */
13434 /*    service_type                          Pointer to Service type       */
13435 /*    service_mask                          The Service mask              */
13436 /*                                                                        */
13437 /*  OUTPUT                                                                */
13438 /*                                                                        */
13439 /*    status                                Completion status             */
13440 /*                                                                        */
13441 /*  CALLS                                                                 */
13442 /*                                                                        */
13443 /*    tx_mutex_get                          Get the mDNS mutex            */
13444 /*    tx_mutex_put                          Put the mDNS mutex            */
13445 /*                                                                        */
13446 /*  CALLED BY                                                             */
13447 /*                                                                        */
13448 /*    Application Code                                                    */
13449 /*                                                                        */
13450 /*  RELEASE HISTORY                                                       */
13451 /*                                                                        */
13452 /*    DATE              NAME                      DESCRIPTION             */
13453 /*                                                                        */
13454 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13455 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13456 /*                                            resulting in version 6.1    */
13457 /*                                                                        */
13458 /**************************************************************************/
_nx_mdns_service_mask_match(NX_MDNS * mdns_ptr,UCHAR * service_type,ULONG service_mask)13459 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask)
13460 {
13461 
13462 UINT        i;
13463 UINT        found;
13464 ULONG       mask;
13465 UINT        type_length;
13466 
13467 
13468     NX_PARAMETER_NOT_USED(mdns_ptr);
13469 
13470     /* Initialize the parameters.  */
13471     i = 0;
13472     found = 0;
13473     mask = 0x00000001;
13474 
13475     /* Compare the service type.  */
13476     while (nx_mdns_service_types[i])
13477     {
13478 
13479         /* Check string length.  */
13480         if (_nx_utility_string_length_check((CHAR *)nx_mdns_service_types[i], &type_length, NX_MDNS_TYPE_MAX))
13481         {
13482             return(NX_MDNS_DATA_SIZE_ERROR);
13483         }
13484 
13485         /* Find the same service type.  */
13486         if (!_nx_mdns_name_match(service_type, (UCHAR *)(nx_mdns_service_types[i]), type_length))
13487         {
13488             found = 1;
13489             break;
13490         }
13491         i ++;
13492     }
13493 
13494     /* Check the result.  */
13495     if (found)
13496     {
13497 
13498         /* Check service mask.  */
13499         if (service_mask & (mask << i))
13500         {
13501               return(NX_MDNS_SUCCESS);
13502         }
13503     }
13504 
13505     /* Return status.  */
13506     return(NX_MDNS_SERVICE_TYPE_MISMATCH);
13507 }
13508 #endif /* NX_MDNS_DISABLE_CLIENT */
13509 
13510 
13511 /**************************************************************************/
13512 /*                                                                        */
13513 /*  FUNCTION                                               RELEASE        */
13514 /*                                                                        */
13515 /*    _nx_mdns_name_match                                 PORTABLE C      */
13516 /*                                                           6.1          */
13517 /*  AUTHOR                                                                */
13518 /*                                                                        */
13519 /*    Yuxin Zhou, Microsoft Corporation                                   */
13520 /*                                                                        */
13521 /*  DESCRIPTION                                                           */
13522 /*                                                                        */
13523 /*    This function name string match, the lowercase letters "a" to "z"   */
13524 /*    match their uppercase equivalents "A" to "Z".                       */
13525 /*                                                                        */
13526 /*  INPUT                                                                 */
13527 /*                                                                        */
13528 /*    ptr                                   Pointer to destination        */
13529 /*    name                                  Source name string            */
13530 /*                                                                        */
13531 /*  OUTPUT                                                                */
13532 /*                                                                        */
13533 /*    status                                Completion status             */
13534 /*                                                                        */
13535 /*  CALLS                                                                 */
13536 /*                                                                        */
13537 /*    None                                                                */
13538 /*                                                                        */
13539 /*  CALLED BY                                                             */
13540 /*                                                                        */
13541 /*    _nx_mdns_packet_rr_add                Add the RR into packet        */
13542 /*                                                                        */
13543 /*  RELEASE HISTORY                                                       */
13544 /*                                                                        */
13545 /*    DATE              NAME                      DESCRIPTION             */
13546 /*                                                                        */
13547 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13548 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13549 /*                                            resulting in version 6.1    */
13550 /*                                                                        */
13551 /**************************************************************************/
_nx_mdns_name_match(UCHAR * src,UCHAR * dst,UINT length)13552 static UINT  _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length)
13553 {
13554 
13555 UINT    index = 0;
13556 
13557 
13558     /* Check the name.  */
13559     while (*dst != '\0')
13560     {
13561         if((*src) != (*dst))
13562         {
13563             if((((*src) | 0x20) >= 'a') && (((*src) | 0x20) <= 'z'))
13564             {
13565                 /* Match the characters, case in-sensitive. */
13566                 if(((*src) | 0x20) != ((*dst) | 0x20))
13567                     return(NX_MDNS_NAME_MISMATCH);
13568             }
13569             else
13570             {
13571                 return(NX_MDNS_NAME_MISMATCH);
13572             }
13573         }
13574         src ++;
13575         dst ++;
13576         index ++;
13577     }
13578 
13579     /* Check the scan length.  */
13580     if (index != length)
13581     {
13582         return (NX_MDNS_NAME_MISMATCH);
13583     }
13584 
13585     /* Return success.  */
13586     return(NX_MDNS_SUCCESS);
13587 }
13588 
13589 
13590 /**************************************************************************/
13591 /*                                                                        */
13592 /*  FUNCTION                                               RELEASE        */
13593 /*                                                                        */
13594 /*    _nx_mdns_txt_string_encode                          PORTABLE C      */
13595 /*                                                           6.1          */
13596 /*  AUTHOR                                                                */
13597 /*                                                                        */
13598 /*    Yuxin Zhou, Microsoft Corporation                                   */
13599 /*                                                                        */
13600 /*  DESCRIPTION                                                           */
13601 /*                                                                        */
13602 /*    This function encodes the txt string and adds the txt string into   */
13603 /*    packet.the TXT records are formatted in a "key=value" notation      */
13604 /*    with ";" acting as separator when more then one key is available.   */
13605 /*                                                                        */
13606 /*  INPUT                                                                 */
13607 /*                                                                        */
13608 /*    ptr                                   Pointer to destination        */
13609 /*    name                                  Source name string            */
13610 /*                                                                        */
13611 /*  OUTPUT                                                                */
13612 /*                                                                        */
13613 /*    status                                Completion status             */
13614 /*                                                                        */
13615 /*  CALLS                                                                 */
13616 /*                                                                        */
13617 /*    None                                                                */
13618 /*                                                                        */
13619 /*  CALLED BY                                                             */
13620 /*                                                                        */
13621 /*    _nx_mdns_packet_rr_add                Add the RR into packet        */
13622 /*                                                                        */
13623 /*  RELEASE HISTORY                                                       */
13624 /*                                                                        */
13625 /*    DATE              NAME                      DESCRIPTION             */
13626 /*                                                                        */
13627 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13628 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13629 /*                                            resulting in version 6.1    */
13630 /*                                                                        */
13631 /**************************************************************************/
_nx_mdns_txt_string_encode(UCHAR * ptr,UCHAR * txt)13632 static UINT  _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *txt)
13633 {
13634 
13635 UCHAR   *length;
13636 UINT    count =  1;
13637 
13638 
13639     /* Point to the first character position in the buffer.  This will point
13640        to the length of the following name.  */
13641     length =  ptr++;
13642 
13643     /* Default the length to zero.  */
13644     *length =  0;
13645 
13646     /* Move through string, copying bytes and updating length.
13647        Whenever a "." is found, start a new string by updating the
13648        pointer to the length and setting the length to zero.  */
13649     while (*txt)
13650     {
13651 
13652         /* Is a dot been found?  */
13653         if (*txt == ';')
13654         {
13655 
13656 
13657             /* Yes, setup a new length pointer. */
13658             length =  ptr++;
13659 
13660             /* Default the length to zero. */
13661             *length =  0;
13662             txt++;
13663         }
13664         else
13665         {
13666 
13667             /* Copy a character to the destination.  */
13668             *ptr++ =  *txt++;
13669 
13670             /* Adjust the length of the current segment.  */
13671             (*length)++;
13672         }
13673 
13674         /* Increment the total count here.  */
13675         count++;
13676     }
13677 
13678     /* Return the count.  */
13679     return(count);
13680 }
13681 
13682 
13683 /**************************************************************************/
13684 /*                                                                        */
13685 /*  FUNCTION                                               RELEASE        */
13686 /*                                                                        */
13687 /*    _nx_mdns_txt_string_decode                          PORTABLE C      */
13688 /*                                                           6.1.3        */
13689 /*  AUTHOR                                                                */
13690 /*                                                                        */
13691 /*    Yuxin Zhou, Microsoft Corporation                                   */
13692 /*                                                                        */
13693 /*  DESCRIPTION                                                           */
13694 /*                                                                        */
13695 /*    This function decode the txt string and adds the txt string into    */
13696 /*    buffer.the TXT records are formatted in a "key=value"  notation     */
13697 /*    with ";" acting as separator when more then one key is available.   */
13698 /*                                                                        */
13699 /*  INPUT                                                                 */
13700 /*                                                                        */
13701 /*    data                                  Pointer to buffer to decode   */
13702 /*    data_length                           The length of data            */
13703 /*    buffer                                Pointer to decoded data       */
13704 /*    size                                  Size of data buffer to decode */
13705 /*                                                                        */
13706 /*  OUTPUT                                                                */
13707 /*                                                                        */
13708 /*    status                                Completion status             */
13709 /*                                                                        */
13710 /*  CALLS                                                                 */
13711 /*                                                                        */
13712 /*    None                                                                */
13713 /*                                                                        */
13714 /*  CALLED BY                                                             */
13715 /*                                                                        */
13716 /*    _nx_mdns_packet_process               Process mDNS packet           */
13717 /*    _nx_mdns_packet_rr_process            Process resource record       */
13718 /*                                                                        */
13719 /*  RELEASE HISTORY                                                       */
13720 /*                                                                        */
13721 /*    DATE              NAME                      DESCRIPTION             */
13722 /*                                                                        */
13723 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13724 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13725 /*                                            resulting in version 6.1    */
13726 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
13727 /*                                            buffer length verification, */
13728 /*                                            resulting in version 6.1.3  */
13729 /*                                                                        */
13730 /**************************************************************************/
_nx_mdns_txt_string_decode(UCHAR * data,UINT data_length,UCHAR * buffer,UINT size)13731 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size)
13732 {
13733 
13734 
13735     /* Check the buffer size.  */
13736     if (data_length >= size)
13737     {
13738         return (NX_MDNS_CACHE_ERROR);
13739     }
13740 
13741     /* decode  the data.   */
13742     while (data_length)
13743     {
13744 
13745     UINT  labelSize =  *data++;
13746 
13747         /* Is this a compression pointer or a count.  */
13748         if (labelSize <= NX_MDNS_LABEL_MAX)
13749         {
13750 
13751             /* Simple count, check for space and copy the label.  */
13752             while ((labelSize > 0) && (data_length > 1))
13753             {
13754 
13755                 *buffer++ =  *data++;
13756                 labelSize--;
13757                 data_length--;
13758             }
13759 
13760             /* Now add the ';' */
13761             *buffer++ =  ';';
13762             data_length--;
13763         }
13764         else
13765         {
13766             return(NX_MDNS_EXCEED_MAX_LABEL);
13767         }
13768     }
13769 
13770     /* Done copying the data, set the last . to a trailing null */
13771     if (*(buffer - 1) == ';')
13772     {
13773 
13774         buffer--;
13775     }
13776 
13777     /* Null terminate name.  */
13778     *buffer =  '\0';
13779 
13780     /* Return name size.  */
13781     return(NX_MDNS_SUCCESS);
13782 }
13783 
13784 
13785 /**************************************************************************/
13786 /*                                                                        */
13787 /*  FUNCTION                                               RELEASE        */
13788 /*                                                                        */
13789 /*    _nx_mdns_name_size_calculate                        PORTABLE C      */
13790 /*                                                           6.1.4        */
13791 /*  AUTHOR                                                                */
13792 /*                                                                        */
13793 /*    Yuxin Zhou, Microsoft Corporation                                   */
13794 /*                                                                        */
13795 /*  DESCRIPTION                                                           */
13796 /*                                                                        */
13797 /*    This function calculates the size of the name.                      */
13798 /*                                                                        */
13799 /*  INPUT                                                                 */
13800 /*                                                                        */
13801 /*    name                                  Pointer to the name           */
13802 /*    packet_ptr                            Pointer to received packet    */
13803 /*                                                                        */
13804 /*  OUTPUT                                                                */
13805 /*                                                                        */
13806 /*    UINT                                  Size of name                  */
13807 /*                                                                        */
13808 /*  CALLS                                                                 */
13809 /*                                                                        */
13810 /*    None                                                                */
13811 /*                                                                        */
13812 /*  CALLED BY                                                             */
13813 /*                                                                        */
13814 /*                                                                        */
13815 /*  RELEASE HISTORY                                                       */
13816 /*                                                                        */
13817 /*    DATE              NAME                      DESCRIPTION             */
13818 /*                                                                        */
13819 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13820 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13821 /*                                            resulting in version 6.1    */
13822 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
13823 /*                                            packet length verification, */
13824 /*                                            resulting in version 6.1.4  */
13825 /*                                                                        */
13826 /**************************************************************************/
_nx_mdns_name_size_calculate(UCHAR * name,NX_PACKET * packet_ptr)13827 static UINT  _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr)
13828 {
13829 
13830 UINT size =  0;
13831 
13832 
13833     /* As long as we haven't found a zero length terminating label */
13834     while (*name != '\0')
13835     {
13836 
13837         UINT  labelSize =  *name++;
13838 
13839         /* Is this a compression pointer or a count.  */
13840         if (labelSize <= NX_MDNS_LABEL_MAX)
13841         {
13842 
13843             if (name + labelSize >= packet_ptr -> nx_packet_append_ptr)
13844             {
13845 
13846                 /* If name buffer is OOB, just fail. */
13847                 return(0);
13848             }
13849 
13850             /* Simple count, adjust size and skip the label.  */
13851             size +=  labelSize + 1;
13852             name +=  labelSize;
13853         }
13854         else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
13855         {
13856 
13857             /* This is a pointer size is 2 bytes and this is the end of this name */
13858             return(size + 2);
13859         }
13860         else
13861         {
13862 
13863             /* Not defined, just fail */
13864             return(0);
13865         }
13866     }
13867 
13868     /* Adjust size for the final NULL.  */
13869     return(size + 1);
13870 }
13871 
13872 
13873 /**************************************************************************/
13874 /*                                                                        */
13875 /*  FUNCTION                                               RELEASE        */
13876 /*                                                                        */
13877 /*    _nx_mdns_name_string_encode                         PORTABLE C      */
13878 /*                                                           6.1          */
13879 /*  AUTHOR                                                                */
13880 /*                                                                        */
13881 /*    Yuxin Zhou, Microsoft Corporation                                   */
13882 /*                                                                        */
13883 /*  DESCRIPTION                                                           */
13884 /*                                                                        */
13885 /*    This function converts a string containing the name as a list of    */
13886 /*    labels separated by dots to the encoded list of labels specified    */
13887 /*    in RFC1035 for DNS servers. This conversion doesn't handle          */
13888 /*    compression and doesn't check on the lengths of the labels or the   */
13889 /*    entire name.                                                        */
13890 /*                                                                        */
13891 /*  INPUT                                                                 */
13892 /*                                                                        */
13893 /*    ptr                                   Pointer to destination        */
13894 /*    name                                  Source name string            */
13895 /*                                                                        */
13896 /*  OUTPUT                                                                */
13897 /*                                                                        */
13898 /*    count                                 Count of characters encoded   */
13899 /*                                                                        */
13900 /*  CALLS                                                                 */
13901 /*                                                                        */
13902 /*    None                                                                */
13903 /*                                                                        */
13904 /*  CALLED BY                                                             */
13905 /*                                                                        */
13906 /*                                                                        */
13907 /*  RELEASE HISTORY                                                       */
13908 /*                                                                        */
13909 /*    DATE              NAME                      DESCRIPTION             */
13910 /*                                                                        */
13911 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13912 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13913 /*                                            resulting in version 6.1    */
13914 /*                                                                        */
13915 /**************************************************************************/
_nx_mdns_name_string_encode(UCHAR * ptr,UCHAR * name)13916 static UINT  _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name)
13917 {
13918 
13919 UCHAR   *length;
13920 UINT    count =  1;
13921 
13922 
13923     /* Point to the first character position in the buffer.  This will point
13924        to the length of the following name.  */
13925     length =  ptr++;
13926 
13927     /* Default the length to zero.  */
13928     *length =  0;
13929 
13930     /* Move through string, copying bytes and updating length.
13931        Whenever a "." is found, start a new string by updating the
13932        pointer to the length and setting the length to zero.  */
13933     while (*name)
13934     {
13935 
13936         /* Is a dot been found?  */
13937         if (*name == '.')
13938         {
13939 
13940             /* Yes, setup a new length pointer. */
13941             length =  ptr++;
13942 
13943             /* Default the length to zero. */
13944             *length =  0;
13945             name++;
13946         }
13947         else
13948         {
13949 
13950             /* Copy a character to the destination.  */
13951             *ptr++ =  *name++;
13952 
13953             /* Adjust the length of the current segment.  */
13954             (*length)++;
13955         }
13956 
13957         /* Increment the total count here.  */
13958         count++;
13959     }
13960 
13961     /* Add the final zero length, like a NULL terminator.  */
13962     *ptr =  0;
13963 
13964     /* Increment the total count.  */
13965     count++;
13966 
13967     /* Return the count.  */
13968     return(count);
13969 }
13970 
13971 
13972 /**************************************************************************/
13973 /*                                                                        */
13974 /*  FUNCTION                                               RELEASE        */
13975 /*                                                                        */
13976 /*    _nx_mdns_name_string_decode                       PORTABLE C        */
13977 /*                                                           6.1.4        */
13978 /*  AUTHOR                                                                */
13979 /*                                                                        */
13980 /*    Yuxin Zhou, Microsoft Corporation                                   */
13981 /*                                                                        */
13982 /*  DESCRIPTION                                                           */
13983 /*                                                                        */
13984 /*    This function converts from the encoded list of labels as specified */
13985 /*    in RFC 1035 to a string containing the name as a list of labels     */
13986 /*    separated by dots.                                                  */
13987 /*                                                                        */
13988 /*  INPUT                                                                 */
13989 /*                                                                        */
13990 /*    data                                  Pointer to buffer to decode   */
13991 /*    start                                 Location of start of data     */
13992 /*    data_length                           Length of data buffer         */
13993 /*    buffer                                Pointer to decoded data       */
13994 /*    size                                  Size of data buffer to decode */
13995 /*                                                                        */
13996 /*  OUTPUT                                                                */
13997 /*                                                                        */
13998 /*    Size of decoded data                                                */
13999 /*                                                                        */
14000 /*  CALLS                                                                 */
14001 /*                                                                        */
14002 /*    None                                                                */
14003 /*                                                                        */
14004 /*  CALLED BY                                                             */
14005 /*                                                                        */
14006 /*                                                                        */
14007 /*  RELEASE HISTORY                                                       */
14008 /*                                                                        */
14009 /*    DATE              NAME                      DESCRIPTION             */
14010 /*                                                                        */
14011 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14012 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14013 /*                                            resulting in version 6.1    */
14014 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
14015 /*                                            buffer length verification, */
14016 /*                                            prevented infinite loop in  */
14017 /*                                            name compression,           */
14018 /*                                            resulting in version 6.1.3  */
14019 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
14020 /*                                            packet length verification, */
14021 /*                                            resulting in version 6.1.4  */
14022 /*                                                                        */
14023 /**************************************************************************/
_nx_mdns_name_string_decode(UCHAR * data,UINT start,UINT data_length,UCHAR * buffer,UINT size)14024 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size)
14025 {
14026 
14027 UCHAR   *character =  data + start;
14028 UINT    length = 0;
14029 UINT    offset;
14030 UINT    pointer_count = 0;
14031 UINT    labelSize;
14032 
14033 
14034     /* As long as there is space in the buffer and we haven't
14035        found a zero terminating label */
14036     while (1)
14037     {
14038 
14039         if (character >= data + data_length)
14040         {
14041             return(0);
14042         }
14043 
14044         if ((size <= length) || (*character == '\0'))
14045         {
14046             break;
14047         }
14048 
14049         labelSize =  *character++;
14050 
14051         /* Is this a compression pointer or a count.  */
14052         if (labelSize <= NX_MDNS_LABEL_MAX)
14053         {
14054 
14055             /* Simple count, check for space and copy the label.  */
14056             while ((size > length) && (labelSize > 0))
14057             {
14058                 if (character >= data + data_length)
14059                 {
14060                     return(0);
14061                 }
14062 
14063                 *buffer++ =  *character++;
14064                 length++;
14065                 labelSize--;
14066             }
14067 
14068             /* Now add the '.' */
14069             *buffer++ =  '.';
14070             length++;
14071         }
14072         else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
14073         {
14074 
14075             if (character >= data + data_length)
14076             {
14077                 return(0);
14078             }
14079 
14080             /* This is a pointer, just adjust the source.  */
14081             offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
14082 
14083             /* Make sure offset is in the buffer.  */
14084             if (offset >= data_length)
14085             {
14086                 return(0);
14087             }
14088 
14089             /* Pointer must not point back to itself. */
14090             if ((data + offset == character) || (data + offset == character - 1))
14091             {
14092                 return(0);
14093             }
14094 
14095             /* Prevent infinite loop with compression pointers. */
14096             pointer_count++;
14097             if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS)
14098             {
14099                 return(0);
14100             }
14101 
14102             character =  data + offset;
14103         }
14104         else
14105         {
14106 
14107             /* Not defined, just fail */
14108             return(0);
14109         }
14110     }
14111 
14112     /* Done copying the data, set the last . to a trailing null */
14113     if ((length > 0) && (*(buffer - 1) == '.'))
14114     {
14115 
14116         buffer--;
14117         length --;
14118     }
14119 
14120     /* Null terminate name.  */
14121     *buffer =  '\0';
14122 
14123     /* Return name size.  */
14124     return(length);
14125 }
14126 
14127 
14128 /**************************************************************************/
14129 /*                                                                        */
14130 /*  FUNCTION                                               RELEASE        */
14131 /*                                                                        */
14132 /*    _nx_mdns_rr_size_get                                PORTABLE C      */
14133 /*                                                           6.1.4        */
14134 /*  AUTHOR                                                                */
14135 /*                                                                        */
14136 /*    Yuxin Zhou, Microsoft Corporation                                   */
14137 /*                                                                        */
14138 /*  DESCRIPTION                                                           */
14139 /*                                                                        */
14140 /*    This function gets the size of resource record.                     */
14141 /*                                                                        */
14142 /*  INPUT                                                                 */
14143 /*                                                                        */
14144 /*    resource                              Pointer to the resource       */
14145 /*    packet_ptr                            Pointer to received packet    */
14146 /*                                                                        */
14147 /*  OUTPUT                                                                */
14148 /*                                                                        */
14149 /*    size of data                                                        */
14150 /*                                                                        */
14151 /*  CALLS                                                                 */
14152 /*                                                                        */
14153 /*                                                                        */
14154 /*  CALLED BY                                                             */
14155 /*                                                                        */
14156 /*                                                                        */
14157 /*  RELEASE HISTORY                                                       */
14158 /*                                                                        */
14159 /*    DATE              NAME                      DESCRIPTION             */
14160 /*                                                                        */
14161 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14162 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14163 /*                                            resulting in version 6.1    */
14164 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
14165 /*                                            packet length verification, */
14166 /*                                            resulting in version 6.1.4  */
14167 /*                                                                        */
14168 /**************************************************************************/
_nx_mdns_rr_size_get(UCHAR * resource,NX_PACKET * packet_ptr)14169 static UINT  _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr)
14170 {
14171 
14172 UINT    name_size;
14173 UINT    data_size;
14174 
14175     /* Resource size is
14176         name size + data size + 2 bytes for type, 2 for class, 4 for time to live and 2 for data length
14177         i.e. name size + data size + 10 bytes overhead.
14178     */
14179     name_size = _nx_mdns_name_size_calculate(resource, packet_ptr);
14180 
14181     if (resource + name_size + 8 + 2 > packet_ptr -> nx_packet_append_ptr)
14182     {
14183         return(0);
14184     }
14185     data_size = NX_MDNS_GET_USHORT_DATA(resource + name_size + 8);
14186 
14187     /* Return resource size.  */
14188     return(name_size + data_size + 10);
14189 }
14190 
14191 
14192 /**************************************************************************/
14193 /*                                                                        */
14194 /*  FUNCTION                                               RELEASE        */
14195 /*                                                                        */
14196 /*    _nx_mdns_short_to_network_convert                   PORTABLE C      */
14197 /*                                                           6.1          */
14198 /*  AUTHOR                                                                */
14199 /*                                                                        */
14200 /*    Yuxin Zhou, Microsoft Corporation                                   */
14201 /*                                                                        */
14202 /*  DESCRIPTION                                                           */
14203 /*                                                                        */
14204 /*    This function converts an unsigned short to network byte order,     */
14205 /*    which is big endian.                                                */
14206 /*                                                                        */
14207 /*  INPUT                                                                 */
14208 /*                                                                        */
14209 /*    ptr                                   Pointer to the destination    */
14210 /*    value                                 Source value                  */
14211 /*                                                                        */
14212 /*  OUTPUT                                                                */
14213 /*                                                                        */
14214 /*    None                                                                */
14215 /*                                                                        */
14216 /*  CALLS                                                                 */
14217 /*                                                                        */
14218 /*    None                                                                */
14219 /*                                                                        */
14220 /*  CALLED BY                                                             */
14221 /*                                                                        */
14222 /*    DNS component                                                       */
14223 /*                                                                        */
14224 /*  RELEASE HISTORY                                                       */
14225 /*                                                                        */
14226 /*    DATE              NAME                      DESCRIPTION             */
14227 /*                                                                        */
14228 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14229 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14230 /*                                            resulting in version 6.1    */
14231 /*                                                                        */
14232 /**************************************************************************/
_nx_mdns_short_to_network_convert(UCHAR * ptr,USHORT value)14233 static void  _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value)
14234 {
14235 
14236     *ptr++ =  (UCHAR)(value >> 8);
14237     *ptr   =  (UCHAR)value;
14238 }
14239 
14240 
14241 /**************************************************************************/
14242 /*                                                                        */
14243 /*  FUNCTION                                               RELEASE        */
14244 /*                                                                        */
14245 /*    _nx_mdns_long_to_network_convert                    PORTABLE C      */
14246 /*                                                           6.1          */
14247 /*  AUTHOR                                                                */
14248 /*                                                                        */
14249 /*    Yuxin Zhou, Microsoft Corporation                                   */
14250 /*                                                                        */
14251 /*  DESCRIPTION                                                           */
14252 /*                                                                        */
14253 /*    This function converts an unsigned long to network format, which    */
14254 /*    big endian.                                                         */
14255 /*                                                                        */
14256 /*  INPUT                                                                 */
14257 /*                                                                        */
14258 /*    ptr                                   Pointer to the destination    */
14259 /*    value                                 Source value                  */
14260 /*                                                                        */
14261 /*  OUTPUT                                                                */
14262 /*                                                                        */
14263 /*    None                                                                */
14264 /*                                                                        */
14265 /*  CALLS                                                                 */
14266 /*                                                                        */
14267 /*    None                                                                */
14268 /*                                                                        */
14269 /*  CALLED BY                                                             */
14270 /*                                                                        */
14271 /*    DNS component                                                       */
14272 /*                                                                        */
14273 /*  RELEASE HISTORY                                                       */
14274 /*                                                                        */
14275 /*    DATE              NAME                      DESCRIPTION             */
14276 /*                                                                        */
14277 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14278 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14279 /*                                            resulting in version 6.1    */
14280 /*                                                                        */
14281 /**************************************************************************/
_nx_mdns_long_to_network_convert(UCHAR * ptr,ULONG value)14282 static void _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value)
14283 {
14284 
14285     *ptr++ =  (UCHAR)(value >> 24);
14286     *ptr++ =  (UCHAR)(value >> 16);
14287     *ptr++ =  (UCHAR)(value >> 8);
14288     *ptr   =  (UCHAR)value;
14289 }
14290