1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Multicast Domain Name System (mDNS)                                 */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 #define NX_MDNS_SOURCE_CODE
25 
26 
27 /* Force error checking to be disabled in this module */
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif /* NX_DISABLE_ERROR_CHECKING  */
31 
32 
33 /* Include necessary system files.  */
34 #include    "nxd_mdns.h"
35 #include    "tx_thread.h"
36 
37 /* Define the application protocol.  */
38 static CHAR         *nx_mdns_app_protocol[]= {"_tcp", "_udp", NX_NULL};
39 
40 /* Define the service type.  */
41 #ifndef NX_MDNS_DISABLE_CLIENT
42 static CHAR         *nx_mdns_service_types[] =
43 {
44     "_device-info",
45     "_http",
46     "_https",
47     "_guid",
48     "_h323",
49     "_ntp",
50     "_objective",
51     "_rdp",
52     "_remote",
53     "_rtsp",
54     "_sip",
55     "_smb",
56     "_soap",
57     "_ssh",
58     "_telnet",
59     "_tftp",
60     "_xmpp-client",
61     NX_NULL
62 };
63 #endif /* NX_MDNS_DISABLE_CLIENT  */
64 
65 
66 /* Define the mDNS internal Function.  */
67 static VOID         _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
68 static VOID         _nx_mdns_timer_entry(ULONG mdns_value);
69 static VOID         _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr, ULONG timer_count);
70 static VOID         _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr);
71 static VOID         _nx_mdns_thread_entry(ULONG mdns_value);
72 static UINT         _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
73 static UINT         _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR type);
74 static VOID         _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index);
75 static UINT         _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type);
76 static UINT         _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index);
77 static UINT         _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op);
78 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
79 static UINT         _nx_mdns_packet_address_check(NX_PACKET *packet_ptr);
80 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
81 static UINT         _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index);
82 static UINT         _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain);
83 static UINT         _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr);
84 static UINT         _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr);
85 static UINT         _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length);
86 static UINT         _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr);
87 static UINT         _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name);
88 static UINT         _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size);
89 static UINT         _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name);
90 static UINT         _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size);
91 static VOID         _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value);
92 static VOID         _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value);
93 
94 #ifndef NX_MDNS_DISABLE_SERVER
95 static VOID         _nx_mdns_address_change_process(NX_MDNS *mdns_ptr);
96 static UINT         _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index);
97 static UINT         _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index);
98 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
99 static UINT         _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index);
100 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
101 static UINT         _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority, USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index);
102 static UINT         _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index);
103 static UINT         _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index);
104 
105 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
106 static UINT         _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index);
107 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES */
108 
109 static UINT         _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length, UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index);
110 static UINT         _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr);
111 static UINT         _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
112 static VOID         _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index);
113 static VOID         _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index);
114 static VOID         _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index);
115 static VOID         _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index);
116 #ifndef NX_DISABLE_IPV4
117 static VOID         _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info);
118 #endif /* NX_DISABLE_IPV4 */
119 #ifdef NX_MDNS_ENABLE_IPV6
120 static VOID         _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address);
121 #endif /* NX_MDNS_ENABLE_IPV6  */
122 #endif /* NX_MDNS_DISABLE_SERVER  */
123 
124 #ifndef NX_MDNS_DISABLE_CLIENT
125 static VOID         _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present);
126 static UINT         _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index);
127 static UINT         _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask);
128 static UINT         _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index);
129 static UINT         _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index);
130 static VOID         _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index);
131 static UINT         _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index);
132 static VOID         _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER);
133 static VOID         _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
134                                                   NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option);
135 static VOID         _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr);
136 static UINT         _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr);
137 static UINT         _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index);
138 #endif /* NX_MDNS_DISABLE_CLIENT  */
139 
140 UINT         _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size, VOID *peer_cache_ptr, UINT peer_cache_size);
141 UINT         _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present);
142 UINT         _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr);
143 UINT         _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_result);
144 UINT         _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len, VOID **insert_ptr, UCHAR find_string, UCHAR add_name);
145 UINT         _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len);
146 VOID         _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr);
147 
148 
149 /* Define the mDNS STRUCT.  */
150 static struct       NX_MDNS_STRUCT  *_nx_mdns_created_ptr;
151 static CHAR         _nx_mdns_dns_sd[NX_MDNS_DNS_SD_MAX + 1] = "_services._dns-sd._udp.local";
152 static UCHAR        temp_string_buffer[NX_MDNS_NAME_MAX + 1];
153 static UCHAR        target_string_buffer[NX_MDNS_NAME_MAX + 1];
154 
155 #ifdef NX_MDNS_ENABLE_IPV6
156 static NXD_ADDRESS  NX_MDNS_IPV6_MULTICAST_ADDRESS;
157 #endif /* NX_MDNS_ENABLE_IPV6 */
158 
159 /**************************************************************************/
160 /*                                                                        */
161 /*  FUNCTION                                               RELEASE        */
162 /*                                                                        */
163 /*    _nxe_mdns_create                                    PORTABLE C      */
164 /*                                                           6.1          */
165 /*  AUTHOR                                                                */
166 /*                                                                        */
167 /*    Yuxin Zhou, Microsoft Corporation                                   */
168 /*                                                                        */
169 /*  DESCRIPTION                                                           */
170 /*                                                                        */
171 /*    This function checks for errors in the mDNS create function call    */
172 /*                                                                        */
173 /*    Note: the name string is generated by internal logic and it is      */
174 /*    always NULL-terminated.                                             */
175 /*                                                                        */
176 /*  INPUT                                                                 */
177 /*                                                                        */
178 /*    mdns_ptr                              Pointer to mDNS instance      */
179 /*    ip_ptr                                Pointer to IP instance        */
180 /*    priority                              The priority of mDNS Thread   */
181 /*    stack_ptr                             Stack pointer for mDNS Thread */
182 /*    stack_size                            Stack size for mDNS Thread    */
183 /*    host_name                             Pointer to host name          */
184 /*    local_cache_ptr                       Pointer to local cache        */
185 /*    local_cache_size                      The size of local cache       */
186 /*    peer_cache_ptr                        Pointer to peer cache         */
187 /*    peer_cache_size                       The size of peer cache        */
188 /*    probing_notify                        mDNS probing notify           */
189 /*                                                                        */
190 /*  OUTPUT                                                                */
191 /*                                                                        */
192 /*    status                                Completion status             */
193 /*                                                                        */
194 /*  CALLS                                                                 */
195 /*                                                                        */
196 /*    _nx_mdns_create                       Actual mDNS create function   */
197 /*                                                                        */
198 /*  CALLED BY                                                             */
199 /*                                                                        */
200 /*    Application Code                                                    */
201 /*                                                                        */
202 /*  RELEASE HISTORY                                                       */
203 /*                                                                        */
204 /*    DATE              NAME                      DESCRIPTION             */
205 /*                                                                        */
206 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
207 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
208 /*                                            resulting in version 6.1    */
209 /*                                                                        */
210 /**************************************************************************/
_nxe_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))211 UINT  _nxe_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
212                        UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
213                        VOID *local_cache_ptr, UINT local_cache_size,
214                        VOID *peer_cache_ptr, UINT peer_cache_size,
215                        VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
216 {
217 
218 UINT    status;
219 UCHAR   *ptr;
220 
221 
222     /* Check for invalid input pointers.  */
223     if ((!ip_ptr) || (!mdns_ptr) || (!stack_ptr) || (!packet_pool) || (!host_name))
224     {
225         return(NX_PTR_ERROR);
226     }
227 
228     /* Check for invalid non pointer input. */
229     if ((ip_ptr -> nx_ip_id != NX_IP_ID) ||
230         (stack_size < TX_MINIMUM_STACK) ||
231         (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
232     {
233         return(NX_MDNS_PARAM_ERROR);
234     }
235 
236     /* Check the host name format, RFC 1033,1034,1035 recomend that host names contain only letters, digits, and hyphens RFC6763, Appendix E, Page44. */
237     ptr = host_name;
238     while (*ptr != '\0')
239     {
240         if (((*ptr >= 'a') && (*ptr <= 'z')) ||
241             ((*ptr >= 'A') && (*ptr <= 'Z')) ||
242             ((*ptr >= '0') && (*ptr <= '9')) ||
243             ((*ptr == '-')))
244             ptr++;
245         else
246             return(NX_MDNS_HOST_NAME_ERROR);
247     }
248 
249     /* Check the default domain name size.  */
250     if ((sizeof("local") - 1) > NX_MDNS_DOMAIN_NAME_MAX)
251     {
252         return(NX_MDNS_DATA_SIZE_ERROR);
253     }
254 
255 #ifndef NX_MDNS_DISABLE_SERVER
256 
257     /* Check for invalid input pointers, cache header and tail (8 bytes).  */
258     if ((!local_cache_ptr) || (local_cache_size < 8))
259     {
260         return(NX_PTR_ERROR);
261     }
262 
263     /* Make sure record_buffer is 4-byte aligned. */
264     if ((((UINT)local_cache_ptr & 0x3) != 0) ||
265         ((local_cache_size & 0x3) != 0))
266     {
267         return(NX_MDNS_CACHE_ERROR);
268     }
269 #endif /* NX_MDNS_DISABLE_SERVER */
270 
271 #ifndef NX_MDNS_DISABLE_CLIENT
272 
273     /* Check for invalid input pointers, cache header and tail (8 bytes).  */
274     if ((!peer_cache_ptr) || (peer_cache_size < 8))
275     {
276         return(NX_PTR_ERROR);
277     }
278 
279     /* Make sure peer cache is 4-byte aligned. */
280     if ((((UINT)peer_cache_ptr & 0x3) != 0) ||
281         ((peer_cache_size & 0x3) != 0))
282     {
283         return(NX_MDNS_CACHE_ERROR);
284     }
285 #endif /* NX_MDNS_DISABLE_CLIENT */
286 
287     /* Call actual mDNS create service.  */
288     status =  _nx_mdns_create(mdns_ptr, ip_ptr, packet_pool, priority,
289                               stack_ptr, stack_size, host_name,
290                               local_cache_ptr, local_cache_size,
291                               peer_cache_ptr, peer_cache_size,
292                               probing_notify);
293 
294     /* Return status.  */
295     return(status);
296 }
297 
298 
299 /**************************************************************************/
300 /*                                                                        */
301 /*  FUNCTION                                               RELEASE        */
302 /*                                                                        */
303 /*    _nx_mdns_create                                     PORTABLE C      */
304 /*                                                           6.1.11       */
305 /*  AUTHOR                                                                */
306 /*                                                                        */
307 /*    Yuxin Zhou, Microsoft Corporation                                   */
308 /*                                                                        */
309 /*  DESCRIPTION                                                           */
310 /*                                                                        */
311 /*    This function initializes the mDNS structure and associated IP      */
312 /*    instance for mDNS operation. In doing so, it creates a UDP socket   */
313 /*    for communication with the server and a mDNS processing thread      */
314 /*                                                                        */
315 /*    Note: the name string is generated by internal logic and it is      */
316 /*    always NULL-terminated.                                             */
317 /*                                                                        */
318 /*  INPUT                                                                 */
319 /*                                                                        */
320 /*    mdns_ptr                              Pointer to mDNS instance      */
321 /*    ip_ptr                                Pointer to IP instance        */
322 /*    priority                              The priority of mDNS Thread   */
323 /*    stack_ptr                             Stack pointer for mDNS Thread */
324 /*    stack_size                            Stack size for mDNS Thread    */
325 /*    host_name                             Pointer to host name          */
326 /*    local_cache_ptr                       Pointer to local cache        */
327 /*    local_cache_size                      The size of local cache       */
328 /*    peer_cache_ptr                        Pointer to peer cache         */
329 /*    peer_cache_size                       The size of peer cache        */
330 /*    probing_notify                        mDNS probing notify           */
331 /*                                                                        */
332 /*  OUTPUT                                                                */
333 /*                                                                        */
334 /*    status                                Completion status             */
335 /*                                                                        */
336 /*  CALLS                                                                 */
337 /*                                                                        */
338 /*    nx_udp_socket_create                  Create the mDNS UDP socket    */
339 /*    nx_udp_socket_delete                  Delete the mDNS UDP socket    */
340 /*    nx_udp_socket_bind                    Bind the mDNS UDP socket      */
341 /*    nx_udp_socket_unbind                  Unbind the mDNS UDP socket    */
342 /*    nx_udp_socket_receive_notify          Register the mDNS function    */
343 /*    nx_ip_address_change_notify           Register IPv4 address function*/
344 /*    nxd_ipv6_address_change_notify        Register IPv6 address function*/
345 /*    tx_mutex_create                       Create the mDNS mutex         */
346 /*    tx_mutex_delete                       Delete the mDNS mutex         */
347 /*    tx_thread_create                      Create the mDNS thread        */
348 /*    tx_thread_delete                      Delete the mDNS thread        */
349 /*    tx_event_flags_create                 Create the ThreadX flag event */
350 /*    _nx_mdns_cache_initialize             Initialize the mDNS cache     */
351 /*                                                                        */
352 /*  CALLED BY                                                             */
353 /*                                                                        */
354 /*    Application Code                                                    */
355 /*                                                                        */
356 /*  RELEASE HISTORY                                                       */
357 /*                                                                        */
358 /*    DATE              NAME                      DESCRIPTION             */
359 /*                                                                        */
360 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
361 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
362 /*                                            verified memcpy use cases,  */
363 /*                                            resulting in version 6.1    */
364 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
365 /*                                            corrected the random value, */
366 /*                                            used internal ip address    */
367 /*                                            change notification,        */
368 /*                                            resulting in version 6.1.11 */
369 /*                                                                        */
370 /**************************************************************************/
_nx_mdns_create(NX_MDNS * mdns_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * packet_pool,UINT priority,VOID * stack_ptr,ULONG stack_size,UCHAR * host_name,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size,VOID (* probing_notify)(NX_MDNS * mdns_ptr,UCHAR * name,UINT probing_state))371 UINT  _nx_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool,
372                       UINT priority, VOID *stack_ptr, ULONG stack_size, UCHAR *host_name,
373                       VOID *local_cache_ptr, UINT local_cache_size,
374                       VOID *peer_cache_ptr, UINT peer_cache_size,
375                       VOID (*probing_notify)(NX_MDNS *mdns_ptr, UCHAR *name, UINT probing_state))
376 {
377 
378 UINT    status;
379 UINT    host_name_size;
380 
381 
382     /* Check the size of the host name string. The last four characters in the
383        host_name are reserved so DNS-SD is able to append " (2)" during the conflict
384        resolution process. */
385 #if (NX_MDNS_HOST_NAME_MAX >= NX_MDNS_LABEL_MAX)
386     if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_LABEL_MAX - 4)))
387 #else
388     if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, (NX_MDNS_HOST_NAME_MAX - 4)))
389 #endif
390     {
391         return(NX_MDNS_DATA_SIZE_ERROR);
392     }
393 
394     /* Initialize the mDNS control block to zero.  */
395     memset((void *) mdns_ptr, 0, sizeof(NX_MDNS));
396 
397 #ifdef NX_MDNS_ENABLE_IPV6
398 
399     /* Initialize the IPv6 Multicast address.  */
400     memset(&NX_MDNS_IPV6_MULTICAST_ADDRESS, 0, sizeof(NXD_ADDRESS));
401     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_version = NX_IP_VERSION_V6;
402     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0] = 0xFF020000;
403     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1] = 0x00000000;
404     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2] = 0x00000000;
405     NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3] = 0x000000FB;
406 #endif /* NX_MDNS_ENABLE_IPV6 */
407 
408     /* Save the IP pointer.  */
409     mdns_ptr -> nx_mdns_ip_ptr = ip_ptr;
410 
411     /* Save the Packet pool.  */
412     mdns_ptr -> nx_mdns_packet_pool_ptr = packet_pool;
413 
414     /* Save the host name.  */
415     memcpy((char*)mdns_ptr -> nx_mdns_host_name, (const char*)host_name, (host_name_size + 1)); /* Use case of memcpy is verified. */
416 
417     /* Set the domain name as "local" by default.  */
418     memcpy((char*)mdns_ptr -> nx_mdns_domain_name, "local", sizeof("local")); /* Use case of memcpy is verified. */
419 
420     /* Assign the resource record change notify. */
421     mdns_ptr -> nx_mdns_probing_notify = probing_notify;
422 
423     /* Set the mDNS announcing period.  */
424     mdns_ptr -> nx_mdns_announcing_period = (USHORT)NX_MDNS_ANNOUNCING_PERIOD;
425 
426     /* Set the mDNS announcing retransmission interval.  */
427     mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)NX_MDNS_ANNOUNCING_RETRANS_INTERVAL;
428 
429     /* Set the mDNS announcing period interval.  */
430     mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)NX_MDNS_ANNOUNCING_PERIOD_INTERVAL;
431 
432     /* Set the mDNS announcing count between one announcing period.  */
433     mdns_ptr -> nx_mdns_announcing_count = (UCHAR)NX_MDNS_ANNOUNCING_COUNT;
434 
435     /* Set the mDNS announcing factor.  */
436     mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)NX_MDNS_ANNOUNCING_FACTOR;
437 
438     /* Set the mDNS announcing max time.  */
439     mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)NX_MDNS_ANNOUNCING_MAX_TIME;
440 
441     /* Set the pointer of global variable mDNS.  */
442     _nx_mdns_created_ptr = mdns_ptr;
443 
444 #ifndef NX_MDNS_DISABLE_SERVER
445 
446 #ifndef NX_DISABLE_IPV4
447     /* Setup the IP address change callback function. */
448     ip_ptr -> nx_ip_address_change_notify_internal = _nx_mdns_ip_address_change_notify;
449 #endif /* NX_DISABLE_IPV4 */
450 
451 #ifdef NX_MDNS_ENABLE_IPV6
452 
453     /* Setup the IPv6 address change callback function. */
454     ip_ptr -> nx_ipv6_address_change_notify_internal =  _nx_mdns_ipv6_address_change_notify;
455 #endif /* NX_MDNS_ENABLE_IPV6  */
456 #endif /* NX_MDNS_DISABLE_SERVER */
457 
458     /* Create the Socket and check the status */
459     status = nx_udp_socket_create(mdns_ptr -> nx_mdns_ip_ptr, &(mdns_ptr -> nx_mdns_socket), "Multicast DNS",
460                                   NX_MDNS_UDP_TYPE_OF_SERVICE, NX_MDNS_UDP_FRAGMENT_OPTION,
461                                   NX_MDNS_UDP_TIME_TO_LIVE, NX_MDNS_UDP_QUEUE_DEPTH);
462 
463     /* Determine if it was successful.  */
464     if (status != NX_SUCCESS)
465     {
466         return(status);
467     }
468 
469     /* Bind the UDP socket to the mDNS port.  */
470     status =  nx_udp_socket_bind(&(mdns_ptr -> nx_mdns_socket), NX_MDNS_UDP_PORT, TX_NO_WAIT);
471 
472     /* Check for error */
473     if (status)
474     {
475 
476         /* Delete the UDP socket.  */
477         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
478         return(status);
479     }
480 
481     /* Register UDP receive callback. */
482     status = nx_udp_socket_receive_notify(&(mdns_ptr -> nx_mdns_socket), _nx_mdns_udp_receive_notify);
483 
484     /* Check for error */
485     if (status)
486     {
487 
488         /* Delete the UDP socket.  */
489         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
490         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
491         return(status);
492     }
493 
494     /* Create the mDNS mutex.  */
495     status =  tx_mutex_create(&(mdns_ptr -> nx_mdns_mutex),
496                               "mDNS Mutex", TX_NO_INHERIT);
497 
498     /* Determine if the semaphore creation was successful.  */
499     if (status != NX_SUCCESS)
500     {
501 
502         /* Delete the UDP socket.  */
503         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
504         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
505 
506         /* No, return error status.  */
507         return(status);
508     }
509 
510     /* Create the internal mDNS event flag object.  */
511     status = tx_event_flags_create(&mdns_ptr -> nx_mdns_events, "mDNS Thread Events");
512 
513     /* Determine if the event flags creation was successful.  */
514     if (status)
515     {
516 
517         /* Delete the UDP socket.  */
518         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
519         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
520 
521         /* Delete the mDNS mutex.  */
522         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
523 
524         /* No, return error status.  */
525         return(status);
526     }
527 
528     /* Create the mDNS processing thread.  */
529     status =  tx_thread_create(&(mdns_ptr -> nx_mdns_thread), "mDNS Thread",
530                                _nx_mdns_thread_entry, (ULONG) mdns_ptr,
531                                stack_ptr, stack_size, priority, priority,
532                                1, TX_AUTO_START);
533 
534     /* Determine if the thread creation was successful.  */
535     if (status != NX_SUCCESS)
536     {
537 
538         /* Delete the UDP socket.  */
539         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
540         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
541 
542         /* Delete the mDNS mutex.  */
543         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
544 
545         /* Delete the mDNS events.  */
546         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
547 
548         /* No, return error status.  */
549         return(status);
550     }
551 
552     /* Create the timer of Resource record lifetime.  */
553     status =  tx_timer_create(&(mdns_ptr -> nx_mdns_timer), "mDNS Timer",
554                               _nx_mdns_timer_entry, (ULONG) mdns_ptr,
555                               0xFFFFFFFF, 0, TX_NO_ACTIVATE);
556 
557     /* Determine if the thread creation was successful.  */
558     if (status != NX_SUCCESS)
559     {
560 
561         /* Delete the UDP socket.  */
562         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
563         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
564 
565         /* Delete the mDNS mutex.  */
566         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
567 
568         /* Delete the mDNS events.  */
569         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
570 
571         /* Delete the mDNS thread.  */
572         tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
573 
574         /* No, return error status.  */
575         return(status);
576     }
577 
578     /* Initialize the buffer.  */
579     status =  _nx_mdns_cache_initialize(mdns_ptr, local_cache_ptr, local_cache_size,
580                                         peer_cache_ptr, peer_cache_size);
581 
582     /* Determine if the buffer initialize was successful.  */
583     if (status != NX_SUCCESS)
584     {
585 
586         /* Delete the UDP socket.  */
587         nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
588         nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
589 
590         /* Delete the mDNS timer.  */
591         tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
592 
593         /* Delete the mDNS mutex.  */
594         tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
595 
596         /* Delete the mDNS events.  */
597         tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
598 
599         /* Delete the mDNS thread.  */
600         tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
601 
602         /* No, return error status.  */
603         return(status);
604     }
605 
606     /* Update the mDNS structure ID.  */
607     mdns_ptr -> nx_mdns_id = NX_MDNS_ID;
608 
609     /* The random delay of first probing for RR. */
610     mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (((ULONG)NX_RAND()) % NX_MDNS_PROBING_TIMER_COUNT));
611 
612     /* Return a successful status.  */
613     return(NX_SUCCESS);
614 }
615 
616 
617 /**************************************************************************/
618 /*                                                                        */
619 /*  FUNCTION                                               RELEASE        */
620 /*                                                                        */
621 /*    _nxe_mdns_delete                                    PORTABLE C      */
622 /*                                                           6.1          */
623 /*  AUTHOR                                                                */
624 /*                                                                        */
625 /*    Yuxin Zhou, Microsoft Corporation                                   */
626 /*                                                                        */
627 /*  DESCRIPTION                                                           */
628 /*                                                                        */
629 /*    This function checks for errors in the mDNS delete function call.   */
630 /*                                                                        */
631 /*  INPUT                                                                 */
632 /*                                                                        */
633 /*    mdns_ptr                              Pointer to mDNS instance      */
634 /*                                                                        */
635 /*  OUTPUT                                                                */
636 /*                                                                        */
637 /*    status                                Completion status             */
638 /*                                                                        */
639 /*  CALLS                                                                 */
640 /*                                                                        */
641 /*    _nx_mdns_delete                       Actual mDNS delete function   */
642 /*                                                                        */
643 /*  CALLED BY                                                             */
644 /*                                                                        */
645 /*    Application Code                                                    */
646 /*                                                                        */
647 /*  RELEASE HISTORY                                                       */
648 /*                                                                        */
649 /*    DATE              NAME                      DESCRIPTION             */
650 /*                                                                        */
651 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
652 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
653 /*                                            resulting in version 6.1    */
654 /*                                                                        */
655 /**************************************************************************/
_nxe_mdns_delete(NX_MDNS * mdns_ptr)656 UINT  _nxe_mdns_delete(NX_MDNS *mdns_ptr)
657 {
658 
659 UINT    status;
660 
661 
662     /* Check for invalid input pointers.  */
663     if (!mdns_ptr)
664     {
665         return(NX_PTR_ERROR);
666     }
667 
668     /* Check for invalid server attributes. */
669     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
670     {
671         return(NX_MDNS_PARAM_ERROR);
672     }
673 
674     /* Call actual mDNS delete service.  */
675     status =  _nx_mdns_delete(mdns_ptr);
676 
677     /* Return status.  */
678     return(status);
679 }
680 
681 
682 /**************************************************************************/
683 /*                                                                        */
684 /*  FUNCTION                                               RELEASE        */
685 /*                                                                        */
686 /*    _nx_mdns_delete                                     PORTABLE C      */
687 /*                                                           6.1          */
688 /*  AUTHOR                                                                */
689 /*                                                                        */
690 /*    Yuxin Zhou, Microsoft Corporation                                   */
691 /*                                                                        */
692 /*  DESCRIPTION                                                           */
693 /*                                                                        */
694 /*    This function deletes the mDNS instance.                            */
695 /*                                                                        */
696 /*  INPUT                                                                 */
697 /*                                                                        */
698 /*    mdns_ptr                              Pointer to mDNS instance      */
699 /*                                                                        */
700 /*  OUTPUT                                                                */
701 /*                                                                        */
702 /*    status                                Completion status             */
703 /*                                                                        */
704 /*  CALLS                                                                 */
705 /*                                                                        */
706 /*    nx_udp_socket_unbind                  Unbind the mDNS UDP socket    */
707 /*    nx_udp_socket_delete                  Delete the mDNS UDP socket    */
708 /*    tx_mutex_get                          Get the mDNS mutex            */
709 /*    tx_mutex_put                          Put the mDNS mutex            */
710 /*    tx_mutex_delete                       Delete the mDNS mutex         */
711 /*    tx_thread_terminate                   Terminate the mDNS thread     */
712 /*    tx_thread_delete                      Delete the mDNS thread        */
713 /*    tx_event_flags_delete                 Delete the mDNS events flag   */
714 /*                                                                        */
715 /*  CALLED BY                                                             */
716 /*                                                                        */
717 /*    Application Code                                                    */
718 /*                                                                        */
719 /*  RELEASE HISTORY                                                       */
720 /*                                                                        */
721 /*    DATE              NAME                      DESCRIPTION             */
722 /*                                                                        */
723 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
724 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
725 /*                                            resulting in version 6.1    */
726 /*                                                                        */
727 /**************************************************************************/
_nx_mdns_delete(NX_MDNS * mdns_ptr)728 UINT  _nx_mdns_delete(NX_MDNS *mdns_ptr)
729 {
730 
731 
732     /* Get the mDNS mutex.  */
733     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
734 
735     /* Clear the mDNS structure ID. */
736     mdns_ptr -> nx_mdns_id =  0;
737 
738     /* Set the pointer of global variable mDNS.  */
739     _nx_mdns_created_ptr = NX_NULL;
740 
741     /* Unbind the port.  */
742     nx_udp_socket_unbind(&(mdns_ptr -> nx_mdns_socket));
743 
744     /* Delete the UDP socket.  */
745     nx_udp_socket_delete(&(mdns_ptr -> nx_mdns_socket));
746 
747     /* Terminate the mDNS processing thread.  */
748     tx_thread_terminate(&(mdns_ptr -> nx_mdns_thread));
749 
750     /* Delete the mDNS processing thread.  */
751     tx_thread_delete(&(mdns_ptr -> nx_mdns_thread));
752 
753     /* Delete the event flags.  */
754     tx_event_flags_delete(&(mdns_ptr -> nx_mdns_events));
755 
756     /* Delete the timer.  */
757     tx_timer_delete(&(mdns_ptr -> nx_mdns_timer));
758 
759     /* Release the mDNS mutex.  */
760     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
761 
762     /* Delete the mDNS mutex.  */
763     tx_mutex_delete(&(mdns_ptr -> nx_mdns_mutex));
764 
765     /* Return a successful status.  */
766     return(NX_SUCCESS);
767 }
768 
769 
770 /**************************************************************************/
771 /*                                                                        */
772 /*  FUNCTION                                               RELEASE        */
773 /*                                                                        */
774 /*    _nxe_mdns_cache_notify_set                          PORTABLE C      */
775 /*                                                           6.1          */
776 /*  AUTHOR                                                                */
777 /*                                                                        */
778 /*    Yuxin Zhou, Microsoft Corporation                                   */
779 /*                                                                        */
780 /*  DESCRIPTION                                                           */
781 /*                                                                        */
782 /*    This function checks for errors in the mDNS cache full notify       */
783 /*    function call.                                                      */
784 /*                                                                        */
785 /*  INPUT                                                                 */
786 /*                                                                        */
787 /*    mdns_ptr                              Pointer to mDNS instance      */
788 /*    cache_full_notify                     Cache full notify function    */
789 /*                                                                        */
790 /*  OUTPUT                                                                */
791 /*                                                                        */
792 /*    status                                Completion status             */
793 /*                                                                        */
794 /*  CALLS                                                                 */
795 /*                                                                        */
796 /*    _nx_mdns_cache_notify_set             Actual cache notify           */
797 /*                                            set function                */
798 /*                                                                        */
799 /*  CALLED BY                                                             */
800 /*                                                                        */
801 /*    Application Code                                                    */
802 /*                                                                        */
803 /*  RELEASE HISTORY                                                       */
804 /*                                                                        */
805 /*    DATE              NAME                      DESCRIPTION             */
806 /*                                                                        */
807 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
808 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
809 /*                                            resulting in version 6.1    */
810 /*                                                                        */
811 /**************************************************************************/
_nxe_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))812 UINT _nxe_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
813 {
814 
815 UINT    status;
816 
817 
818     /* Check for invalid input pointers.  */
819     if (!mdns_ptr)
820     {
821         return(NX_PTR_ERROR);
822     }
823 
824     /* Check for invalid non pointer input. */
825     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
826     {
827         return(NX_MDNS_PARAM_ERROR);
828     }
829 
830     /* Call actual mDNS cache notify set function.  */
831     status =  _nx_mdns_cache_notify_set(mdns_ptr, cache_full_notify_cb);
832 
833     /* Return status.  */
834     return(status);
835 }
836 
837 
838 /**************************************************************************/
839 /*                                                                        */
840 /*  FUNCTION                                               RELEASE        */
841 /*                                                                        */
842 /*    _nx_mdns_cache_notify_set                           PORTABLE C      */
843 /*                                                           6.1          */
844 /*  AUTHOR                                                                */
845 /*                                                                        */
846 /*    Yuxin Zhou, Microsoft Corporation                                   */
847 /*                                                                        */
848 /*  DESCRIPTION                                                           */
849 /*                                                                        */
850 /*    This function set the cache full notify function.                   */
851 /*                                                                        */
852 /*  INPUT                                                                 */
853 /*                                                                        */
854 /*    mdns_ptr                              Pointer to mDNS instance      */
855 /*                                                                        */
856 /*  OUTPUT                                                                */
857 /*                                                                        */
858 /*    status                                Completion status             */
859 /*                                                                        */
860 /*  CALLS                                                                 */
861 /*                                                                        */
862 /*    tx_mutex_get                          Get the mDNS mutex            */
863 /*    tx_mutex_put                          Put the mDNS mutex            */
864 /*                                                                        */
865 /*  CALLED BY                                                             */
866 /*                                                                        */
867 /*    Application Code                                                    */
868 /*                                                                        */
869 /*  RELEASE HISTORY                                                       */
870 /*                                                                        */
871 /*    DATE              NAME                      DESCRIPTION             */
872 /*                                                                        */
873 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
874 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
875 /*                                            resulting in version 6.1    */
876 /*                                                                        */
877 /**************************************************************************/
_nx_mdns_cache_notify_set(NX_MDNS * mdns_ptr,VOID (* cache_full_notify_cb)(NX_MDNS * mdns_ptr,UINT,UINT))878 UINT _nx_mdns_cache_notify_set(NX_MDNS *mdns_ptr, VOID (*cache_full_notify_cb)(NX_MDNS *mdns_ptr, UINT, UINT))
879 {
880 
881 
882     /* Get the mDNS mutex.  */
883     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
884 
885     /* Set the cache notify.  */
886     mdns_ptr -> nx_mdns_cache_full_notify = cache_full_notify_cb;
887 
888     /* Release the mDNS mutex.  */
889     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
890 
891     return(NX_MDNS_SUCCESS);
892 }
893 
894 
895 /**************************************************************************/
896 /*                                                                        */
897 /*  FUNCTION                                               RELEASE        */
898 /*                                                                        */
899 /*    _nxe_mdns_cache_notify_clear                        PORTABLE C      */
900 /*                                                           6.1          */
901 /*  AUTHOR                                                                */
902 /*                                                                        */
903 /*    Yuxin Zhou, Microsoft Corporation                                   */
904 /*                                                                        */
905 /*  DESCRIPTION                                                           */
906 /*                                                                        */
907 /*    This function checks for errors in the mDNS cache full notify       */
908 /*    function call.                                                      */
909 /*                                                                        */
910 /*  INPUT                                                                 */
911 /*                                                                        */
912 /*    mdns_ptr                              Pointer to mDNS instance      */
913 /*    cache_full_notify                     Cache full notify function    */
914 /*                                                                        */
915 /*  OUTPUT                                                                */
916 /*                                                                        */
917 /*    status                                Completion status             */
918 /*                                                                        */
919 /*  CALLS                                                                 */
920 /*                                                                        */
921 /*    _nx_mdns_cache_notify_clear           Actual cache notify           */
922 /*                                            clear function              */
923 /*                                                                        */
924 /*  CALLED BY                                                             */
925 /*                                                                        */
926 /*    Application Code                                                    */
927 /*                                                                        */
928 /*  RELEASE HISTORY                                                       */
929 /*                                                                        */
930 /*    DATE              NAME                      DESCRIPTION             */
931 /*                                                                        */
932 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
933 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
934 /*                                            resulting in version 6.1    */
935 /*                                                                        */
936 /**************************************************************************/
_nxe_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)937 UINT _nxe_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
938 {
939 
940 UINT    status;
941 
942 
943     /* Check for invalid input pointers.  */
944     if (!mdns_ptr)
945     {
946         return(NX_PTR_ERROR);
947     }
948 
949     /* Check for invalid non pointer input. */
950     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
951     {
952         return(NX_MDNS_PARAM_ERROR);
953     }
954 
955     /* Call actual mDNS cache notify clear function.  */
956     status =  _nx_mdns_cache_notify_clear(mdns_ptr);
957 
958     /* Return status.  */
959     return(status);
960 }
961 
962 
963 /**************************************************************************/
964 /*                                                                        */
965 /*  FUNCTION                                               RELEASE        */
966 /*                                                                        */
967 /*    _nx_mdns_cache_notify_clear                         PORTABLE C      */
968 /*                                                           6.1          */
969 /*  AUTHOR                                                                */
970 /*                                                                        */
971 /*    Yuxin Zhou, Microsoft Corporation                                   */
972 /*                                                                        */
973 /*  DESCRIPTION                                                           */
974 /*                                                                        */
975 /*    This function set the cache full notify function.                   */
976 /*                                                                        */
977 /*  INPUT                                                                 */
978 /*                                                                        */
979 /*    mdns_ptr                              Pointer to mDNS instance      */
980 /*                                                                        */
981 /*  OUTPUT                                                                */
982 /*                                                                        */
983 /*    status                                Completion status             */
984 /*                                                                        */
985 /*  CALLS                                                                 */
986 /*                                                                        */
987 /*    tx_mutex_get                          Get the mDNS mutex            */
988 /*    tx_mutex_put                          Put the mDNS mutex            */
989 /*                                                                        */
990 /*  CALLED BY                                                             */
991 /*                                                                        */
992 /*    Application Code                                                    */
993 /*                                                                        */
994 /*  RELEASE HISTORY                                                       */
995 /*                                                                        */
996 /*    DATE              NAME                      DESCRIPTION             */
997 /*                                                                        */
998 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
999 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1000 /*                                            resulting in version 6.1    */
1001 /*                                                                        */
1002 /**************************************************************************/
_nx_mdns_cache_notify_clear(NX_MDNS * mdns_ptr)1003 UINT _nx_mdns_cache_notify_clear(NX_MDNS *mdns_ptr)
1004 {
1005 
1006 
1007     /* Get the mDNS mutex.  */
1008     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1009 
1010     /* Clear the cache notify.  */
1011     mdns_ptr -> nx_mdns_cache_full_notify = NX_NULL;
1012 
1013     /* Release the mDNS mutex.  */
1014     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1015 
1016     return(NX_MDNS_SUCCESS);
1017 }
1018 
1019 
1020 #ifndef NX_MDNS_DISABLE_CLIENT
1021 /**************************************************************************/
1022 /*                                                                        */
1023 /*  FUNCTION                                               RELEASE        */
1024 /*                                                                        */
1025 /*    _nxe_mdns_service_ignore_set                        PORTABLE C      */
1026 /*                                                           6.1          */
1027 /*  AUTHOR                                                                */
1028 /*                                                                        */
1029 /*    Yuxin Zhou, Microsoft Corporation                                   */
1030 /*                                                                        */
1031 /*  DESCRIPTION                                                           */
1032 /*                                                                        */
1033 /*    This function checks for errors in the mDNS service ignore mask     */
1034 /*    set function call.                                                  */
1035 /*                                                                        */
1036 /*  INPUT                                                                 */
1037 /*                                                                        */
1038 /*    mdns_ptr                              Pointer to mDNS instance      */
1039 /*    service_mask                          The service mask              */
1040 /*                                                                        */
1041 /*  OUTPUT                                                                */
1042 /*                                                                        */
1043 /*    status                                Completion status             */
1044 /*                                                                        */
1045 /*  CALLS                                                                 */
1046 /*                                                                        */
1047 /*    _nx_mdns_service_ignore_set           Actual ignore set function    */
1048 /*                                                                        */
1049 /*  CALLED BY                                                             */
1050 /*                                                                        */
1051 /*    Application Code                                                    */
1052 /*                                                                        */
1053 /*  RELEASE HISTORY                                                       */
1054 /*                                                                        */
1055 /*    DATE              NAME                      DESCRIPTION             */
1056 /*                                                                        */
1057 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1058 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1059 /*                                            resulting in version 6.1    */
1060 /*                                                                        */
1061 /**************************************************************************/
_nxe_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1062 UINT _nxe_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1063 {
1064 
1065 UINT    status;
1066 
1067 
1068     /* Check for invalid input pointers.  */
1069     if (!mdns_ptr)
1070     {
1071         return(NX_PTR_ERROR);
1072     }
1073 
1074     /* Check for invalid non pointer input. */
1075     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1076     {
1077         return(NX_MDNS_PARAM_ERROR);
1078     }
1079 
1080     /* Call actual mDNS service ignore mask set function.  */
1081     status =  _nx_mdns_service_ignore_set(mdns_ptr, service_mask);
1082 
1083     /* Return status.  */
1084     return(status);
1085 }
1086 
1087 
1088 /**************************************************************************/
1089 /*                                                                        */
1090 /*  FUNCTION                                               RELEASE        */
1091 /*                                                                        */
1092 /*    _nx_mdns_service_ignore_set                         PORTABLE C      */
1093 /*                                                           6.1          */
1094 /*  AUTHOR                                                                */
1095 /*                                                                        */
1096 /*    Yuxin Zhou, Microsoft Corporation                                   */
1097 /*                                                                        */
1098 /*  DESCRIPTION                                                           */
1099 /*                                                                        */
1100 /*    This function sets the service mask to ignore the service.          */
1101 /*                                                                        */
1102 /*  INPUT                                                                 */
1103 /*                                                                        */
1104 /*    mdns_ptr                              Pointer to mDNS instance      */
1105 /*    service_mask                          The service mask              */
1106 /*                                                                        */
1107 /*  OUTPUT                                                                */
1108 /*                                                                        */
1109 /*    status                                Completion status             */
1110 /*                                                                        */
1111 /*  CALLS                                                                 */
1112 /*                                                                        */
1113 /*    tx_mutex_get                          Get the MDNS mutex            */
1114 /*    tx_mutex_put                          Put the MDNS mutex            */
1115 /*                                                                        */
1116 /*  CALLED BY                                                             */
1117 /*                                                                        */
1118 /*    Application Code                                                    */
1119 /*                                                                        */
1120 /*  RELEASE HISTORY                                                       */
1121 /*                                                                        */
1122 /*    DATE              NAME                      DESCRIPTION             */
1123 /*                                                                        */
1124 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1125 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1126 /*                                            resulting in version 6.1    */
1127 /*                                                                        */
1128 /**************************************************************************/
_nx_mdns_service_ignore_set(NX_MDNS * mdns_ptr,ULONG service_mask)1129 UINT _nx_mdns_service_ignore_set(NX_MDNS *mdns_ptr, ULONG service_mask)
1130 {
1131 
1132 
1133     /* Get the mDNS mutex.  */
1134     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1135 
1136     /* Set the service ignore mask.  */
1137     mdns_ptr -> nx_mdns_service_ignore_mask = service_mask;
1138 
1139     /* Release the mDNS mutex.  */
1140     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1141 
1142     return(NX_MDNS_SUCCESS);
1143 }
1144 
1145 
1146 /**************************************************************************/
1147 /*                                                                        */
1148 /*  FUNCTION                                               RELEASE        */
1149 /*                                                                        */
1150 /*    _nxe_mdns_service_notify_set                        PORTABLE C      */
1151 /*                                                           6.1          */
1152 /*  AUTHOR                                                                */
1153 /*                                                                        */
1154 /*    Yuxin Zhou, Microsoft Corporation                                   */
1155 /*                                                                        */
1156 /*  DESCRIPTION                                                           */
1157 /*                                                                        */
1158 /*    This function checks for errors in the mDNS service notify function */
1159 /*    call.                                                               */
1160 /*                                                                        */
1161 /*  INPUT                                                                 */
1162 /*                                                                        */
1163 /*    mdns_ptr                              Pointer to mDNS instance      */
1164 /*    service_mask                          The service mask              */
1165 /*    service_change_notify                 Service change notify function*/
1166 /*                                                                        */
1167 /*  OUTPUT                                                                */
1168 /*                                                                        */
1169 /*    status                                Completion status             */
1170 /*                                                                        */
1171 /*  CALLS                                                                 */
1172 /*                                                                        */
1173 /*    _nx_mdns_service_notify_set           Actual mDNS service notify    */
1174 /*                                            set function                */
1175 /*                                                                        */
1176 /*  CALLED BY                                                             */
1177 /*                                                                        */
1178 /*    Application Code                                                    */
1179 /*                                                                        */
1180 /*  RELEASE HISTORY                                                       */
1181 /*                                                                        */
1182 /*    DATE              NAME                      DESCRIPTION             */
1183 /*                                                                        */
1184 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1185 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1186 /*                                            resulting in version 6.1    */
1187 /*                                                                        */
1188 /**************************************************************************/
_nxe_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1189 UINT _nxe_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1190                                   VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1191 {
1192 
1193 UINT    status;
1194 
1195 
1196     /* Check for invalid input pointers.  */
1197     if (!mdns_ptr)
1198     {
1199         return(NX_PTR_ERROR);
1200     }
1201 
1202     /* Check for invalid non pointer input. */
1203     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1204     {
1205         return(NX_MDNS_PARAM_ERROR);
1206     }
1207 
1208     /* Call actual mDNS service notify set function.  */
1209     status =  _nx_mdns_service_notify_set(mdns_ptr, service_mask, service_change_notify);
1210 
1211     /* Return status.  */
1212     return(status);
1213 }
1214 
1215 
1216 /**************************************************************************/
1217 /*                                                                        */
1218 /*  FUNCTION                                               RELEASE        */
1219 /*                                                                        */
1220 /*    _nx_mdns_service_notify_set                         PORTABLE C      */
1221 /*                                                           6.1          */
1222 /*  AUTHOR                                                                */
1223 /*                                                                        */
1224 /*    Yuxin Zhou, Microsoft Corporation                                   */
1225 /*                                                                        */
1226 /*  DESCRIPTION                                                           */
1227 /*                                                                        */
1228 /*    This function set the service mask and notify callback function.    */
1229 /*                                                                        */
1230 /*  INPUT                                                                 */
1231 /*                                                                        */
1232 /*    mdns_ptr                              Pointer to mDNS instance      */
1233 /*    service_mask                          The service mask              */
1234 /*    service_change_notify                 Service change notify function*/
1235 /*                                                                        */
1236 /*  OUTPUT                                                                */
1237 /*                                                                        */
1238 /*    status                                Completion status             */
1239 /*                                                                        */
1240 /*  CALLS                                                                 */
1241 /*                                                                        */
1242 /*    tx_mutex_get                          Get the mDNS mutex            */
1243 /*    tx_mutex_put                          Put the mDNS mutex            */
1244 /*                                                                        */
1245 /*  CALLED BY                                                             */
1246 /*                                                                        */
1247 /*    Application Code                                                    */
1248 /*                                                                        */
1249 /*  RELEASE HISTORY                                                       */
1250 /*                                                                        */
1251 /*    DATE              NAME                      DESCRIPTION             */
1252 /*                                                                        */
1253 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1254 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1255 /*                                            resulting in version 6.1    */
1256 /*                                                                        */
1257 /**************************************************************************/
_nx_mdns_service_notify_set(NX_MDNS * mdns_ptr,ULONG service_mask,VOID (* service_change_notify)(NX_MDNS * mdns_ptr,NX_MDNS_SERVICE * service_ptr,UINT state))1258 UINT _nx_mdns_service_notify_set(NX_MDNS *mdns_ptr, ULONG service_mask,
1259                                  VOID (*service_change_notify)(NX_MDNS *mdns_ptr, NX_MDNS_SERVICE *service_ptr, UINT state))
1260 {
1261 
1262 
1263     /* Get the mDNS mutex.  */
1264     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1265 
1266     /* Set the service mask.  */
1267     mdns_ptr -> nx_mdns_service_notify_mask = service_mask;
1268 
1269     /* Assign the service change notify. */
1270     mdns_ptr -> nx_mdns_service_change_notify = service_change_notify;
1271 
1272     /* Release the mDNS mutex.  */
1273     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1274 
1275     return(NX_MDNS_SUCCESS);
1276 }
1277 
1278 
1279 /**************************************************************************/
1280 /*                                                                        */
1281 /*  FUNCTION                                               RELEASE        */
1282 /*                                                                        */
1283 /*    _nxe_mdns_service_notify_clear                      PORTABLE C      */
1284 /*                                                           6.1          */
1285 /*  AUTHOR                                                                */
1286 /*                                                                        */
1287 /*    Yuxin Zhou, Microsoft Corporation                                   */
1288 /*                                                                        */
1289 /*  DESCRIPTION                                                           */
1290 /*                                                                        */
1291 /*    This function checks for errors in the mDNS service notify function */
1292 /*    call.                                                               */
1293 /*                                                                        */
1294 /*  INPUT                                                                 */
1295 /*                                                                        */
1296 /*    mdns_ptr                              Pointer to mDNS instance      */
1297 /*                                                                        */
1298 /*  OUTPUT                                                                */
1299 /*                                                                        */
1300 /*    status                                Completion status             */
1301 /*                                                                        */
1302 /*  CALLS                                                                 */
1303 /*                                                                        */
1304 /*    _nx_mdns_service_notify_clear         Actual service notify         */
1305 /*                                            clear function              */
1306 /*                                                                        */
1307 /*  CALLED BY                                                             */
1308 /*                                                                        */
1309 /*    Application Code                                                    */
1310 /*                                                                        */
1311 /*  RELEASE HISTORY                                                       */
1312 /*                                                                        */
1313 /*    DATE              NAME                      DESCRIPTION             */
1314 /*                                                                        */
1315 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1316 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1317 /*                                            resulting in version 6.1    */
1318 /*                                                                        */
1319 /**************************************************************************/
_nxe_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1320 UINT _nxe_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1321 {
1322 
1323 UINT    status;
1324 
1325 
1326     /* Check for invalid input pointers.  */
1327     if (!mdns_ptr)
1328     {
1329 
1330         return(NX_PTR_ERROR);
1331     }
1332 
1333     /* Check for invalid non pointer input. */
1334     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1335     {
1336 
1337         return(NX_MDNS_PARAM_ERROR);
1338     }
1339 
1340     /* Call actual mDNS service notify clear function.  */
1341     status =  _nx_mdns_service_notify_clear(mdns_ptr);
1342 
1343     /* Return status.  */
1344     return(status);
1345 }
1346 
1347 
1348 /**************************************************************************/
1349 /*                                                                        */
1350 /*  FUNCTION                                               RELEASE        */
1351 /*                                                                        */
1352 /*    _nx_mdns_service_notify_clear                       PORTABLE C      */
1353 /*                                                           6.1          */
1354 /*  AUTHOR                                                                */
1355 /*                                                                        */
1356 /*    Yuxin Zhou, Microsoft Corporation                                   */
1357 /*                                                                        */
1358 /*  DESCRIPTION                                                           */
1359 /*                                                                        */
1360 /*    This function clears the service mask and notify callback function. */
1361 /*                                                                        */
1362 /*  INPUT                                                                 */
1363 /*                                                                        */
1364 /*    mdns_ptr                              Pointer to mDNS instance      */
1365 /*                                                                        */
1366 /*  OUTPUT                                                                */
1367 /*                                                                        */
1368 /*    status                                Completion status             */
1369 /*                                                                        */
1370 /*  CALLS                                                                 */
1371 /*                                                                        */
1372 /*    tx_mutex_get                          Get the mDNS mutex            */
1373 /*    tx_mutex_put                          Put the mDNS mutex            */
1374 /*                                                                        */
1375 /*  CALLED BY                                                             */
1376 /*                                                                        */
1377 /*    Application Code                                                    */
1378 /*                                                                        */
1379 /*  RELEASE HISTORY                                                       */
1380 /*                                                                        */
1381 /*    DATE              NAME                      DESCRIPTION             */
1382 /*                                                                        */
1383 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1384 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1385 /*                                            resulting in version 6.1    */
1386 /*                                                                        */
1387 /**************************************************************************/
_nx_mdns_service_notify_clear(NX_MDNS * mdns_ptr)1388 UINT _nx_mdns_service_notify_clear(NX_MDNS *mdns_ptr)
1389 {
1390 
1391 
1392     /* Get the mDNS mutex.  */
1393     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1394 
1395     /* Clear the service mask.  */
1396     mdns_ptr -> nx_mdns_service_notify_mask = 0;
1397 
1398     /* Clear the service change notify. */
1399     mdns_ptr -> nx_mdns_service_change_notify = NX_NULL;
1400 
1401     /* Release the mDNS mutex.  */
1402     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1403 
1404     return(NX_MDNS_SUCCESS);
1405 }
1406 #endif /* NX_MDNS_DISABLE_CLIENT  */
1407 
1408 
1409 #ifndef NX_MDNS_DISABLE_SERVER
1410 /**************************************************************************/
1411 /*                                                                        */
1412 /*  FUNCTION                                               RELEASE        */
1413 /*                                                                        */
1414 /*    _nxe_mdns_service_announcement_timing_set           PORTABLE C      */
1415 /*                                                           6.1          */
1416 /*  AUTHOR                                                                */
1417 /*                                                                        */
1418 /*    Yuxin Zhou, Microsoft Corporation                                   */
1419 /*                                                                        */
1420 /*  DESCRIPTION                                                           */
1421 /*                                                                        */
1422 /*    This function checks for errors in the mDNS announcement timing     */
1423 /*    set function call.                                                  */
1424 /*                                                                        */
1425 /*  INPUT                                                                 */
1426 /*                                                                        */
1427 /*    mdns_ptr                              Pointer to mDNS instance      */
1428 /*    t                                     Announcing period             */
1429 /*    p                                     Announcing count              */
1430 /*    k                                     Announcing factor             */
1431 /*    retrans_interval                      Announcing retransmission     */
1432 /*                                            interval                    */
1433 /*    interval                              Announcing period interval    */
1434 /*    max_time                              Announcing max time           */
1435 /*                                                                        */
1436 /*  OUTPUT                                                                */
1437 /*                                                                        */
1438 /*    status                                Completion status             */
1439 /*                                                                        */
1440 /*  CALLS                                                                 */
1441 /*                                                                        */
1442 /*    _nx_mdns_service_announcement_timing_set                            */
1443 /*                                          Actual mDNS announcement      */
1444 /*                                            timing set function         */
1445 /*                                                                        */
1446 /*  CALLED BY                                                             */
1447 /*                                                                        */
1448 /*    Application Code                                                    */
1449 /*                                                                        */
1450 /*  RELEASE HISTORY                                                       */
1451 /*                                                                        */
1452 /*    DATE              NAME                      DESCRIPTION             */
1453 /*                                                                        */
1454 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1455 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1456 /*                                            resulting in version 6.1    */
1457 /*                                                                        */
1458 /**************************************************************************/
_nxe_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1459 UINT _nxe_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1460 {
1461 
1462 UINT    status;
1463 
1464 
1465     /* Check for invalid input pointers.  */
1466     if ((!mdns_ptr) || (!t) || (!p) || (!k) || (!period_interval) || (!max_time))
1467     {
1468         return(NX_PTR_ERROR);
1469     }
1470 
1471     /* Check for invalid non pointer input. */
1472     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1473     {
1474         return(NX_MDNS_PARAM_ERROR);
1475     }
1476 
1477     /* Call actual mDNS delete service.  */
1478     status =  _nx_mdns_service_announcement_timing_set(mdns_ptr, t, p, k, retrans_interval, period_interval, max_time);
1479 
1480     /* Return status.  */
1481     return(status);
1482 }
1483 
1484 
1485 /**************************************************************************/
1486 /*                                                                        */
1487 /*  FUNCTION                                               RELEASE        */
1488 /*                                                                        */
1489 /*    _nx_mdns_service_announcement_timing_set            PORTABLE C      */
1490 /*                                                           6.1          */
1491 /*  AUTHOR                                                                */
1492 /*                                                                        */
1493 /*    Yuxin Zhou, Microsoft Corporation                                   */
1494 /*                                                                        */
1495 /*  DESCRIPTION                                                           */
1496 /*                                                                        */
1497 /*    This function set the service mask and notify callback function.    */
1498 /*                                                                        */
1499 /*  INPUT                                                                 */
1500 /*                                                                        */
1501 /*    mdns_ptr                              Pointer to mDNS instance      */
1502 /*    t                                     Announcing period             */
1503 /*    p                                     Announcing count              */
1504 /*    k                                     Announcing factor             */
1505 /*    retrans_interval                      Announcing retransmission     */
1506 /*                                            interval                    */
1507 /*    interval                              Announcing period interval    */
1508 /*    max_time                              Announcing max time           */
1509 /*                                                                        */
1510 /*  OUTPUT                                                                */
1511 /*                                                                        */
1512 /*    status                                Completion status             */
1513 /*                                                                        */
1514 /*  CALLS                                                                 */
1515 /*                                                                        */
1516 /*    tx_mutex_get                          Get the mDNS mutex            */
1517 /*    tx_mutex_put                          Put the mDNS mutex            */
1518 /*                                                                        */
1519 /*  CALLED BY                                                             */
1520 /*                                                                        */
1521 /*    Application Code                                                    */
1522 /*                                                                        */
1523 /*  RELEASE HISTORY                                                       */
1524 /*                                                                        */
1525 /*    DATE              NAME                      DESCRIPTION             */
1526 /*                                                                        */
1527 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1528 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1529 /*                                            resulting in version 6.1    */
1530 /*                                                                        */
1531 /**************************************************************************/
_nx_mdns_service_announcement_timing_set(NX_MDNS * mdns_ptr,UINT t,UINT p,UINT k,UINT retrans_interval,ULONG period_interval,UINT max_time)1532 UINT _nx_mdns_service_announcement_timing_set(NX_MDNS *mdns_ptr, UINT t, UINT p, UINT k, UINT retrans_interval, ULONG period_interval, UINT max_time)
1533 {
1534 
1535 
1536     /* Get the mDNS mutex.  */
1537     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1538 
1539     /* Set the mDNS announcing period.  */
1540     mdns_ptr -> nx_mdns_announcing_period = (USHORT)t;
1541 
1542     /* Set the mDNS announcing count between one announcing period.  */
1543     mdns_ptr -> nx_mdns_announcing_count = (UCHAR)p;
1544 
1545     /* Set the mDNS announcing factor.  */
1546     mdns_ptr -> nx_mdns_announcing_factor = (UCHAR)k;
1547 
1548     /* Set the mDNS announcing retransmission interval.  */
1549     mdns_ptr -> nx_mdns_announcing_retrans_interval = (USHORT)retrans_interval;
1550 
1551     /* Set the mDNS announcing period interval.  */
1552     mdns_ptr -> nx_mdns_announcing_period_interval = (ULONG)period_interval;
1553 
1554     /* Set the mDNS announcing max time.  */
1555     mdns_ptr -> nx_mdns_announcing_max_time = (UCHAR)max_time;
1556 
1557     /* Release the mDNS mutex.  */
1558     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1559 
1560     return(NX_MDNS_SUCCESS);
1561 }
1562 #endif /* NX_MDNS_DISABLE_SERVER  */
1563 
1564 
1565 /**************************************************************************/
1566 /*                                                                        */
1567 /*  FUNCTION                                               RELEASE        */
1568 /*                                                                        */
1569 /*    _nxe_mdns_enable                                    PORTABLE C      */
1570 /*                                                           6.1          */
1571 /*  AUTHOR                                                                */
1572 /*                                                                        */
1573 /*    Yuxin Zhou, Microsoft Corporation                                   */
1574 /*                                                                        */
1575 /*  DESCRIPTION                                                           */
1576 /*                                                                        */
1577 /*    This function checks for errors in the mDNS enable function call.   */
1578 /*                                                                        */
1579 /*  INPUT                                                                 */
1580 /*                                                                        */
1581 /*    mdns_ptr                              Pointer to mDNS instance      */
1582 /*    interface_index                       The interface index           */
1583 /*                                                                        */
1584 /*  OUTPUT                                                                */
1585 /*                                                                        */
1586 /*    status                                Completion status             */
1587 /*                                                                        */
1588 /*  CALLS                                                                 */
1589 /*                                                                        */
1590 /*    _nx_mdns_enable                       Actual mDNS enable function   */
1591 /*                                                                        */
1592 /*  CALLED BY                                                             */
1593 /*                                                                        */
1594 /*    Application Code                                                    */
1595 /*                                                                        */
1596 /*  RELEASE HISTORY                                                       */
1597 /*                                                                        */
1598 /*    DATE              NAME                      DESCRIPTION             */
1599 /*                                                                        */
1600 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1601 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1602 /*                                            resulting in version 6.1    */
1603 /*                                                                        */
1604 /**************************************************************************/
_nxe_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1605 UINT _nxe_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1606 {
1607 
1608 UINT    status;
1609 
1610 
1611     /* Check for invalid input pointers.  */
1612     if (!mdns_ptr)
1613     {
1614         return(NX_PTR_ERROR);
1615     }
1616 
1617     /* Check for invalid non pointer input or invalid server attributes. */
1618     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1619     {
1620         return(NX_MDNS_PARAM_ERROR);
1621     }
1622 
1623     /* Call actual mDNS delete service.  */
1624     status =  _nx_mdns_enable(mdns_ptr, interface_index);
1625 
1626     /* Return status.  */
1627     return(status);
1628 }
1629 
1630 
1631 /**************************************************************************/
1632 /*                                                                        */
1633 /*  FUNCTION                                               RELEASE        */
1634 /*                                                                        */
1635 /*    _nx_mdns_enable                                     PORTABLE C      */
1636 /*                                                           6.1          */
1637 /*  AUTHOR                                                                */
1638 /*                                                                        */
1639 /*    Yuxin Zhou, Microsoft Corporation                                   */
1640 /*                                                                        */
1641 /*  DESCRIPTION                                                           */
1642 /*                                                                        */
1643 /*    This function enables the mDNS of the physical host interface by    */
1644 /*    interface index.                                                    */
1645 /*                                                                        */
1646 /*  INPUT                                                                 */
1647 /*                                                                        */
1648 /*    mdns_ptr                              Pointer to mDNS instance      */
1649 /*    interface_index                       The interface index           */
1650 /*                                                                        */
1651 /*  OUTPUT                                                                */
1652 /*                                                                        */
1653 /*    status                                Completion status             */
1654 /*                                                                        */
1655 /*  CALLS                                                                 */
1656 /*                                                                        */
1657 /*    tx_mutex_get                          Get the mDNS mutex            */
1658 /*    tx_mutex_put                          Put the mDNS mutex            */
1659 /*    nx_ipv4_multicast_interface_join      Join the IPv4 Multicast group */
1660 /*    nxd_ipv6_multicast_interface_join     Join the IPv6 Multicast group */
1661 /*    _nx_mdns_host_name_register           Register the host name        */
1662 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
1663 /*                                                                        */
1664 /*  CALLED BY                                                             */
1665 /*                                                                        */
1666 /*    Application Code                                                    */
1667 /*                                                                        */
1668 /*  RELEASE HISTORY                                                       */
1669 /*                                                                        */
1670 /*    DATE              NAME                      DESCRIPTION             */
1671 /*                                                                        */
1672 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1673 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1674 /*                                            resulting in version 6.1    */
1675 /*                                                                        */
1676 /**************************************************************************/
_nx_mdns_enable(NX_MDNS * mdns_ptr,UINT interface_index)1677 UINT _nx_mdns_enable(NX_MDNS *mdns_ptr, UINT interface_index)
1678 {
1679 
1680 UINT        status;
1681 
1682 #ifndef NX_MDNS_DISABLE_SERVER
1683 ULONG       *head;
1684 NX_MDNS_RR  *p;
1685 #endif /* NX_MDNS_DISABLE_SERVER */
1686 
1687 #ifdef NX_MDNS_ENABLE_IPV6
1688 NX_INTERFACE        *interface_ptr;
1689 NXD_IPV6_ADDRESS    *ipv6_address;
1690 #endif /* NX_MDNS_ENABLE_IPV6  */
1691 
1692     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1693     {
1694         return(NX_MDNS_PARAM_ERROR);
1695     }
1696 
1697     /* Check to see if mDNS is already enabled on this interface.  */
1698     if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_TRUE)
1699     {
1700         return(NX_MDNS_ALREADY_ENABLED);
1701     }
1702 
1703     /* Get the mDNS mutex.  */
1704     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
1705 
1706     /* Enable the mdns function.  */
1707     mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_TRUE;
1708 
1709 #ifdef NX_MDNS_ENABLE_IPV6
1710     /* Set the interface pointer.  */
1711     interface_ptr = &(mdns_ptr -> nx_mdns_ip_ptr -> nx_ip_interface[interface_index]);
1712 
1713     /* Find the link-local address as source adress. Get first address from interface.  */
1714     ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
1715 
1716     /* Loop to check the address.  */
1717     while (ipv6_address)
1718     {
1719 
1720         /* Check for link-local address. */
1721         if (IPv6_Address_Type(ipv6_address -> nxd_ipv6_address) & IPV6_ADDRESS_LINKLOCAL)
1722         {
1723             break;
1724         }
1725         ipv6_address = ipv6_address -> nxd_ipv6_address_next;
1726     }
1727 
1728     /* Check if found the link-local address.  */
1729     if(ipv6_address)
1730     {
1731 
1732         /* Set the IPv6 link-local address index.  */
1733         mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = ipv6_address -> nxd_ipv6_address_index;
1734     }
1735     else
1736     {
1737 
1738         /* No available address, set the address index as 0xFFFFFFFF.  */
1739         mdns_ptr -> nx_mdns_ipv6_address_index[interface_index] = 0xFFFFFFFF;
1740     }
1741 #endif /* NX_MDNS_ENABLE_IPV6  */
1742 
1743     /* Join the group.  */
1744     status = nx_ipv4_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
1745 
1746     /* Check status.  */
1747     if (status)
1748     {
1749 
1750         /* Release the mDNS mutex.  */
1751         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1752         return(status);
1753     }
1754 
1755 #ifdef NX_MDNS_ENABLE_IPV6
1756     status = nxd_ipv6_multicast_interface_join(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
1757 
1758     /* Check status.  */
1759     if (status)
1760     {
1761 
1762         /* Release the mDNS mutex.  */
1763         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1764         return(status);
1765     }
1766 #endif /* NX_MDNS_ENABLE_IPV6  */
1767 
1768 #ifndef NX_MDNS_DISABLE_SERVER
1769 
1770     /* Register the host name.  */
1771     status = _nx_mdns_host_name_register(mdns_ptr, NX_TRUE, interface_index);
1772 
1773     /* Check status.  */
1774     if (status)
1775     {
1776 
1777         /* Release the mDNS mutex.  */
1778         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1779         return(status);
1780     }
1781 
1782     /* Probing the all resource record wheneven a Multicast DNS responder starts up, waks up from sleep, receives an indication of a network interface "Link CHange" event.RFC6762, Section8, Page25.   */
1783 
1784     /* Get the header to the local buffer. */
1785     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
1786 
1787     /* Set the pointer.  */
1788     head = (ULONG*)(*head);
1789 
1790     /* Check the resource record.  */
1791     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
1792     {
1793 
1794         /* Check the interface index.  */
1795         if (p -> nx_mdns_rr_interface_index != interface_index)
1796             continue;
1797 
1798         /* Check whether the resource record is valid. */
1799         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
1800             continue;
1801 
1802         /* Check the state and delete flag, GOODBYE state and DELETE FLAG means this resource record should be deleted.  */
1803         if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) &&
1804             (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE))
1805         {
1806 
1807             /* Delete the resource records.  */
1808             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
1809             continue;
1810         }
1811 
1812         /* Check the resource reocrd type.  */
1813         if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) ||
1814             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))
1815         {
1816             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
1817             continue;
1818         }
1819 
1820         /* Check the unique flag.  */
1821         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
1822         {
1823             /* For a unique type, we need to probe it on the network
1824             to guarantee its uniqueness. */
1825             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
1826             p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
1827             p -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
1828         }
1829         else
1830         {
1831             /* If the record is not marked as unique, start the announcement process. */
1832             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
1833             p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
1834             p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
1835 
1836             /* Check the announcing max time.  */
1837             if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
1838                 p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
1839             else
1840                 p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
1841 
1842             /* Set the retransmit count.  */
1843             if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
1844                 p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
1845             else
1846                 p -> nx_mdns_rr_retransmit_count = 1;
1847         }
1848 
1849         /* Set the mDNS timer.  */
1850         _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
1851     }
1852 #endif /* NX_MDNS_DISABLE_SERVER */
1853 
1854     /* Set the mdns started flag.  */
1855     mdns_ptr -> nx_mdns_started = NX_TRUE;
1856 
1857     /* Release the mDNS mutex.  */
1858     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
1859 
1860     /* Return.  */
1861     return(NX_MDNS_SUCCESS);
1862 }
1863 
1864 
1865 /**************************************************************************/
1866 /*                                                                        */
1867 /*  FUNCTION                                               RELEASE        */
1868 /*                                                                        */
1869 /*    _nxe_mdns_disable                                   PORTABLE C      */
1870 /*                                                           6.1          */
1871 /*  AUTHOR                                                                */
1872 /*                                                                        */
1873 /*    Yuxin Zhou, Microsoft Corporation                                   */
1874 /*                                                                        */
1875 /*  DESCRIPTION                                                           */
1876 /*                                                                        */
1877 /*    This function checks for errors in the mDNS disable function call.  */
1878 /*                                                                        */
1879 /*  INPUT                                                                 */
1880 /*                                                                        */
1881 /*    mdns_ptr                              Pointer to mDNS instance      */
1882 /*    interface_index                       The interface index           */
1883 /*                                                                        */
1884 /*  OUTPUT                                                                */
1885 /*                                                                        */
1886 /*    status                                Completion status             */
1887 /*                                                                        */
1888 /*  CALLS                                                                 */
1889 /*                                                                        */
1890 /*    _nx_mdns_disable                      Actual mDNS disable function  */
1891 /*                                                                        */
1892 /*  CALLED BY                                                             */
1893 /*                                                                        */
1894 /*    Application Code                                                    */
1895 /*                                                                        */
1896 /*  RELEASE HISTORY                                                       */
1897 /*                                                                        */
1898 /*    DATE              NAME                      DESCRIPTION             */
1899 /*                                                                        */
1900 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1901 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1902 /*                                            resulting in version 6.1    */
1903 /*                                                                        */
1904 /**************************************************************************/
_nxe_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1905 UINT _nxe_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1906 {
1907 
1908 UINT    status;
1909 
1910 
1911     /* Check for invalid input pointers.  */
1912     if (!mdns_ptr)
1913     {
1914         return(NX_PTR_ERROR);
1915     }
1916 
1917     /* Check for invalid non pointer input or invalid server attributes. */
1918     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
1919     {
1920         return(NX_MDNS_PARAM_ERROR);
1921     }
1922 
1923     /* Call actual mDNS delete service.  */
1924     status =  _nx_mdns_disable(mdns_ptr, interface_index);
1925 
1926     /* Return status.  */
1927     return(status);
1928 }
1929 
1930 
1931 /**************************************************************************/
1932 /*                                                                        */
1933 /*  FUNCTION                                               RELEASE        */
1934 /*                                                                        */
1935 /*    _nx_mdns_disable                                    PORTABLE C      */
1936 /*                                                           6.1          */
1937 /*  AUTHOR                                                                */
1938 /*                                                                        */
1939 /*    Yuxin Zhou, Microsoft Corporation                                   */
1940 /*                                                                        */
1941 /*  DESCRIPTION                                                           */
1942 /*                                                                        */
1943 /*    This function disables the mDNS of the physical host interface by   */
1944 /*    interface index.                                                    */
1945 /*                                                                        */
1946 /*  INPUT                                                                 */
1947 /*                                                                        */
1948 /*    mdns_ptr                              Pointer to mDNS instance      */
1949 /*    interface_index                       The interface index           */
1950 /*                                                                        */
1951 /*  OUTPUT                                                                */
1952 /*                                                                        */
1953 /*    status                                Completion status             */
1954 /*                                                                        */
1955 /*  CALLS                                                                 */
1956 /*                                                                        */
1957 /*    tx_mutex_get                          Get the mDNS mutex            */
1958 /*    tx_mutex_put                          Put the mDNS mutex            */
1959 /*    nx_ipv4_multicast_leave               Leave the IPv4 Multicast group*/
1960 /*    nxd_ipv6_multicast_interface_leave    Leave the IPv6 Multicast group*/
1961 /*    _nx_mdns_cache_initialize             Initialize the mDNS peer cache*/
1962 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
1963 /*                                                                        */
1964 /*  CALLED BY                                                             */
1965 /*                                                                        */
1966 /*    Application Code                                                    */
1967 /*                                                                        */
1968 /*  RELEASE HISTORY                                                       */
1969 /*                                                                        */
1970 /*    DATE              NAME                      DESCRIPTION             */
1971 /*                                                                        */
1972 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1973 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1974 /*                                            resulting in version 6.1    */
1975 /*                                                                        */
1976 /**************************************************************************/
_nx_mdns_disable(NX_MDNS * mdns_ptr,UINT interface_index)1977 UINT _nx_mdns_disable(NX_MDNS *mdns_ptr, UINT interface_index)
1978 {
1979 
1980 UINT        dns_sd_size;
1981 UINT        i;
1982 ULONG       *head;
1983 NX_MDNS_RR  *p;
1984 
1985 
1986     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1987     {
1988         return(NX_MDNS_PARAM_ERROR);
1989     }
1990 
1991     /* Check to see if mDNS is not enabled on this interface.
1992        Note: Only support one interface yet.  */
1993     if (mdns_ptr -> nx_mdns_interface_enabled[interface_index] == NX_FALSE)
1994     {
1995         return(NX_MDNS_NOT_ENABLED);
1996     }
1997 
1998     /* Check the DNS-SD string.  */
1999     if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_size, NX_MDNS_DNS_SD_MAX))
2000     {
2001         return(NX_MDNS_DATA_SIZE_ERROR);
2002     }
2003 
2004     /* Get the mDNS mutex.  */
2005     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2006 
2007     /* Disable the mdns function.  */
2008     mdns_ptr -> nx_mdns_interface_enabled[interface_index] = NX_FALSE;
2009 
2010     /* Leave the group.  */
2011     nx_ipv4_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, interface_index);
2012 
2013 #ifdef NX_MDNS_ENABLE_IPV6
2014     nxd_ipv6_multicast_interface_leave(mdns_ptr -> nx_mdns_ip_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, interface_index);
2015 #endif /* NX_MDNS_ENABLE_IPV6  */
2016 
2017 #ifndef NX_MDNS_DISABLE_CLIENT
2018 
2019     /* Get the local buffer head. */
2020     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
2021 
2022     /* Set the pointer.  */
2023     head = (ULONG*)(*head);
2024 
2025     /* Delete all services on this interface.  */
2026     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2027     {
2028 
2029         /* Check whether the resource record is valid. */
2030         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2031             continue;
2032 
2033         /* Check the interface index.  */
2034         if (p -> nx_mdns_rr_interface_index != interface_index)
2035             continue;
2036 
2037         /* Delete the resource record.  */
2038         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
2039     }
2040 #endif /* NX_MDNS_DISABLE_CLIENT */
2041 
2042 #ifndef NX_MDNS_DISABLE_SERVER
2043 
2044     /* Get the local buffer head. */
2045     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2046 
2047     /* Set the pointer.  */
2048     head = (ULONG*)(*head);
2049 
2050     /* Send the Goodbye message, RFC6762, Section10.1, Page33.  */
2051     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2052     {
2053 
2054         /* Check whether the resource record is valid. */
2055         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2056             continue;
2057 
2058         /* Check the interface index.  */
2059         if (p -> nx_mdns_rr_interface_index != interface_index)
2060             continue;
2061 
2062         /* Skip the NSEC and DNS-SD PTR resource record.  */
2063         if ((p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) ||
2064             ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
2065              (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_size))))
2066         {
2067 
2068             /* Suspend the resource record.  */
2069             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
2070         }
2071         else
2072         {
2073 
2074             /* Set the state to send Goodbye packet.  */
2075             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
2076 
2077             /* Clear the retransmit count.  */
2078             p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
2079 
2080             /* Set the timer count. 250ms.  */
2081             p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
2082 
2083             /* Set the mDNS timer.  */
2084             _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
2085         }
2086     }
2087 #endif /* NX_MDNS_DISABLE_SERVER */
2088 
2089     /* Check if all interfaces are disabled.  */
2090     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
2091     {
2092         if (mdns_ptr -> nx_mdns_interface_enabled[i])
2093             break;
2094     }
2095 
2096     /* Set the mdns started flag.  */
2097     if (i == NX_MAX_PHYSICAL_INTERFACES)
2098         mdns_ptr -> nx_mdns_started = NX_FALSE;
2099 
2100     /* Release the mDNS mutex.  */
2101     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2102 
2103     return(NX_MDNS_SUCCESS);
2104 }
2105 
2106 
2107 /**************************************************************************/
2108 /*                                                                        */
2109 /*  FUNCTION                                               RELEASE        */
2110 /*                                                                        */
2111 /*    _nxe_mdns_local_domain_set                          PORTABLE C      */
2112 /*                                                           6.1          */
2113 /*  AUTHOR                                                                */
2114 /*                                                                        */
2115 /*    Yuxin Zhou, Microsoft Corporation                                   */
2116 /*                                                                        */
2117 /*  DESCRIPTION                                                           */
2118 /*                                                                        */
2119 /*    This function checks for errors in the mDNS domain sets             */
2120 /*    function call.                                                      */
2121 /*                                                                        */
2122 /*  INPUT                                                                 */
2123 /*                                                                        */
2124 /*    mdns_ptr                              Pointer to mDNS instance      */
2125 /*    domain_name                           Domain name                   */
2126 /*                                                                        */
2127 /*  OUTPUT                                                                */
2128 /*                                                                        */
2129 /*    status                                Completion status             */
2130 /*                                                                        */
2131 /*  CALLS                                                                 */
2132 /*                                                                        */
2133 /*    _nx_mdns_domain_name_set              Actual domain set function    */
2134 /*                                                                        */
2135 /*  CALLED BY                                                             */
2136 /*                                                                        */
2137 /*    Application Code                                                    */
2138 /*                                                                        */
2139 /*  RELEASE HISTORY                                                       */
2140 /*                                                                        */
2141 /*    DATE              NAME                      DESCRIPTION             */
2142 /*                                                                        */
2143 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2144 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2145 /*                                            resulting in version 6.1    */
2146 /*                                                                        */
2147 /**************************************************************************/
_nxe_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2148 UINT _nxe_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2149 {
2150 
2151 UINT    status;
2152 
2153 
2154     /* Check for invalid input pointers.  */
2155     if ((!mdns_ptr) || (!domain_name))
2156     {
2157         return(NX_PTR_ERROR);
2158     }
2159 
2160     /* Check for invalid non pointer input or invalid server attributes. */
2161     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2162     {
2163         return(NX_MDNS_PARAM_ERROR);
2164     }
2165 
2166     /* Call actual mDNS domain name set service.  */
2167     status =  _nx_mdns_domain_name_set(mdns_ptr, domain_name);
2168 
2169     /* Return status.  */
2170     return(status);
2171 }
2172 
2173 
2174 /**************************************************************************/
2175 /*                                                                        */
2176 /*  FUNCTION                                               RELEASE        */
2177 /*                                                                        */
2178 /*    _nx_mdns_domain_name_set                            PORTABLE C      */
2179 /*                                                           6.1          */
2180 /*  AUTHOR                                                                */
2181 /*                                                                        */
2182 /*    Yuxin Zhou, Microsoft Corporation                                   */
2183 /*                                                                        */
2184 /*  DESCRIPTION                                                           */
2185 /*                                                                        */
2186 /*    This function sets the mDNS domain name. By default is "local".     */
2187 /*                                                                        */
2188 /*  INPUT                                                                 */
2189 /*                                                                        */
2190 /*    mdns_ptr                              Pointer to mDNS instance      */
2191 /*    domain_name                           Domain name                   */
2192 /*                                                                        */
2193 /*  OUTPUT                                                                */
2194 /*                                                                        */
2195 /*    status                                Completion status             */
2196 /*                                                                        */
2197 /*  CALLS                                                                 */
2198 /*                                                                        */
2199 /*    tx_mutex_get                          Get the mDNS mutex            */
2200 /*    tx_mutex_put                          Put the mDNS mutex            */
2201 /*                                                                        */
2202 /*  CALLED BY                                                             */
2203 /*                                                                        */
2204 /*    Application Code                                                    */
2205 /*                                                                        */
2206 /*  RELEASE HISTORY                                                       */
2207 /*                                                                        */
2208 /*    DATE              NAME                      DESCRIPTION             */
2209 /*                                                                        */
2210 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2211 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2212 /*                                            verified memcpy use cases,  */
2213 /*                                            resulting in version 6.1    */
2214 /*                                                                        */
2215 /**************************************************************************/
_nx_mdns_domain_name_set(NX_MDNS * mdns_ptr,UCHAR * domain_name)2216 UINT _nx_mdns_domain_name_set(NX_MDNS *mdns_ptr, UCHAR *domain_name)
2217 {
2218 
2219 UINT        index;
2220 UINT        domain_name_size;
2221 
2222 
2223     /* Check the size.  */
2224     if (_nx_utility_string_length_check((CHAR *)domain_name, &domain_name_size, NX_MDNS_DOMAIN_NAME_MAX))
2225     {
2226         return(NX_MDNS_DATA_SIZE_ERROR);
2227     }
2228 
2229     /* Get the mDNS mutex.  */
2230     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2231 
2232     /* Save the new domain name.  */
2233     memcpy(&mdns_ptr -> nx_mdns_domain_name[0], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2234     mdns_ptr -> nx_mdns_domain_name[domain_name_size] = NX_NULL;
2235 
2236     /* Initialize the struct.  */
2237     memset(_nx_mdns_dns_sd, 0, NX_MDNS_DNS_SD_MAX);
2238 
2239     /* Update the services dns-sd.  */
2240     memcpy(_nx_mdns_dns_sd, "_services._dns-sd._udp.", (sizeof("_services._dns-sd._udp.") - 1)); /* Use case of memcpy is verified. */
2241     index = (sizeof("_services._dns-sd._udp.") - 1);
2242     memcpy(&_nx_mdns_dns_sd[index], domain_name, domain_name_size); /* Use case of memcpy is verified. */
2243 
2244     /* Release the mDNS mutex.  */
2245     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2246 
2247     /* Return a successful status.  */
2248     return(NX_SUCCESS);
2249 }
2250 
2251 
2252 #ifndef NX_MDNS_DISABLE_SERVER
2253 /**************************************************************************/
2254 /*                                                                        */
2255 /*  FUNCTION                                               RELEASE        */
2256 /*                                                                        */
2257 /*    _nxe_mdns_service_add                               PORTABLE C      */
2258 /*                                                           6.1          */
2259 /*  AUTHOR                                                                */
2260 /*                                                                        */
2261 /*    Yuxin Zhou, Microsoft Corporation                                   */
2262 /*                                                                        */
2263 /*  DESCRIPTION                                                           */
2264 /*                                                                        */
2265 /*    This function checks for errors in the mDNS service add             */
2266 /*    function call.                                                      */
2267 /*                                                                        */
2268 /*  INPUT                                                                 */
2269 /*                                                                        */
2270 /*    mdns_ptr                              Pointer to mDNS instance      */
2271 /*    name                                  Service instance name         */
2272 /*    type                                  The type of the service       */
2273 /*    subtype                               The subtype of the service    */
2274 /*    txt                                   The txt string of the service */
2275 /*    ttl                                   The ttl of the service        */
2276 /*    priority                              The priority of target host   */
2277 /*    weights                               Service weight                */
2278 /*    port                                  The port on this target host  */
2279 /*    is_unique                             The RR set of the service     */
2280 /*    interface_index                       The interface index           */
2281 /*                                                                        */
2282 /*  OUTPUT                                                                */
2283 /*                                                                        */
2284 /*    status                                Completion status             */
2285 /*                                                                        */
2286 /*  CALLS                                                                 */
2287 /*                                                                        */
2288 /*    _nx_mdns_service_add                  Actual service add function   */
2289 /*                                                                        */
2290 /*  CALLED BY                                                             */
2291 /*                                                                        */
2292 /*    Application Code                                                    */
2293 /*                                                                        */
2294 /*  RELEASE HISTORY                                                       */
2295 /*                                                                        */
2296 /*    DATE              NAME                      DESCRIPTION             */
2297 /*                                                                        */
2298 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2299 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2300 /*                                            resulting in version 6.1    */
2301 /*                                                                        */
2302 /**************************************************************************/
_nxe_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2303 UINT _nxe_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2304                            USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2305 {
2306 
2307 UINT    status;
2308 
2309 
2310     /* Check for invalid input pointers.  */
2311     if (!mdns_ptr)
2312     {
2313         return(NX_PTR_ERROR);
2314     }
2315 
2316     /* Check for invalid server attributes. */
2317     if ((mdns_ptr -> nx_mdns_id != NX_MDNS_ID) || (!port))
2318     {
2319         return(NX_MDNS_PARAM_ERROR);
2320     }
2321 
2322     /* Check the size of the service name string. The last four characters in the
2323        service name are reserved so DNS-SD is able to append " (2)" during the conflict
2324        resolution process. */
2325 #if (NX_MDNS_SERVICE_NAME_MAX >= NX_MDNS_LABEL_MAX)
2326     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_LABEL_MAX - 4)))
2327 #else
2328     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, (NX_MDNS_SERVICE_NAME_MAX - 4)))
2329 #endif
2330     {
2331         return(NX_MDNS_DATA_SIZE_ERROR);
2332     }
2333 
2334     /* Check the type.  */
2335     if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2336     {
2337         return(NX_MDNS_DATA_SIZE_ERROR);
2338     }
2339 
2340     /* Check the txt string size.  */
2341     if (txt)
2342     {
2343         if (_nx_utility_string_length_check((CHAR *)txt, NX_NULL, NX_MDNS_NAME_MAX))
2344         {
2345             return(NX_MDNS_DATA_SIZE_ERROR);
2346         }
2347     }
2348 
2349     /* Check the txt string size.  */
2350     if (sub_type)
2351     {
2352         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
2353         {
2354             return(NX_MDNS_DATA_SIZE_ERROR);
2355         }
2356     }
2357 
2358     /* Check the interface index.  */
2359     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
2360     {
2361         return(NX_INVALID_INTERFACE);
2362     }
2363 
2364     /* Call actual mDNS service add service.  */
2365     status =  _nx_mdns_service_add(mdns_ptr, name, type, sub_type, txt, ttl, priority,
2366                                    weights, port, is_unique, interface_index);
2367 
2368     /* Return status.  */
2369     return(status);
2370 }
2371 
2372 
2373 /**************************************************************************/
2374 /*                                                                        */
2375 /*  FUNCTION                                               RELEASE        */
2376 /*                                                                        */
2377 /*    _nx_mdns_service_add                                PORTABLE C      */
2378 /*                                                           6.1          */
2379 /*  AUTHOR                                                                */
2380 /*                                                                        */
2381 /*    Yuxin Zhou, Microsoft Corporation                                   */
2382 /*                                                                        */
2383 /*  DESCRIPTION                                                           */
2384 /*                                                                        */
2385 /*    This function adds the mDNS services, and the PTR, SRV and TXT      */
2386 /*    records into the local buffer.                                      */
2387 /*                                                                        */
2388 /*  INPUT                                                                 */
2389 /*                                                                        */
2390 /*    mdns_ptr                              Pointer to mDNS instance      */
2391 /*    name                                  Service nstance name          */
2392 /*    type                                  The type of the service       */
2393 /*    subtype                               The subtype of the service    */
2394 /*    txt                                   The txt string of the service */
2395 /*    ttl                                   The ttl of the service        */
2396 /*    priority                              The priority of target host   */
2397 /*    weights                               Service weight                */
2398 /*    port                                  The port on this target host  */
2399 /*    is_unique                             The RR set of the service     */
2400 /*    interface_index                       The interface index           */
2401 /*                                                                        */
2402 /*  OUTPUT                                                                */
2403 /*                                                                        */
2404 /*    status                                Completion status             */
2405 /*                                                                        */
2406 /*  CALLS                                                                 */
2407 /*                                                                        */
2408 /*    tx_mutex_get                          Get the mDNS mutex            */
2409 /*    tx_mutex_put                          Put the mDNS mutex            */
2410 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
2411 /*    _nx_mdns_rr_srv_add                   Add the SRV resource record   */
2412 /*    _nx_mdns_rr_txt_add                   Add the TXT resource record   */
2413 /*    _nx_mdns_rr_ptr_add                   Add the PTR resource record   */
2414 /*    _nx_mdns_rr_delete                    Delete the resource record    */
2415 /*                                                                        */
2416 /*  CALLED BY                                                             */
2417 /*                                                                        */
2418 /*    Application Code                                                    */
2419 /*                                                                        */
2420 /*  RELEASE HISTORY                                                       */
2421 /*                                                                        */
2422 /*    DATE              NAME                      DESCRIPTION             */
2423 /*                                                                        */
2424 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2425 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2426 /*                                            resulting in version 6.1    */
2427 /*                                                                        */
2428 /**************************************************************************/
_nx_mdns_service_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * txt,ULONG ttl,USHORT priority,USHORT weights,USHORT port,UCHAR is_unique,UINT interface_index)2429 UINT _nx_mdns_service_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *txt, ULONG ttl,
2430                           USHORT priority, USHORT weights, USHORT port, UCHAR is_unique, UINT interface_index)
2431 {
2432 
2433 UINT        status;
2434 UINT        type_index;
2435 NX_MDNS_RR *srv_rr;
2436 NX_MDNS_RR *txt_rr;
2437 NX_MDNS_RR *ptr_rr;
2438 NX_MDNS_RR *dns_sd_rr;
2439 ULONG       *head;
2440 NX_MDNS_RR  *p;
2441 ULONG        srv_ttl;
2442 ULONG        txt_ttl;
2443 ULONG        ptr_ttl;
2444 UINT         string_length;
2445 
2446 
2447     /* Get the mDNS mutex.  */
2448     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2449 
2450     /* Check the ttl value.  */
2451     if (ttl)
2452     {
2453 
2454         /* Use user supplied TTL value if it is not zero. */
2455         srv_ttl = ttl;
2456         txt_ttl = ttl;
2457         ptr_ttl = ttl;
2458     }
2459     else
2460     {
2461 
2462         /* Use the RFC recommended TTL values if user doesn't supply one.  */
2463         srv_ttl = NX_MDNS_RR_TTL_HOST;
2464         txt_ttl = NX_MDNS_RR_TTL_OTHER;
2465         ptr_ttl = NX_MDNS_RR_TTL_OTHER;
2466     }
2467 
2468     /* Construct the SRV name.  */
2469     status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2470 
2471     /* Check the status.  */
2472     if (status)
2473     {
2474 
2475         /* Release the mDNS mutex.  */
2476         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2477         return (status);
2478     }
2479 
2480     /* Check string length.  */
2481     if (_nx_utility_string_length_check((CHAR *)(&temp_string_buffer[0]), &string_length, NX_MDNS_NAME_MAX))
2482     {
2483 
2484         /* Release the mDNS mutex.  */
2485         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2486         return (NX_MDNS_DATA_SIZE_ERROR);
2487     }
2488 
2489     /* Check whether the same service name exist.  */
2490     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2491     head = (ULONG*)(*head);
2492 
2493     /* Check the resource record.  */
2494     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2495     {
2496         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2497             continue;
2498 
2499         /* Check the interface.  */
2500         if (p -> nx_mdns_rr_interface_index != interface_index)
2501             continue;
2502 
2503         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
2504         {
2505 
2506             /* Compare the service name.  */
2507             if (!_nx_mdns_name_match(&temp_string_buffer[0], p -> nx_mdns_rr_name, string_length))
2508             {
2509 
2510                 /* Release the mDNS mutex.  */
2511                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2512 
2513                 return(NX_MDNS_EXIST_SAME_SERVICE);
2514             }
2515         }
2516     }
2517 
2518     /* Construct the SRV target name.  */
2519     status = _nx_mdns_service_name_assemble(mdns_ptr -> nx_mdns_host_name, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
2520 
2521     /* Check the status.  */
2522     if (status)
2523     {
2524 
2525         /* Release the mDNS mutex.  */
2526         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2527         return (status);
2528     }
2529 
2530     /* Add the SRV resource records message.  */
2531     status = _nx_mdns_rr_srv_add(mdns_ptr, &temp_string_buffer[0], srv_ttl, is_unique, priority, weights, port, &target_string_buffer[0], &srv_rr, interface_index);
2532 
2533     /* Check the status.  */
2534     if (status)
2535     {
2536 
2537         /* Release the mDNS mutex.  */
2538         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2539         return(status);
2540     }
2541 
2542     /* Add the TXT resource records message.  */
2543     status = _nx_mdns_rr_txt_add(mdns_ptr, &temp_string_buffer[0], txt_ttl, is_unique, txt, &txt_rr, interface_index);
2544 
2545     /* Check the status.  */
2546     if (status)
2547     {
2548 
2549         /* Delete the SRV records.  */
2550         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2551 
2552         /* Release the mDNS mutex.  */
2553         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2554 
2555         return(status);
2556     }
2557 
2558     /* Add the dns-sd PTR resource records message.  */
2559     status = _nx_mdns_rr_ptr_add(mdns_ptr, (UCHAR *)_nx_mdns_dns_sd, ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[type_index], NX_TRUE, &dns_sd_rr, interface_index);
2560 
2561     /* Check the status.  */
2562     if (status)
2563     {
2564 
2565         /* Delete the TXT records.  */
2566         _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2567 
2568         /* Delete the SRV records.  */
2569         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2570 
2571         /* Release the mDNS mutex.  */
2572         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2573 
2574         return(status);
2575     }
2576 
2577     /* Add the PTR resource records message.  */
2578     status = _nx_mdns_rr_ptr_add(mdns_ptr, &temp_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, &ptr_rr, interface_index);
2579 
2580     /* Check the status.  */
2581     if (status)
2582     {
2583 
2584         /* Delete the TXT records.  */
2585         _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2586 
2587         /* Delete the SRV records.  */
2588         _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2589 
2590         /* Delete the DNS_SD PTR records.  */
2591         _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2592 
2593         /* Release the mDNS mutex.  */
2594         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2595 
2596         return(status);
2597     }
2598 
2599     /* Add another PTR type for the subtype. */
2600     if (sub_type)
2601     {
2602 
2603         /* Construct the PTR target name.  */
2604         status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &target_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2605 
2606         /* Check the status.  */
2607         if (status)
2608         {
2609 
2610             /* Release the mDNS mutex.  */
2611             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2612 
2613             return (status);
2614         }
2615 
2616         /* Add the Sub PTR resource records message.  */
2617         status = _nx_mdns_rr_ptr_add(mdns_ptr, &target_string_buffer[type_index], ptr_ttl, NX_MDNS_RR_SET_SHARED, &temp_string_buffer[0], NX_TRUE, NX_NULL, interface_index);
2618 
2619         /* Check the status.  */
2620         if (status)
2621         {
2622 
2623             /* Delete the PTR records.  */
2624             _nx_mdns_rr_delete(mdns_ptr, ptr_rr);
2625 
2626             /* Delete the DNS_SD PTR records.  */
2627             _nx_mdns_rr_delete(mdns_ptr, dns_sd_rr);
2628 
2629             /* Delete the SRV records.  */
2630             _nx_mdns_rr_delete(mdns_ptr, srv_rr);
2631 
2632             /* Delete the TXT records.  */
2633             _nx_mdns_rr_delete(mdns_ptr, txt_rr);
2634 
2635             /* Release the mDNS mutex.  */
2636             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2637 
2638             return(status);
2639         }
2640     }
2641 
2642 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2643 
2644     /* Add the NSEC resource record for service.  */
2645     _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], NX_FALSE, NX_FALSE, NX_MDNS_ADD_NSEC_FOR_SERVICE, interface_index);
2646 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
2647 
2648     /* Release the mDNS mutex.  */
2649     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2650 
2651     /* Return a successful status.  */
2652     return(NX_SUCCESS);
2653 }
2654 
2655 
2656 /**************************************************************************/
2657 /*                                                                        */
2658 /*  FUNCTION                                               RELEASE        */
2659 /*                                                                        */
2660 /*    _nxe_mdns_service_delete                            PORTABLE C      */
2661 /*                                                           6.1          */
2662 /*  AUTHOR                                                                */
2663 /*                                                                        */
2664 /*    Yuxin Zhou, Microsoft Corporation                                   */
2665 /*                                                                        */
2666 /*  DESCRIPTION                                                           */
2667 /*                                                                        */
2668 /*    This function checks for errors in the mDNS service delete          */
2669 /*    function call.                                                      */
2670 /*                                                                        */
2671 /*  INPUT                                                                 */
2672 /*                                                                        */
2673 /*    mdns_ptr                              Pointer to mDNS instance      */
2674 /*    name                                  The name of the service       */
2675 /*    type                                  The type of the service       */
2676 /*    subtype                               The subtype of the service    */
2677 /*                                                                        */
2678 /*  OUTPUT                                                                */
2679 /*                                                                        */
2680 /*    status                                Completion status             */
2681 /*                                                                        */
2682 /*  CALLS                                                                 */
2683 /*                                                                        */
2684 /*    _nx_mdns_service_delete               Actual service delete function*/
2685 /*                                                                        */
2686 /*  CALLED BY                                                             */
2687 /*                                                                        */
2688 /*    Application Code                                                    */
2689 /*                                                                        */
2690 /*  RELEASE HISTORY                                                       */
2691 /*                                                                        */
2692 /*    DATE              NAME                      DESCRIPTION             */
2693 /*                                                                        */
2694 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2695 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2696 /*                                            resulting in version 6.1    */
2697 /*                                                                        */
2698 /**************************************************************************/
_nxe_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2699 UINT _nxe_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2700 {
2701 
2702 UINT    status;
2703 
2704     /* Check for invalid input pointers.  */
2705     if ((!mdns_ptr) || (!name) || (!type))
2706     {
2707         return(NX_PTR_ERROR);
2708     }
2709 
2710     /* Check for invalid server attributes. */
2711     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
2712     {
2713         return(NX_MDNS_PARAM_ERROR);
2714     }
2715 
2716     /* Check the size.  */
2717     if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX) ||
2718         _nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
2719     {
2720         return(NX_MDNS_DATA_SIZE_ERROR);
2721     }
2722 
2723     /* Call actual mDNS service delete service.  */
2724     status =  _nx_mdns_service_delete(mdns_ptr, name, type, sub_type);
2725 
2726     /* Return status.  */
2727     return(status);
2728 }
2729 
2730 /**************************************************************************/
2731 /*                                                                        */
2732 /*  FUNCTION                                               RELEASE        */
2733 /*                                                                        */
2734 /*    _nx_mdns_service_delete                             PORTABLE C      */
2735 /*                                                           6.1          */
2736 /*  AUTHOR                                                                */
2737 /*                                                                        */
2738 /*    Yuxin Zhou, Microsoft Corporation                                   */
2739 /*                                                                        */
2740 /*  DESCRIPTION                                                           */
2741 /*                                                                        */
2742 /*    This function deletes the mDNS services.                            */
2743 /*                                                                        */
2744 /*  INPUT                                                                 */
2745 /*                                                                        */
2746 /*    mdns_ptr                              Pointer to mDNS instance      */
2747 /*    name                                  The name of the service       */
2748 /*    type                                  The type of the service       */
2749 /*    subtype                               The subtype of the service    */
2750 /*                                                                        */
2751 /*  OUTPUT                                                                */
2752 /*                                                                        */
2753 /*    status                                Completion status             */
2754 /*                                                                        */
2755 /*  CALLS                                                                 */
2756 /*                                                                        */
2757 /*    _nx_mdns_service_delete_internal      Actual service delete function*/
2758 /*                                                                        */
2759 /*  CALLED BY                                                             */
2760 /*                                                                        */
2761 /*    Application Code                                                    */
2762 /*                                                                        */
2763 /*  RELEASE HISTORY                                                       */
2764 /*                                                                        */
2765 /*    DATE              NAME                      DESCRIPTION             */
2766 /*                                                                        */
2767 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2768 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2769 /*                                            resulting in version 6.1    */
2770 /*                                                                        */
2771 /**************************************************************************/
_nx_mdns_service_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)2772 UINT _nx_mdns_service_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
2773 {
2774 
2775 UINT    i;
2776 UINT    status = NX_MDNS_NOT_ENABLED;
2777 UINT    service_delete_success = NX_FALSE;
2778 
2779     /* Delete service from all enabled interfaces.  */
2780     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i ++)
2781     {
2782 
2783         /* Call actual mDNS service delete service.  */
2784         status =  _nx_mdns_service_interface_delete(mdns_ptr, name, type, sub_type, i);
2785 
2786         /* Check status.  */
2787         if (status == NX_MDNS_SUCCESS)
2788         {
2789             service_delete_success = NX_TRUE;
2790         }
2791     }
2792 
2793     /* Check if delete service on all enabled interface.  */
2794     if (service_delete_success)
2795         return(NX_MDNS_SUCCESS);
2796     else
2797         return(status);
2798 }
2799 
2800 
2801 /**************************************************************************/
2802 /*                                                                        */
2803 /*  FUNCTION                                               RELEASE        */
2804 /*                                                                        */
2805 /*    _nx_mdns_service_interface_delete                   PORTABLE C      */
2806 /*                                                           6.1          */
2807 /*  AUTHOR                                                                */
2808 /*                                                                        */
2809 /*    Yuxin Zhou, Microsoft Corporation                                   */
2810 /*                                                                        */
2811 /*  DESCRIPTION                                                           */
2812 /*                                                                        */
2813 /*    This function deletes the mDNS services, and remove SRV and TXT     */
2814 /*    records from local buffer.                                          */
2815 /*                                                                        */
2816 /*  INPUT                                                                 */
2817 /*                                                                        */
2818 /*    mdns_ptr                              Pointer to mDNS instance      */
2819 /*    name                                  The name of the service       */
2820 /*    type                                  The type of the service       */
2821 /*    subtype                               The subtype of the service    */
2822 /*    interface_index                       The interface index           */
2823 /*                                                                        */
2824 /*  OUTPUT                                                                */
2825 /*                                                                        */
2826 /*    status                                Completion status             */
2827 /*                                                                        */
2828 /*  CALLS                                                                 */
2829 /*                                                                        */
2830 /*    tx_mutex_get                          Get the mDNS mutex            */
2831 /*    tx_mutex_put                          Put the mDNS mutex            */
2832 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
2833 /*    _nx_mdns_name_match                   Match the name string         */
2834 /*    _nx_mdns_rr_delete                    Delete the resource record    */
2835 /*                                                                        */
2836 /*  CALLED BY                                                             */
2837 /*                                                                        */
2838 /*    Application Code                                                    */
2839 /*                                                                        */
2840 /*  RELEASE HISTORY                                                       */
2841 /*                                                                        */
2842 /*    DATE              NAME                      DESCRIPTION             */
2843 /*                                                                        */
2844 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2845 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2846 /*                                            resulting in version 6.1    */
2847 /*                                                                        */
2848 /**************************************************************************/
_nx_mdns_service_interface_delete(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT interface_index)2849 UINT _nx_mdns_service_interface_delete(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT interface_index)
2850 {
2851 
2852 UINT        status;
2853 UINT        found;
2854 UINT        delete_flag;
2855 UINT        type_index;
2856 ULONG      *head;
2857 NX_MDNS_RR *p;
2858 UINT        rr_name_length;
2859 UINT        rr_ptr_name_length;
2860 
2861     NX_PARAMETER_NOT_USED(sub_type);
2862 
2863     /* Get the mDNS mutex.  */
2864     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
2865 
2866     /* Initialize the parameters.  */
2867     type_index = 0;
2868     delete_flag = NX_FALSE;
2869 
2870     /* Construct the SRV name.  */
2871     status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
2872 
2873     /* Check the status.  */
2874     if (status)
2875     {
2876 
2877         /* Release the mDNS mutex.  */
2878         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2879         return (status);
2880     }
2881 
2882     /* Get head. */
2883     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
2884     head = (ULONG*)(*head);
2885 
2886     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
2887     {
2888 
2889         /* Clear the found value.  */
2890         found = NX_FALSE;
2891 
2892         /* Check the interface index.  */
2893         if (p -> nx_mdns_rr_interface_index != interface_index)
2894             continue;
2895 
2896         /* Check whether the resource record is valid. */
2897         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
2898             continue;
2899 
2900         /* Check string length.  */
2901         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
2902         {
2903             continue;
2904         }
2905 
2906         /* Compare the RDATA. */
2907         switch (p -> nx_mdns_rr_type)
2908         {
2909 
2910             case NX_MDNS_RR_TYPE_SRV:
2911             case NX_MDNS_RR_TYPE_TXT:
2912             {
2913                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2914                 {
2915                     found = NX_TRUE;
2916                     delete_flag = NX_TRUE;
2917                 }
2918                 break;
2919             }
2920             case NX_MDNS_RR_TYPE_PTR:
2921             {
2922 
2923                 /* Check string length.  */
2924                 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), &rr_ptr_name_length, NX_MDNS_NAME_MAX))
2925                 {
2926                     break;
2927                 }
2928 
2929                 /* Find the PTR and Sub PTR resource record which pointer to the SRV resource record.*/
2930                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[0], rr_ptr_name_length))
2931                 {
2932                     found = NX_TRUE;
2933                 }
2934 
2935                 /* Find one DNS-SD PRT which pointer to the PTR resource record.  */
2936                 if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)) &&
2937                     (!_nx_mdns_name_match(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &temp_string_buffer[type_index], rr_ptr_name_length)))
2938                 {
2939 
2940                     /* Check the count.  */
2941                     if (p -> nx_mdns_rr_count)
2942                     {
2943                         p -> nx_mdns_rr_count --;
2944                     }
2945                     else
2946                     {
2947 
2948                         /* Delete this resource record directly.  */
2949                         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2950                     }
2951                 }
2952                 break;
2953             }
2954 
2955 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
2956             case NX_MDNS_RR_TYPE_NSEC:
2957             {
2958                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length))
2959                 {
2960 
2961                     /* Delete this resource record directly.  */
2962                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
2963                 }
2964                 break;
2965             }
2966 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
2967         }
2968 
2969         if (found)
2970         {
2971 
2972             /* Delete the resource records.  */
2973             status = _nx_mdns_rr_delete(mdns_ptr, p);
2974 
2975             /* Check the status.  */
2976             if (status)
2977             {
2978                 /* Release the mDNS mutex.  */
2979                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2980 
2981                 return(status);
2982             }
2983         }
2984     }
2985 
2986     /* Release the mDNS mutex.  */
2987     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
2988 
2989     if (delete_flag == NX_TRUE)
2990         return(NX_MDNS_SUCCESS);
2991     else
2992         return(NX_MDNS_ERROR);
2993 }
2994 #endif /* NX_MDNS_DISABLE_SERVER */
2995 
2996 
2997 #ifndef NX_MDNS_DISABLE_CLIENT
2998 /**************************************************************************/
2999 /*                                                                        */
3000 /*  FUNCTION                                               RELEASE        */
3001 /*                                                                        */
3002 /*    _nxe_mdns_service_one_shot_query                      PORTABLE C    */
3003 /*                                                           6.1          */
3004 /*  AUTHOR                                                                */
3005 /*                                                                        */
3006 /*    Yuxin Zhou, Microsoft Corporation                                   */
3007 /*                                                                        */
3008 /*  DESCRIPTION                                                           */
3009 /*                                                                        */
3010 /*    This function checks for errors in the mDNS resource record query   */
3011 /*    add function call.                                                  */
3012 /*                                                                        */
3013 /*  INPUT                                                                 */
3014 /*                                                                        */
3015 /*    mdns_ptr                              Pointer to mDNS instance      */
3016 /*    name                                  The name of the service       */
3017 /*    type                                  The type of the service       */
3018 /*    subtype                               The subtype of the service    */
3019 /*    service                               Pointer to response service   */
3020 /*    timeout                               The timeour for service query */
3021 /*                                                                        */
3022 /*  OUTPUT                                                                */
3023 /*                                                                        */
3024 /*    status                                Completion status             */
3025 /*                                                                        */
3026 /*  CALLS                                                                 */
3027 /*                                                                        */
3028 /*    _nx_mdns_service_one_shot_query       Actual query service function */
3029 /*                                                                        */
3030 /*  CALLED BY                                                             */
3031 /*                                                                        */
3032 /*    Application Code                                                    */
3033 /*                                                                        */
3034 /*  RELEASE HISTORY                                                       */
3035 /*                                                                        */
3036 /*    DATE              NAME                      DESCRIPTION             */
3037 /*                                                                        */
3038 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3039 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3040 /*                                            resulting in version 6.1    */
3041 /*                                                                        */
3042 /**************************************************************************/
_nxe_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3043 UINT _nxe_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3044 {
3045 
3046 UINT    status;
3047 
3048 
3049     /* Check for invalid input pointers.  */
3050     if ((!mdns_ptr) || (!type) || (!service))
3051     {
3052         return(NX_PTR_ERROR);
3053     }
3054 
3055     /* Check for mDNS started flag.  */
3056     if (!mdns_ptr -> nx_mdns_started)
3057     {
3058         return(NX_MDNS_NOT_STARTED);
3059     }
3060 
3061     /* Check for name.  */
3062     if (name)
3063     {
3064 
3065         /* Check the name size.  */
3066         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3067         {
3068             return(NX_MDNS_DATA_SIZE_ERROR);
3069         }
3070     }
3071 
3072     /* Check the type size.  */
3073     if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3074     {
3075         return(NX_MDNS_DATA_SIZE_ERROR);
3076     }
3077 
3078     /* Check the sub type.  */
3079     if (sub_type)
3080     {
3081 
3082         /* Check the name size.  */
3083         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3084         {
3085             return(NX_MDNS_DATA_SIZE_ERROR);
3086         }
3087     }
3088 
3089     /* Call actual mDNS create service.  */
3090     status = _nx_mdns_service_one_shot_query(mdns_ptr, name, type, sub_type, service, timeout);
3091 
3092     /* Return status.  */
3093     return(status);
3094 }
3095 
3096 
3097 /**************************************************************************/
3098 /*                                                                        */
3099 /*  FUNCTION                                               RELEASE        */
3100 /*                                                                        */
3101 /*    _nx_mdns_service_one_shot_query                     PORTABLE C      */
3102 /*                                                           6.1.11       */
3103 /*  AUTHOR                                                                */
3104 /*                                                                        */
3105 /*    Yuxin Zhou, Microsoft Corporation                                   */
3106 /*                                                                        */
3107 /*  DESCRIPTION                                                           */
3108 /*                                                                        */
3109 /*    This function starts service one-shot query on all enabled          */
3110 /*    interfaces.                                                         */
3111 /*                                                                        */
3112 /*  INPUT                                                                 */
3113 /*                                                                        */
3114 /*    mdns_ptr                              Pointer to mDNS instance      */
3115 /*    name                                  The name of the service       */
3116 /*    type                                  The type of the service       */
3117 /*    subtype                               The subtype of the service    */
3118 /*    service                               Pointer to response service   */
3119 /*    timeout                               The timeour for service query */
3120 /*                                                                        */
3121 /*  OUTPUT                                                                */
3122 /*                                                                        */
3123 /*    status                                Completion status             */
3124 /*                                                                        */
3125 /*  CALLS                                                                 */
3126 /*                                                                        */
3127 /*    tx_mutex_get                          Get the mDNS mutex            */
3128 /*    tx_mutex_put                          Put the mDNS mutex            */
3129 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3130 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
3131 /*    _nx_mdns_query                        Send the One Shot query       */
3132 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
3133 /*                                                                        */
3134 /*  CALLED BY                                                             */
3135 /*                                                                        */
3136 /*    Application Code                                                    */
3137 /*                                                                        */
3138 /*  RELEASE HISTORY                                                       */
3139 /*                                                                        */
3140 /*    DATE              NAME                      DESCRIPTION             */
3141 /*                                                                        */
3142 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3143 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3144 /*                                            verified memcpy use cases,  */
3145 /*                                            resulting in version 6.1    */
3146 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3147 /*                                            fixed compiler warnings,    */
3148 /*                                            resulting in version 6.1.11 */
3149 /*                                                                        */
3150 /**************************************************************************/
_nx_mdns_service_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,NX_MDNS_SERVICE * service,UINT timeout)3151 UINT _nx_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout)
3152 {
3153 
3154 UINT        type_index;
3155 UINT        status;
3156 NX_MDNS_RR *answer_rr;
3157 UCHAR      *query_name;
3158 USHORT      query_type;
3159 UINT        i;
3160 UINT        name_length;
3161 
3162 
3163     /* Get the mDNS mutex.  */
3164     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3165 
3166     /* Initialize the struct.  */
3167     memset(service, 0, sizeof(NX_MDNS_SERVICE));
3168 
3169     /* Loop to start one-shot query on all enabled interfaces until get the answer or query timeout.  */
3170     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3171     {
3172 
3173         /* Check if this interface is enabled.  */
3174         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3175             continue;
3176 
3177         /* Step1. Construct the query name and set the query type.  */
3178         if (name)
3179         {
3180 
3181             /* Construct the SRV name.  */
3182             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3183 
3184             /* Check the status.  */
3185             if (status)
3186             {
3187 
3188                 /* Release the mDNS mutex.  */
3189                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3190                 return(status);
3191             }
3192 
3193             /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT).  */
3194             query_name = temp_string_buffer;
3195             query_type = NX_MDNS_RR_TYPE_ALL;
3196         }
3197         else
3198         {
3199 
3200             /* Construct the PTR name.  */
3201             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3202 
3203             /* Check the status.  */
3204             if (status)
3205             {
3206 
3207                 /* Release the mDNS mutex.  */
3208                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3209                 return (status);
3210             }
3211 
3212             /* Set the query name and query type.  */
3213             query_name = &temp_string_buffer[type_index];
3214             query_type = NX_MDNS_RR_TYPE_PTR;
3215         }
3216 
3217         /* Step2. Start one shot query.  */
3218         status = _nx_mdns_one_shot_query(mdns_ptr, query_name, query_type, &answer_rr, timeout, i);
3219 
3220         /* Check the status.  */
3221         if ((status == NX_SUCCESS) ||
3222             (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3223             (status == NX_MDNS_EXIST_SHARED_RR))
3224         {
3225 
3226             /* Check the query type.  */
3227             if (name)
3228             {
3229 
3230                 /* Store the service name from SRV record.  */
3231                 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_name, &name_length, NX_MDNS_NAME_MAX))
3232                 {
3233 
3234                     /* Release the mDNS mutex.  */
3235                     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3236                     return (NX_MDNS_DATA_SIZE_ERROR);
3237                 }
3238                 memcpy((char *)(service -> buffer), (char*)(answer_rr -> nx_mdns_rr_name), name_length); /* Use case of memcpy is verified. */
3239             }
3240             else
3241             {
3242 
3243                 /* Store the service name from PTR record.  */
3244                 if (_nx_utility_string_length_check((CHAR *)answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &name_length, NX_MDNS_NAME_MAX))
3245                 {
3246 
3247                     /* Release the mDNS mutex.  */
3248                     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3249                     return (NX_MDNS_DATA_SIZE_ERROR);
3250                 }
3251                 memcpy((CHAR *)(service -> buffer), (CHAR *)(answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), name_length); /* Use case of memcpy is verified. */
3252             }
3253 
3254             /* Get the additional information of service.  */
3255             _nx_mdns_service_addition_info_get(mdns_ptr, service -> buffer, service, i);
3256 
3257             /* Reslove the service name.  */
3258             status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
3259 
3260             /* Check status.  */
3261             if (status)
3262                 continue;
3263 
3264             /* Release the mDNS mutex.  */
3265             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3266 
3267             /* Return success.  */
3268             return (NX_MDNS_SUCCESS);
3269         }
3270     }
3271 
3272     /* Release the mDNS mutex.  */
3273     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3274 
3275     /* Return error.  */
3276     return (NX_MDNS_ERROR);
3277 }
3278 
3279 
3280 /**************************************************************************/
3281 /*                                                                        */
3282 /*  FUNCTION                                               RELEASE        */
3283 /*                                                                        */
3284 /*    _nx_mdns_one_shot_query                             PORTABLE C      */
3285 /*                                                           6.1.11       */
3286 /*  AUTHOR                                                                */
3287 /*                                                                        */
3288 /*    Yuxin Zhou, Microsoft Corporation                                   */
3289 /*                                                                        */
3290 /*  DESCRIPTION                                                           */
3291 /*                                                                        */
3292 /*    This function adds the mDNS resource record into remote buffer,     */
3293 /*    mDNS thread send the query message.                                 */
3294 /*                                                                        */
3295 /*  INPUT                                                                 */
3296 /*                                                                        */
3297 /*    mdns_ptr                              Pointer to mDNS instance      */
3298 /*    name                                  The resource record name      */
3299 /*    type                                  The resource record type      */
3300 /*    out_rr                                Pointer to response RR        */
3301 /*    one_shot                              One shot or continuous        */
3302 /*    wait_option                           Wait option                   */
3303 /*                                                                        */
3304 /*  OUTPUT                                                                */
3305 /*                                                                        */
3306 /*    status                                Completion status             */
3307 /*                                                                        */
3308 /*  CALLS                                                                 */
3309 /*                                                                        */
3310 /*    tx_mutex_get                          Get the mDNS mutex            */
3311 /*    tx_mutex_put                          Put the mDNS mutex            */
3312 /*    _tx_thread_system_suspend             Suspend the thread            */
3313 /*    _nx_mdns_query_check                  Check the query RR            */
3314 /*    _nx_mdns_cache_add_string             Add the string into cache     */
3315 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
3316 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
3317 /*                                            into cache                  */
3318 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
3319 /*                                            from cache                  */
3320 /*                                                                        */
3321 /*  CALLED BY                                                             */
3322 /*                                                                        */
3323 /*    Application Code                                                    */
3324 /*                                                                        */
3325 /*  RELEASE HISTORY                                                       */
3326 /*                                                                        */
3327 /*    DATE              NAME                      DESCRIPTION             */
3328 /*                                                                        */
3329 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3330 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3331 /*                                            resulting in version 6.1    */
3332 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3333 /*                                            corrected the random value, */
3334 /*                                            fixed the issue of timer,   */
3335 /*                                            resulting in version 6.1.11 */
3336 /*                                                                        */
3337 /**************************************************************************/
_nx_mdns_one_shot_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,NX_MDNS_RR ** out_rr,ULONG wait_option,UINT interface_index)3338 static UINT _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index)
3339 {
3340 
3341 UINT        status;
3342 NX_MDNS_RR  *rr;
3343 NX_MDNS_RR  *insert_rr;
3344 NX_MDNS_RR  temp_resource_record;
3345 UINT        name_length;
3346 
3347 
3348     /* Clear the return record.  */
3349     *out_rr =   NX_NULL;
3350 
3351     /* Check the query RR.  */
3352     status = _nx_mdns_query_check(mdns_ptr, name, type, NX_TRUE, &rr, interface_index);
3353 
3354     /* Check the state.  */
3355     if (status)
3356     {
3357 
3358         /* Whether exists unique resource record in cache.  */
3359         if ((status == NX_MDNS_EXIST_UNIQUE_RR) ||
3360             (status == NX_MDNS_EXIST_SHARED_RR))
3361         {
3362             *out_rr = rr;
3363             return (NX_MDNS_SUCCESS);
3364         }
3365         else
3366         {
3367             return(status);
3368         }
3369     }
3370 
3371     if (wait_option != 0)
3372     {
3373 
3374         /* Initialize the struct.  */
3375         memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3376 
3377         if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3378         {
3379             return (NX_MDNS_DATA_SIZE_ERROR);
3380         }
3381 
3382         /* Add the name.  */
3383         status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3384                                            (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3385 
3386         /* Check for error.  */
3387         if (status)
3388         {
3389             return(status);
3390         }
3391 
3392         /* Add the parameters.  */
3393         temp_resource_record.nx_mdns_rr_type = type;
3394         temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3395 
3396         /* Set the resource record status.  */
3397         temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3398 
3399         /* Remote resource record, set the owner flag.  */
3400         temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3401 
3402         /* Set the interface index.  */
3403         temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3404 
3405         /* Add the resource record.  */
3406         status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3407 
3408         /* Check for error.  */
3409         if (status)
3410         {
3411 
3412             /* Delete the same strings. */
3413             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3414             return(status);
3415         }
3416 
3417         /* A multicast DNS querier should also delay the first query of the series by
3418            a randomly chosen amount in the range 20-120ms.  */
3419         insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3420         insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3421 
3422         /* Set the mDNS timer.  */
3423         _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3424 
3425         /* Release the mDNS mutex to process response.  */
3426         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3427 
3428         /* Suspend the thread on this mDNS query attempt.  */
3429         _nx_mdns_query_thread_suspend(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), _nx_mdns_query_cleanup, mdns_ptr, out_rr, wait_option);
3430 
3431         /* Get the mDNS mutex.  */
3432         tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
3433 
3434         /* Determine if a packet was received successfully.  */
3435         if (_tx_thread_current_ptr -> tx_thread_suspend_status != NX_MDNS_SUCCESS)
3436         {
3437 
3438             /* Delete the query resource record.  */
3439             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, insert_rr);
3440         }
3441 
3442         /* Return the status.  */
3443         return(_tx_thread_current_ptr -> tx_thread_suspend_status);
3444     }
3445     else
3446     {
3447 
3448         /* Immediate return, return error completion.  */
3449         return(NX_MDNS_NO_RR);
3450     }
3451 }
3452 
3453 
3454 /**************************************************************************/
3455 /*                                                                        */
3456 /*  FUNCTION                                               RELEASE        */
3457 /*                                                                        */
3458 /*    _nxe_mdns_service_continuous_query                    PORTABLE C    */
3459 /*                                                           6.1          */
3460 /*  AUTHOR                                                                */
3461 /*                                                                        */
3462 /*    Yuxin Zhou, Microsoft Corporation                                   */
3463 /*                                                                        */
3464 /*  DESCRIPTION                                                           */
3465 /*                                                                        */
3466 /*    This function checks for errors in the mDNS resource record query   */
3467 /*    add function call.                                                  */
3468 /*                                                                        */
3469 /*  INPUT                                                                 */
3470 /*                                                                        */
3471 /*    mdns_ptr                              Pointer to mDNS instance      */
3472 /*    name                                  The name of the service       */
3473 /*    type                                  The type of the service       */
3474 /*    subtype                               The subtype of the service    */
3475 /*                                                                        */
3476 /*  OUTPUT                                                                */
3477 /*                                                                        */
3478 /*    status                                Completion status             */
3479 /*                                                                        */
3480 /*  CALLS                                                                 */
3481 /*                                                                        */
3482 /*    _nx_mdns_service_continuous_query     Actual mDNS query RR function */
3483 /*                                                                        */
3484 /*  CALLED BY                                                             */
3485 /*                                                                        */
3486 /*    Application Code                                                    */
3487 /*                                                                        */
3488 /*  RELEASE HISTORY                                                       */
3489 /*                                                                        */
3490 /*    DATE              NAME                      DESCRIPTION             */
3491 /*                                                                        */
3492 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3493 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3494 /*                                            resulting in version 6.1    */
3495 /*                                                                        */
3496 /**************************************************************************/
_nxe_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3497 UINT _nxe_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3498 {
3499 
3500 UINT    status;
3501 
3502 
3503     /* Check for invalid input pointers.  */
3504     if (!mdns_ptr)
3505     {
3506         return(NX_PTR_ERROR);
3507     }
3508 
3509     /* Check for invalid server attributes. */
3510     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3511     {
3512         return(NX_MDNS_PARAM_ERROR);
3513     }
3514 
3515     /* Check for mDNS stareted flag.  */
3516     if (!mdns_ptr -> nx_mdns_started)
3517     {
3518         return(NX_MDNS_NOT_STARTED);
3519     }
3520 
3521     /* Check the type. If the type is null,indicate lookup the all service type, the name and sub type must be null.  */
3522     if (!type)
3523     {
3524         if ((name) || (sub_type))
3525         {
3526             return(NX_MDNS_PARAM_ERROR);
3527         }
3528     }
3529     else
3530     {
3531 
3532         /* Check the name, If the name is non-null, the sub type must be null.  */
3533         if ((name) && (sub_type))
3534         {
3535             return(NX_MDNS_PARAM_ERROR);
3536         }
3537     }
3538 
3539     /* Check the name.  */
3540     if (name)
3541     {
3542 
3543         /* Check the name size.  */
3544         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_LABEL_MAX))
3545         {
3546             return(NX_MDNS_DATA_SIZE_ERROR);
3547         }
3548     }
3549 
3550     /* Check the type.  */
3551     if (type)
3552     {
3553 
3554         /* Check the type size.  */
3555         if (_nx_utility_string_length_check((CHAR *)type, NX_NULL, NX_MDNS_TYPE_MAX))
3556         {
3557             return(NX_MDNS_DATA_SIZE_ERROR);
3558         }
3559     }
3560 
3561     /* Check the sub type.  */
3562     if (sub_type)
3563     {
3564 
3565         /* Check the sub type size.  */
3566         if (_nx_utility_string_length_check((CHAR *)sub_type, NX_NULL, NX_MDNS_LABEL_MAX))
3567         {
3568             return(NX_MDNS_DATA_SIZE_ERROR);
3569         }
3570     }
3571 
3572     /* Call actual mDNS create service.  */
3573     status =  _nx_mdns_service_continuous_query(mdns_ptr, name, type, sub_type);
3574 
3575     /* Return status.  */
3576     return(status);
3577 }
3578 
3579 
3580 /**************************************************************************/
3581 /*                                                                        */
3582 /*  FUNCTION                                               RELEASE        */
3583 /*                                                                        */
3584 /*    _nx_mdns_service_continuous_query                   PORTABLE C      */
3585 /*                                                           6.1          */
3586 /*  AUTHOR                                                                */
3587 /*                                                                        */
3588 /*    Yuxin Zhou, Microsoft Corporation                                   */
3589 /*                                                                        */
3590 /*  DESCRIPTION                                                           */
3591 /*                                                                        */
3592 /*    This function starts service continuous query on all enabled        */
3593 /*    interfaces.                                                         */
3594 /*                                                                        */
3595 /*  INPUT                                                                 */
3596 /*                                                                        */
3597 /*    mdns_ptr                              Pointer to mDNS instance      */
3598 /*    name                                  The name of the service       */
3599 /*    type                                  The type of the service       */
3600 /*    subtype                               The subtype of the service    */
3601 /*                                                                        */
3602 /*  OUTPUT                                                                */
3603 /*                                                                        */
3604 /*    status                                Completion status             */
3605 /*                                                                        */
3606 /*  CALLS                                                                 */
3607 /*                                                                        */
3608 /*    tx_mutex_get                          Get the mDNS mutex            */
3609 /*    tx_mutex_put                          Put the mDNS mutex            */
3610 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3611 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
3612 /*    _nx_mdns_query                        Send the One Shot query       */
3613 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
3614 /*                                                                        */
3615 /*  CALLED BY                                                             */
3616 /*                                                                        */
3617 /*    Application Code                                                    */
3618 /*                                                                        */
3619 /*  RELEASE HISTORY                                                       */
3620 /*                                                                        */
3621 /*    DATE              NAME                      DESCRIPTION             */
3622 /*                                                                        */
3623 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3624 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3625 /*                                            resulting in version 6.1    */
3626 /*                                                                        */
3627 /**************************************************************************/
_nx_mdns_service_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3628 UINT _nx_mdns_service_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3629 {
3630 
3631 UINT        status = NX_MDNS_ERROR;
3632 UINT        type_index;
3633 UCHAR      *query_name;
3634 USHORT      query_type;
3635 UINT        query_success = NX_FALSE;
3636 UINT        i;
3637 
3638 
3639     /* Get the mDNS mutex.  */
3640     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3641 
3642     /* Step1. Construct the query name and set the query type.  */
3643     /* Check the type. if the type is null, indicate search all service.  */
3644     if (!type)
3645     {
3646 
3647         /* Set the query name and query type.  */
3648         query_name = (UCHAR *)_nx_mdns_dns_sd;
3649         query_type = NX_MDNS_RR_TYPE_PTR;
3650     }
3651     else if (name)
3652     {
3653 
3654         /* Construct the SRV name.  */
3655         status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
3656 
3657         /* Check the status.  */
3658         if (status)
3659         {
3660 
3661             /* Release the mDNS mutex.  */
3662             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3663             return (status);
3664         }
3665 
3666         /* Set the query name and query type (NX_MDNS_RR_TYPE_ALL for SRV and TXT).  */
3667         query_name = temp_string_buffer;
3668         query_type = NX_MDNS_RR_TYPE_ALL;
3669     }
3670     else
3671     {
3672 
3673         /* Construct the PTR name.  */
3674         status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
3675 
3676         /* Check the status.  */
3677         if (status)
3678         {
3679 
3680             /* Release the mDNS mutex.  */
3681             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3682             return (status);
3683         }
3684 
3685         /* Set the query name and query type.  */
3686         query_name = &temp_string_buffer[type_index];
3687         query_type = NX_MDNS_RR_TYPE_PTR;
3688     }
3689 
3690     /* Step2. Loop to start continuous query on all enabled interfaces.  */
3691     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
3692     {
3693 
3694         /* Check if this interface is enabled.  */
3695         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
3696             continue;
3697 
3698         /* Start continuous query.  */
3699         status = _nx_mdns_continuous_query(mdns_ptr, query_name, query_type, i);
3700 
3701         /* Check the status.  */
3702         if ((status == NX_SUCCESS) ||
3703             (status == NX_MDNS_EXIST_SAME_QUERY) ||
3704             (status == NX_MDNS_EXIST_UNIQUE_RR) ||
3705             (status == NX_MDNS_EXIST_SHARED_RR))
3706             query_success = NX_TRUE;
3707     }
3708 
3709     /* Release the mDNS mutex.  */
3710     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
3711 
3712     /* Check if start continuous query success.  */
3713     if (query_success)
3714         return (NX_MDNS_SUCCESS);
3715     else
3716         return(status);
3717 }
3718 
3719 
3720 /**************************************************************************/
3721 /*                                                                        */
3722 /*  FUNCTION                                               RELEASE        */
3723 /*                                                                        */
3724 /*    _nx_mdns_continuous_query                           PORTABLE C      */
3725 /*                                                           6.1.11       */
3726 /*  AUTHOR                                                                */
3727 /*                                                                        */
3728 /*    Yuxin Zhou, Microsoft Corporation                                   */
3729 /*                                                                        */
3730 /*  DESCRIPTION                                                           */
3731 /*                                                                        */
3732 /*    This function starts continuous query on specified interfaces.      */
3733 /*                                                                        */
3734 /*  INPUT                                                                 */
3735 /*                                                                        */
3736 /*    mdns_ptr                              Pointer to mDNS instance      */
3737 /*    interface_index                       The interface index           */
3738 /*    name                                  The resource record name      */
3739 /*    type                                  The resource record type      */
3740 /*                                                                        */
3741 /*  OUTPUT                                                                */
3742 /*                                                                        */
3743 /*    status                                Completion status             */
3744 /*                                                                        */
3745 /*  CALLS                                                                 */
3746 /*                                                                        */
3747 /*    tx_mutex_get                          Get the mDNS mutex            */
3748 /*    tx_mutex_put                          Put the mDNS mutex            */
3749 /*    _nx_mdns_query_check                  Check the query RR            */
3750 /*    _nx_mdns_cache_add_string             Add the string into cache     */
3751 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
3752 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
3753 /*                                            into cache                  */
3754 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
3755 /*                                            from cache                  */
3756 /*                                                                        */
3757 /*  CALLED BY                                                             */
3758 /*                                                                        */
3759 /*    Application Code                                                    */
3760 /*                                                                        */
3761 /*  RELEASE HISTORY                                                       */
3762 /*                                                                        */
3763 /*    DATE              NAME                      DESCRIPTION             */
3764 /*                                                                        */
3765 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3766 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3767 /*                                            resulting in version 6.1    */
3768 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
3769 /*                                            corrected the random value, */
3770 /*                                            fixed the issue of timer,   */
3771 /*                                            resulting in version 6.1.11 */
3772 /*                                                                        */
3773 /**************************************************************************/
_nx_mdns_continuous_query(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT interface_index)3774 static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index)
3775 {
3776 
3777 UINT        status;
3778 NX_MDNS_RR  *insert_rr;
3779 NX_MDNS_RR  temp_resource_record;
3780 UINT        name_length;
3781 
3782 
3783     /* Check the query RR.  */
3784     status = _nx_mdns_query_check(mdns_ptr, name, type, NX_FALSE, NX_NULL, interface_index);
3785 
3786     /* Check the state.  */
3787     if (status)
3788     {
3789         return(status);
3790     }
3791 
3792     /* Initialize the struct.  */
3793     memset(&temp_resource_record, 0, sizeof(NX_MDNS_RR));
3794 
3795     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
3796     {
3797         return (NX_MDNS_DATA_SIZE_ERROR);
3798     }
3799 
3800     /* Add the name.  */
3801     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, name, name_length,
3802                                        (VOID **)(&temp_resource_record.nx_mdns_rr_name), NX_FALSE, NX_TRUE);
3803 
3804     /* Check for error.  */
3805     if (status)
3806     {
3807         return(status);
3808     }
3809 
3810     /* Add the parameters.  */
3811     temp_resource_record.nx_mdns_rr_type = type;
3812     temp_resource_record.nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
3813 
3814     /* Set the resource record status.  */
3815     temp_resource_record.nx_mdns_rr_state = NX_MDNS_RR_STATE_QUERY;
3816 
3817     /* Remote resource record, set the owner flag.  */
3818     temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER);
3819 
3820     /* Continuous query, set the query type flag.  */
3821     if ((type != NX_MDNS_RR_TYPE_A) &&
3822         (type != NX_MDNS_RR_TYPE_AAAA))
3823     {
3824         temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_CONTINUOUS_QUERY);
3825     }
3826 
3827     /* Set the interface index.  */
3828     temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index;
3829 
3830     /* Add the resource record.  */
3831     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL);
3832 
3833     /* Check for error.  */
3834     if (status)
3835     {
3836 
3837         /* Delete the same strings. */
3838         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_resource_record.nx_mdns_rr_name, 0);
3839         return(status);
3840     }
3841 
3842     /* A multicast DNS querier should also delay the first query of the series by
3843         a randomly chosen amount in the range 20-120ms.  */
3844     insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
3845     insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
3846 
3847     /* Set the mDNS timer.  */
3848     _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
3849 
3850     /* Return success.  */
3851     return NX_SUCCESS;
3852 }
3853 
3854 
3855 /**************************************************************************/
3856 /*                                                                        */
3857 /*  FUNCTION                                               RELEASE        */
3858 /*                                                                        */
3859 /*    _nxe_mdns_service_query_stop                          PORTABLE C    */
3860 /*                                                           6.1          */
3861 /*  AUTHOR                                                                */
3862 /*                                                                        */
3863 /*    Yuxin Zhou, Microsoft Corporation                                   */
3864 /*                                                                        */
3865 /*  DESCRIPTION                                                           */
3866 /*                                                                        */
3867 /*    This function checks for errors in the mDNS resource record query   */
3868 /*    add function call.                                                  */
3869 /*                                                                        */
3870 /*  INPUT                                                                 */
3871 /*                                                                        */
3872 /*    mdns_ptr                              Pointer to mDNS instance      */
3873 /*    name                                  The name of the service       */
3874 /*    type                                  The type of the service       */
3875 /*    subtype                               The subtype of the service    */
3876 /*                                                                        */
3877 /*  OUTPUT                                                                */
3878 /*                                                                        */
3879 /*    status                                Completion status             */
3880 /*                                                                        */
3881 /*  CALLS                                                                 */
3882 /*                                                                        */
3883 /*    _nx_mdns_service_query_stop           Actual query RR function      */
3884 /*                                                                        */
3885 /*  CALLED BY                                                             */
3886 /*                                                                        */
3887 /*    Application Code                                                    */
3888 /*                                                                        */
3889 /*  RELEASE HISTORY                                                       */
3890 /*                                                                        */
3891 /*    DATE              NAME                      DESCRIPTION             */
3892 /*                                                                        */
3893 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3894 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3895 /*                                            resulting in version 6.1    */
3896 /*                                                                        */
3897 /**************************************************************************/
_nxe_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3898 UINT _nxe_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3899 {
3900 
3901 UINT    status;
3902 
3903 
3904     /* Check for invalid input pointers.  */
3905     if (!mdns_ptr)
3906     {
3907         return(NX_PTR_ERROR);
3908     }
3909 
3910     /* Check for invalid server attributes. */
3911     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
3912     {
3913         return(NX_MDNS_PARAM_ERROR);
3914     }
3915 
3916     if (name)
3917     {
3918 
3919         /* Check the size.  */
3920         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
3921         {
3922             return(NX_MDNS_DATA_SIZE_ERROR);
3923         }
3924     }
3925 
3926     /* Call actual mDNS create service.  */
3927     status =  _nx_mdns_service_query_stop(mdns_ptr, name, type, sub_type);
3928 
3929     /* Return status.  */
3930     return(status);
3931 }
3932 
3933 
3934 /**************************************************************************/
3935 /*                                                                        */
3936 /*  FUNCTION                                               RELEASE        */
3937 /*                                                                        */
3938 /*    _nx_mdns_service_query_stop                         PORTABLE C      */
3939 /*                                                           6.1          */
3940 /*  AUTHOR                                                                */
3941 /*                                                                        */
3942 /*    Yuxin Zhou, Microsoft Corporation                                   */
3943 /*                                                                        */
3944 /*  DESCRIPTION                                                           */
3945 /*                                                                        */
3946 /*    This function adds the mDNS resource record into peer service cache,*/
3947 /*    mDNS thread send the query message using continuous type.           */
3948 /*                                                                        */
3949 /*  INPUT                                                                 */
3950 /*                                                                        */
3951 /*    mdns_ptr                              Pointer to mDNS instance      */
3952 /*    name                                  The name of the service       */
3953 /*    type                                  The type of the service       */
3954 /*    subtype                               The subtype of the service    */
3955 /*                                                                        */
3956 /*  OUTPUT                                                                */
3957 /*                                                                        */
3958 /*    status                                Completion status             */
3959 /*                                                                        */
3960 /*  CALLS                                                                 */
3961 /*                                                                        */
3962 /*    tx_mutex_get                          Get the mDNS mutex            */
3963 /*    tx_mutex_put                          Put the mDNS mutex            */
3964 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
3965 /*    _nx_mdns_name_match                   Match the name string         */
3966 /*    _nx_mdns_rr_delete                    Delete the resource record    */
3967 /*                                                                        */
3968 /*  CALLED BY                                                             */
3969 /*                                                                        */
3970 /*    Application Code                                                    */
3971 /*                                                                        */
3972 /*  RELEASE HISTORY                                                       */
3973 /*                                                                        */
3974 /*    DATE              NAME                      DESCRIPTION             */
3975 /*                                                                        */
3976 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3977 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3978 /*                                            resulting in version 6.1    */
3979 /*                                                                        */
3980 /**************************************************************************/
_nx_mdns_service_query_stop(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type)3981 UINT _nx_mdns_service_query_stop(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type)
3982 {
3983 
3984 UINT        status;
3985 UINT        type_index = 0;
3986 UINT        query_stop = NX_FALSE;
3987 ULONG       *head;
3988 NX_MDNS_RR  *p;
3989 UINT         rr_name_length;
3990 
3991 
3992     /* Get the mDNS mutex.  */
3993     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
3994 
3995     if (type)
3996     {
3997         if (name)
3998         {
3999 
4000             /* Construct the SRV name.  */
4001             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4002 
4003             /* Check the status.  */
4004             if (status)
4005             {
4006 
4007                 /* Release the mDNS mutex.  */
4008                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4009                 return (status);
4010             }
4011         }
4012         else
4013         {
4014 
4015             /* Construct the PTR name.  */
4016             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4017 
4018             /* Check the status.  */
4019             if (status)
4020             {
4021 
4022                 /* Release the mDNS mutex.  */
4023                 tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4024                 return (status);
4025             }
4026         }
4027     }
4028 
4029     /* Get the remote buffer head. */
4030     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4031 
4032     if (!head)
4033     {
4034 
4035         /* Release the mDNS mutex.  */
4036         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4037 
4038         /* Return a successful status.  */
4039         return(NX_MDNS_CACHE_ERROR);
4040     }
4041 
4042     /* Set the pointer.  */
4043     head = (ULONG*)(*head);
4044 
4045     /* Loop to delete query resource record.  */
4046     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
4047     {
4048 
4049         /* Check the resource record state. */
4050         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
4051             continue;
4052 
4053         /* Check string length.  */
4054         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
4055         {
4056             continue;
4057         }
4058 
4059         if (!type)
4060         {
4061             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
4062                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
4063             {
4064 
4065                 /* Delete the resource records.  */
4066                 status = _nx_mdns_rr_delete(mdns_ptr, p);
4067 
4068                 /* Check status.  */
4069                 if (status == NX_MDNS_SUCCESS)
4070                     query_stop = NX_TRUE;
4071             }
4072         }
4073         else
4074         {
4075             if (name)
4076             {
4077                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) &&
4078                     (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], rr_name_length)))
4079                 {
4080 
4081                     /* Delete the resource records.  */
4082                     status = _nx_mdns_rr_delete(mdns_ptr, p);
4083 
4084                     /* Check status.  */
4085                     if (status == NX_MDNS_SUCCESS)
4086                         query_stop = NX_TRUE;
4087                 }
4088             }
4089             else
4090             {
4091                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)&&
4092                     (!_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[type_index], rr_name_length)))
4093                 {
4094 
4095                     /* Delete the resource records.  */
4096                     status = _nx_mdns_rr_delete(mdns_ptr, p);
4097 
4098                     /* Check status.  */
4099                     if (status == NX_MDNS_SUCCESS)
4100                         query_stop = NX_TRUE;
4101                 }
4102             }
4103         }
4104     }
4105 
4106     /* Release the mDNS mutex.  */
4107     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4108 
4109     /* Check if stop service continuous query.  */
4110     if (query_stop == NX_TRUE)
4111         return(NX_MDNS_SUCCESS);
4112     else
4113         return(NX_MDNS_ERROR);
4114 }
4115 
4116 
4117 /**************************************************************************/
4118 /*                                                                        */
4119 /*  FUNCTION                                               RELEASE        */
4120 /*                                                                        */
4121 /*    _nxe_mdns_service_lookup                              PORTABLE C    */
4122 /*                                                           6.1          */
4123 /*  AUTHOR                                                                */
4124 /*                                                                        */
4125 /*    Yuxin Zhou, Microsoft Corporation                                   */
4126 /*                                                                        */
4127 /*  DESCRIPTION                                                           */
4128 /*                                                                        */
4129 /*    This function checks for errors in the mDNS resource record query   */
4130 /*    add function call.                                                  */
4131 /*                                                                        */
4132 /*  INPUT                                                                 */
4133 /*                                                                        */
4134 /*    mdns_ptr                              Pointer to mDNS instance      */
4135 /*    name                                  The name of the service       */
4136 /*    type                                  The type of the service       */
4137 /*    subtype                               The subtype of the service    */
4138 /*    service_index                         The index of the service      */
4139 /*    service                               Pointer to Service instance   */
4140 /*                                                                        */
4141 /*  OUTPUT                                                                */
4142 /*                                                                        */
4143 /*    status                                Completion status             */
4144 /*                                                                        */
4145 /*  CALLS                                                                 */
4146 /*                                                                        */
4147 /*    _nx_mdns_service_lookup               Actual mDNS query RR function */
4148 /*                                                                        */
4149 /*  CALLED BY                                                             */
4150 /*                                                                        */
4151 /*    Application Code                                                    */
4152 /*                                                                        */
4153 /*  RELEASE HISTORY                                                       */
4154 /*                                                                        */
4155 /*    DATE              NAME                      DESCRIPTION             */
4156 /*                                                                        */
4157 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4158 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4159 /*                                            resulting in version 6.1    */
4160 /*                                                                        */
4161 /**************************************************************************/
_nxe_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4162 UINT _nxe_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4163 {
4164 
4165 UINT    status;
4166 
4167 
4168     /* Check for invalid input pointers.  */
4169     if (!mdns_ptr)
4170     {
4171         return(NX_PTR_ERROR);
4172     }
4173 
4174     /* Check for invalid server attributes. */
4175     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4176     {
4177         return(NX_MDNS_PARAM_ERROR);
4178     }
4179 
4180     if (name)
4181     {
4182 
4183         /* Check the size.  */
4184         if (_nx_utility_string_length_check((CHAR *)name, NX_NULL, NX_MDNS_NAME_MAX))
4185         {
4186             return(NX_MDNS_DATA_SIZE_ERROR);
4187         }
4188     }
4189 
4190     /* Call actual mDNS create service.  */
4191     status =  _nx_mdns_service_lookup(mdns_ptr, name, type, sub_type, service_index, service);
4192 
4193     /* Return status.  */
4194     return(status);
4195 }
4196 
4197 
4198 /**************************************************************************/
4199 /*                                                                        */
4200 /*  FUNCTION                                               RELEASE        */
4201 /*                                                                        */
4202 /*    _nx_mdns_service_lookup                             PORTABLE C      */
4203 /*                                                           6.1.11       */
4204 /*  AUTHOR                                                                */
4205 /*                                                                        */
4206 /*    Yuxin Zhou, Microsoft Corporation                                   */
4207 /*                                                                        */
4208 /*  DESCRIPTION                                                           */
4209 /*                                                                        */
4210 /*    This function adds the mDNS resource record into peer service cache,*/
4211 /*    mDNS thread send the query message using continuous type.           */
4212 /*                                                                        */
4213 /*  INPUT                                                                 */
4214 /*                                                                        */
4215 /*    mdns_ptr                              Pointer to mDNS instance      */
4216 /*    name                                  The name of the service       */
4217 /*    type                                  The type of the service       */
4218 /*    subtype                               The subtype of the service    */
4219 /*    service_index                         The index of the service      */
4220 /*    service                               Pointer to Service instance   */
4221 /*                                                                        */
4222 /*  OUTPUT                                                                */
4223 /*                                                                        */
4224 /*    status                                Completion status             */
4225 /*                                                                        */
4226 /*  CALLS                                                                 */
4227 /*                                                                        */
4228 /*    tx_mutex_get                          Get the mDNS mutex            */
4229 /*    tx_mutex_put                          Put the mDNS mutex            */
4230 /*    tx_time_get                           Get the time                  */
4231 /*    _nx_mdns_service_name_assemble        Assemble the service name     */
4232 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
4233 /*    _nx_mdns_service_addition_info_get    Get additional info of service*/
4234 /*    _nx_mdns_name_match                   Match the name string         */
4235 /*                                                                        */
4236 /*  CALLED BY                                                             */
4237 /*                                                                        */
4238 /*    Application Code                                                    */
4239 /*                                                                        */
4240 /*  RELEASE HISTORY                                                       */
4241 /*                                                                        */
4242 /*    DATE              NAME                      DESCRIPTION             */
4243 /*                                                                        */
4244 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4245 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4246 /*                                            verified memcpy use cases,  */
4247 /*                                            resulting in version 6.1    */
4248 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
4249 /*                                            fixed compiler warnings,    */
4250 /*                                            resulting in version 6.1.11 */
4251 /*                                                                        */
4252 /**************************************************************************/
_nx_mdns_service_lookup(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR * type,UCHAR * sub_type,UINT service_index,NX_MDNS_SERVICE * service)4253 UINT _nx_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service)
4254 {
4255 
4256 UINT        status;
4257 UINT        type_index;
4258 UINT        dns_sd_flag;
4259 UINT        sub_type_flag;
4260 UINT        index;
4261 UINT        count;
4262 UINT        found;
4263 UCHAR       *srv_name = NX_NULL;
4264 UCHAR       *ptr;
4265 UCHAR       *tmp_sub_type;
4266 UCHAR       *tmp_type;
4267 UCHAR       *tmp_domain;
4268 NX_MDNS_RR  *p = NX_NULL;
4269 NX_MDNS_RR  *p1;
4270 ULONG       *head, *tail;
4271 UCHAR       i;
4272 UINT        interface_index = 0;
4273 UINT        temp_string_length;
4274 UINT        dns_sd_length;
4275 UINT        srv_name_length;
4276 UINT        target_string_length;
4277 
4278 
4279     /* Get the mDNS mutex.  */
4280     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4281 
4282     /* Zero out the content of service */
4283     memset(service, 0, sizeof(NX_MDNS_SERVICE));
4284 
4285     /* Initialize the struct.  */
4286     count = 0;
4287     found = NX_FALSE;
4288 
4289     /* Check the type.  */
4290     if (type)
4291     {
4292         if (name)
4293         {
4294 
4295             /* Construct the Service name.  */
4296             status = _nx_mdns_service_name_assemble(name, type, NX_NULL, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, NX_NULL);
4297 
4298         }
4299         else
4300         {
4301 
4302             /* Construct the Service name.  */
4303             status = _nx_mdns_service_name_assemble(NX_NULL, type, sub_type, mdns_ptr -> nx_mdns_domain_name, &temp_string_buffer[0], NX_MDNS_NAME_MAX, &type_index);
4304         }
4305         /* Check the status.  */
4306         if (status)
4307         {
4308 
4309             /* Release the mDNS mutex.  */
4310             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4311             return (status);
4312         }
4313 
4314         /* Check string length.  */
4315         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
4316         {
4317 
4318             /* Release the mDNS mutex.  */
4319             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4320             return (NX_MDNS_DATA_SIZE_ERROR);
4321         }
4322     }
4323 
4324     /* Check the DNS-SD string.  */
4325     if (_nx_utility_string_length_check((CHAR *)_nx_mdns_dns_sd, &dns_sd_length, NX_MDNS_DNS_SD_MAX))
4326     {
4327 
4328         /* Release the mDNS mutex.  */
4329         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4330         return (NX_MDNS_DATA_SIZE_ERROR);
4331     }
4332 
4333     /* Loop to search local and peer cache.  */
4334     for(i = 0; i < 2; i++)
4335     {
4336 
4337         /* Set the pointer. */
4338         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
4339         {
4340 #ifndef NX_MDNS_DISABLE_SERVER
4341             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
4342 #else
4343             continue;
4344 #endif /* NX_MDNS_DISABLE_SERVER */
4345         }
4346         else
4347         {
4348             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
4349         }
4350 
4351         if(head == NX_NULL)
4352             continue;
4353 
4354         /* Set the pointer.  */
4355         tail = (ULONG*)(*head);
4356 
4357         /* Check the resource record.  */
4358         for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
4359         {
4360 
4361             /* Check whether the resource record is valid. */
4362             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4363                 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4364                 continue;
4365 
4366             if((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) || (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4367             {
4368 
4369                 if(type)
4370                 {
4371                     if (_nx_mdns_name_match(p -> nx_mdns_rr_name, &temp_string_buffer[0], temp_string_length))
4372                         continue;
4373                 }
4374                 else if(p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
4375                     continue;
4376 
4377                 if(name && (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV))
4378                 {
4379 
4380                     /* Store the service name.  */
4381                     srv_name = p -> nx_mdns_rr_name;
4382                     interface_index = p -> nx_mdns_rr_interface_index;
4383                 }
4384                 else
4385                 {
4386 
4387                     /* Set the service name pointer.  */
4388                     srv_name = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name;
4389                     interface_index = p -> nx_mdns_rr_interface_index;
4390                 }
4391 
4392                 /* Check string length.  */
4393                 if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
4394                     continue;
4395 
4396                 /* Store the service name.  */
4397                 memcpy((CHAR *)(service -> buffer), (CHAR *)srv_name, srv_name_length + 1); /* Use case of memcpy is verified. */
4398 
4399                 /* Reslove the service name and check the PTR rdata name. Ignore the PTR when the PTR rdata does not pointer the service.  */
4400                 status = _nx_mdns_service_name_resolve(service -> buffer, &(service -> service_name), &(service -> service_type), &(service -> service_domain));
4401 
4402                 if (status)
4403                     continue;
4404 
4405                 if(type == NX_NULL)
4406                 {
4407 
4408                     /* Set the parameters.  */
4409                     sub_type_flag = NX_FALSE;
4410                     dns_sd_flag = NX_FALSE;
4411                     index = 0;
4412 
4413                     /* Check the PTR resource record with sub type.  */
4414                     ptr = p -> nx_mdns_rr_name;
4415                     while (*ptr != '\0')
4416                     {
4417                         if (*ptr == '.')
4418                         {
4419                             if (!_nx_mdns_name_match(ptr - index, (UCHAR *)"_sub", 4))
4420                             {
4421                                 sub_type_flag = NX_TRUE;
4422                                 break;
4423                             }
4424                             index = 0;
4425                         }
4426                         else
4427                             index ++;
4428                         ptr ++;
4429                     }
4430                     if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, dns_sd_length))
4431                     {
4432                         dns_sd_flag = NX_TRUE;
4433                     }
4434 
4435                     /* Check the DNS-SD PTR reousrce record.  */
4436                     if ((dns_sd_flag == NX_TRUE) ||
4437                         (sub_type_flag == NX_TRUE))
4438                     {
4439 
4440                         /* Find the PTR resource record which pointer to the service.  */
4441                         for(p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
4442                         {
4443 
4444                             /* Check whether the resource record is valid. */
4445                             if ((p1 == p) ||
4446                                 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
4447                                 (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
4448                                 continue;
4449 
4450                             /* Check the interface index.  */
4451                             if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
4452                                 continue;
4453 
4454                             if (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
4455                             {
4456                                 if ((dns_sd_flag == NX_TRUE))
4457                                 {
4458 
4459                                     /* Check string length.  */
4460                                     if (_nx_utility_string_length_check((CHAR *)(p1 -> nx_mdns_rr_name), &target_string_length, NX_MDNS_NAME_MAX))
4461                                     {
4462                                         continue;
4463                                     }
4464 
4465                                     /* Set the pointer.  */
4466                                     memcpy((CHAR *)&target_string_buffer[0], (CHAR *)(p1 -> nx_mdns_rr_name), target_string_length + 1); /* Use case of memcpy is verified. */
4467 
4468                                     /* Reslove the type.  */
4469                                     status = _nx_mdns_service_name_resolve(&target_string_buffer[0], &tmp_sub_type, &tmp_type, &tmp_domain);
4470 
4471                                     if (status)
4472                                         continue;
4473 
4474                                     /* Check string length.  */
4475                                     if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4476                                     {
4477                                         continue;
4478                                     }
4479 
4480                                     /* Construct the type and doamin, _http._tcp.local.  */
4481                                     *(tmp_type + target_string_length) = '.';
4482 
4483                                     /* Check string length.  */
4484                                     if (_nx_utility_string_length_check((CHAR *)tmp_type, &target_string_length, NX_MDNS_TYPE_MAX))
4485                                     {
4486                                         continue;
4487                                     }
4488 
4489                                     /* Compare the DNS_SD rdata.  */
4490                                     if (!_nx_mdns_name_match(tmp_type, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, target_string_length))
4491                                     {
4492 
4493                                         /* Exist resource record including more info.  */
4494                                         count --;
4495                                         break;
4496                                     }
4497                                 }
4498                                 else
4499                                 {
4500 
4501                                     /* Exist the PTR RR which pointer to the same service.  */
4502                                     if (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
4503                                     {
4504                                         count --;
4505                                         break;
4506                                     }
4507                                 }
4508                             }
4509                         }
4510                     }
4511                 }
4512 
4513                 /* Check the count state.  */
4514                 if (count == service_index)
4515                 {
4516                     /* Yes, find. */
4517                     found = NX_TRUE;
4518                     break;
4519                 }
4520                 count ++;
4521             }
4522         }
4523 
4524         /* Check if find the service.  */
4525         if (found == NX_TRUE)
4526         {
4527             break;
4528         }
4529     }
4530 
4531     if (found)
4532     {
4533 
4534         /* Update the elasped time.  */
4535         p -> nx_mdns_rr_elapsed_time = tx_time_get();
4536 
4537         /* Get the additional information.  */
4538         _nx_mdns_service_addition_info_get(mdns_ptr, srv_name, service, interface_index);
4539 
4540         /* Release the mDNS mutex.  */
4541         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4542         return(NX_MDNS_SUCCESS);
4543     }
4544     else
4545     {
4546         /* Release the mDNS mutex.  */
4547         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4548         return(NX_MDNS_NO_MORE_ENTRIES);
4549     }
4550 }
4551 
4552 
4553 /**************************************************************************/
4554 /*                                                                        */
4555 /*  FUNCTION                                               RELEASE        */
4556 /*                                                                        */
4557 /*    _nxe_mdns_peer_cache_clear                            PORTABLE C    */
4558 /*                                                           6.1          */
4559 /*  AUTHOR                                                                */
4560 /*                                                                        */
4561 /*    Yuxin Zhou, Microsoft Corporation                                   */
4562 /*                                                                        */
4563 /*  DESCRIPTION                                                           */
4564 /*                                                                        */
4565 /*    This function checks for errors in the mDNS peer service cache      */
4566 /*    clear function call.                                                */
4567 /*                                                                        */
4568 /*  INPUT                                                                 */
4569 /*                                                                        */
4570 /*    mdns_ptr                              Pointer to mDNS instance      */
4571 /*                                                                        */
4572 /*  OUTPUT                                                                */
4573 /*                                                                        */
4574 /*    status                                Completion status             */
4575 /*                                                                        */
4576 /*  CALLS                                                                 */
4577 /*                                                                        */
4578 /*    _nx_mdns_peer_cache_clear             Actual peer cache clear       */
4579 /*                                            function                    */
4580 /*                                                                        */
4581 /*  CALLED BY                                                             */
4582 /*                                                                        */
4583 /*    Application Code                                                    */
4584 /*                                                                        */
4585 /*  RELEASE HISTORY                                                       */
4586 /*                                                                        */
4587 /*    DATE              NAME                      DESCRIPTION             */
4588 /*                                                                        */
4589 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4590 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4591 /*                                            resulting in version 6.1    */
4592 /*                                                                        */
4593 /**************************************************************************/
_nxe_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4594 UINT _nxe_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4595 {
4596 
4597 UINT    status;
4598 
4599 
4600     /* Check for invalid input pointers.  */
4601     if (!mdns_ptr)
4602     {
4603         return(NX_PTR_ERROR);
4604     }
4605 
4606     /* Check for invalid server attributes. */
4607     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
4608     {
4609         return(NX_MDNS_PARAM_ERROR);
4610     }
4611 
4612     /* Call actual mDNS create service.  */
4613     status =  _nx_mdns_peer_cache_clear(mdns_ptr);
4614 
4615     /* Return status.  */
4616     return(status);
4617 }
4618 
4619 
4620 /**************************************************************************/
4621 /*                                                                        */
4622 /*  FUNCTION                                               RELEASE        */
4623 /*                                                                        */
4624 /*    _nx_mdns_peer_cache_clear                           PORTABLE C      */
4625 /*                                                           6.1          */
4626 /*  AUTHOR                                                                */
4627 /*                                                                        */
4628 /*    Yuxin Zhou, Microsoft Corporation                                   */
4629 /*                                                                        */
4630 /*  DESCRIPTION                                                           */
4631 /*                                                                        */
4632 /*    This function clears the mDNS peer service cache.                   */
4633 /*                                                                        */
4634 /*  INPUT                                                                 */
4635 /*                                                                        */
4636 /*    mdns_ptr                              Pointer to mDNS instance      */
4637 /*                                                                        */
4638 /*  OUTPUT                                                                */
4639 /*                                                                        */
4640 /*    status                                Completion status             */
4641 /*                                                                        */
4642 /*  CALLS                                                                 */
4643 /*                                                                        */
4644 /*    tx_mutex_get                          Get the mDNS mutex            */
4645 /*    tx_mutex_put                          Put the mDNS mutex            */
4646 /*    _nx_mdns_cache_initialize             Initialize the cache          */
4647 /*                                                                        */
4648 /*  CALLED BY                                                             */
4649 /*                                                                        */
4650 /*    Application Code                                                    */
4651 /*                                                                        */
4652 /*  RELEASE HISTORY                                                       */
4653 /*                                                                        */
4654 /*    DATE              NAME                      DESCRIPTION             */
4655 /*                                                                        */
4656 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4657 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4658 /*                                            resulting in version 6.1    */
4659 /*                                                                        */
4660 /**************************************************************************/
_nx_mdns_peer_cache_clear(NX_MDNS * mdns_ptr)4661 UINT _nx_mdns_peer_cache_clear(NX_MDNS *mdns_ptr)
4662 {
4663 
4664 UINT    status;
4665 
4666 
4667     /* Get the mDNS mutex.  */
4668     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
4669 
4670     status = _nx_mdns_cache_initialize(mdns_ptr, NX_NULL, NX_NULL, mdns_ptr -> nx_mdns_peer_service_cache, mdns_ptr -> nx_mdns_peer_service_cache_size);
4671 
4672     /* Release the mDNS mutex.  */
4673     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4674 
4675     /* Return a error status.  */
4676     return(status);
4677 }
4678 
4679 
4680 /**************************************************************************/
4681 /*                                                                        */
4682 /*  FUNCTION                                               RELEASE        */
4683 /*                                                                        */
4684 /*    _nxe_mdns_host_address_get                          PORTABLE C      */
4685 /*                                                           6.1          */
4686 /*  AUTHOR                                                                */
4687 /*                                                                        */
4688 /*    Yuxin Zhou, Microsoft Corporation                                   */
4689 /*                                                                        */
4690 /*  DESCRIPTION                                                           */
4691 /*                                                                        */
4692 /*    This function checks for errors in the mDNS host address get        */
4693 /*    function call.                                                      */
4694 /*                                                                        */
4695 /*  INPUT                                                                 */
4696 /*                                                                        */
4697 /*    mdns_ptr                              Pointer to mDNS instance      */
4698 /*    name                                  The name of the service       */
4699 /*    type                                  The type of the service       */
4700 /*    subtype                               The subtype of the service    */
4701 /*    service                               Pointer to response service   */
4702 /*    timeout                               The timeour for service query */
4703 /*                                                                        */
4704 /*  OUTPUT                                                                */
4705 /*                                                                        */
4706 /*    status                                Completion status             */
4707 /*                                                                        */
4708 /*  CALLS                                                                 */
4709 /*                                                                        */
4710 /*    _nx_mdns_host_address_get             Actual mDNS host address      */
4711 /*                                            get function                */
4712 /*                                                                        */
4713 /*  CALLED BY                                                             */
4714 /*                                                                        */
4715 /*    Application Code                                                    */
4716 /*                                                                        */
4717 /*  RELEASE HISTORY                                                       */
4718 /*                                                                        */
4719 /*    DATE              NAME                      DESCRIPTION             */
4720 /*                                                                        */
4721 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4722 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
4723 /*                                            buffer length verification, */
4724 /*                                            resulting in version 6.1    */
4725 /*                                                                        */
4726 /**************************************************************************/
_nxe_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4727 UINT _nxe_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address,  UINT timeout)
4728 {
4729 
4730 UINT    status;
4731 
4732 
4733     /* Check for invalid input pointers.  */
4734     if ((!mdns_ptr) || (!host_name))
4735     {
4736         return(NX_PTR_ERROR);
4737     }
4738 
4739     /* Check for mDNS started flag.  */
4740     if (!mdns_ptr -> nx_mdns_started)
4741     {
4742         return(NX_MDNS_NOT_STARTED);
4743     }
4744 
4745     /* Call actual mDNS create service.  */
4746     status = _nx_mdns_host_address_get(mdns_ptr, host_name, ipv4_address, ipv6_address, timeout);
4747 
4748     /* Return status.  */
4749     return(status);
4750 }
4751 
4752 
4753 /**************************************************************************/
4754 /*                                                                        */
4755 /*  FUNCTION                                               RELEASE        */
4756 /*                                                                        */
4757 /*    _nx_mdns_host_address_get                           PORTABLE C      */
4758 /*                                                           6.1          */
4759 /*  AUTHOR                                                                */
4760 /*                                                                        */
4761 /*    Yuxin Zhou, Microsoft Corporation                                   */
4762 /*                                                                        */
4763 /*  DESCRIPTION                                                           */
4764 /*                                                                        */
4765 /*    This function adds the mDNS query record into peer buffer,          */
4766 /*    mDNS thread send the query message using one-shot type.             */
4767 /*                                                                        */
4768 /*  INPUT                                                                 */
4769 /*                                                                        */
4770 /*    mdns_ptr                              Pointer to mDNS instance      */
4771 /*    name                                  The name of the service       */
4772 /*    type                                  The type of the service       */
4773 /*    subtype                               The subtype of the service    */
4774 /*    service                               Pointer to response service   */
4775 /*    timeout                               The timeour for service query */
4776 /*                                                                        */
4777 /*  OUTPUT                                                                */
4778 /*                                                                        */
4779 /*    status                                Completion status             */
4780 /*                                                                        */
4781 /*  CALLS                                                                 */
4782 /*                                                                        */
4783 /*    tx_mutex_get                          Get the mDNS mutex            */
4784 /*    tx_mutex_put                          Put the mDNS mutex            */
4785 /*    tx_time_get                           Get the mDNS time             */
4786 /*    _nx_mdns_host_check                   Check the host info           */
4787 /*    _nx_mdns_answer_wait                  Wait the answer               */
4788 /*    _nx_mdns_cache_add_query              Add the query into cache      */
4789 /*    _nx_mdns_cache_delete_query           Delete the query from cache   */
4790 /*                                                                        */
4791 /*  CALLED BY                                                             */
4792 /*                                                                        */
4793 /*    Application Code                                                    */
4794 /*                                                                        */
4795 /*  RELEASE HISTORY                                                       */
4796 /*                                                                        */
4797 /*    DATE              NAME                      DESCRIPTION             */
4798 /*                                                                        */
4799 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4800 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4801 /*                                            verified memcpy use cases,  */
4802 /*                                            resulting in version 6.1    */
4803 /*                                                                        */
4804 /**************************************************************************/
_nx_mdns_host_address_get(NX_MDNS * mdns_ptr,UCHAR * host_name,ULONG * ipv4_address,ULONG * ipv6_address,UINT timeout)4805 UINT _nx_mdns_host_address_get(NX_MDNS *mdns_ptr, UCHAR *host_name, ULONG *ipv4_address, ULONG *ipv6_address, UINT timeout)
4806 {
4807 
4808 UINT                status;
4809 ULONG               start_time;
4810 ULONG               current_time;
4811 ULONG               elapsed_time;
4812 ULONG               wait_time = timeout;
4813 NX_MDNS_RR         *a_rr;
4814 NX_MDNS_RR         *aaaa_rr;
4815 UCHAR               host_name_query[NX_MDNS_NAME_MAX + 1];
4816 UINT                i = 0;
4817 UCHAR               domain_flag = NX_FALSE;
4818 UINT                answer = NX_FALSE;
4819 UINT                domain_name_length;
4820 
4821 
4822     /* Check string length.  */
4823     if (_nx_utility_string_length_check((CHAR *)host_name, NX_NULL, NX_MDNS_HOST_NAME_MAX))
4824     {
4825         return(NX_MDNS_DATA_SIZE_ERROR);
4826     }
4827 
4828     /* Get the mDNS mutex.  */
4829     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), NX_WAIT_FOREVER);
4830 
4831     /* Clear the buffer.  */
4832     memset(host_name_query, 0, NX_MDNS_NAME_MAX + 1);
4833 
4834     /* Copy the host name into host name query buffer.  */
4835     while(host_name[i] != NX_NULL)
4836     {
4837         host_name_query[i] = host_name[i];
4838         if (host_name[i] == '.')
4839         {
4840 
4841             /* Update the flag.  */
4842             domain_flag = NX_TRUE;
4843         }
4844         i++;
4845     }
4846 
4847     /* Check if include the domain.  */
4848     if (domain_flag == NX_FALSE)
4849     {
4850         host_name_query[i++] = '.';
4851 
4852         /* Check string length.  */
4853         if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &domain_name_length, NX_MDNS_DOMAIN_NAME_MAX))
4854         {
4855 
4856             /* Release the mDNS mutex.  */
4857             tx_mutex_put(&(mdns_ptr->nx_mdns_mutex));
4858             return (NX_MDNS_DATA_SIZE_ERROR);
4859         }
4860 
4861         memcpy((char*)(&host_name_query[i]), (const char*)mdns_ptr -> nx_mdns_domain_name, domain_name_length + 1); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX and NX_MDNS_DOMAIN_NAME_MAX are limited in nxd_mdns.h. */
4862     }
4863 
4864     /* Initialize the value.  */
4865     if (ipv4_address)
4866         *ipv4_address = NX_NULL;
4867     if (ipv6_address)
4868         memset(ipv6_address, 0, 16);
4869 
4870     /* Start host address query on all enabled interfaces until get the answer or query timeout.  */
4871     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
4872     {
4873 
4874         /* Check if this interface is enabled.  */
4875         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
4876             continue;
4877 
4878         /* Get the query start time.  */
4879         wait_time = timeout;
4880         start_time = tx_time_get();
4881 
4882         /* Get the host IPv4 address.  */
4883         if (ipv4_address)
4884         {
4885 
4886             /* One shot query for host name.  */
4887             status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_A, &a_rr, wait_time, i);
4888 
4889             /* Check the status.  */
4890             if (status == NX_MDNS_SUCCESS)
4891             {
4892 
4893                 /* Set the IPv4 address.  */
4894                 *ipv4_address = a_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
4895                 answer = NX_TRUE;
4896             }
4897         }
4898 
4899         /* Get the host IPv6 address.  */
4900         if (ipv6_address)
4901         {
4902 
4903             /* How much time has elapsed? */
4904             current_time = tx_time_get();
4905 
4906             /* Has the time wrapped? */
4907             if (current_time >= start_time)
4908             {
4909                 /* No, simply subtract to get the elapsed time.   */
4910                 elapsed_time =  current_time - start_time;
4911             }
4912             else
4913             {
4914 
4915                 /* Yes it has. Time has rolled over the 32-bit boundary.  */
4916                 elapsed_time =  (((ULONG) 0xFFFFFFFF) - start_time) + current_time;
4917             }
4918 
4919             /* Update the timeout.  */
4920             if (wait_time > elapsed_time)
4921                 wait_time -= elapsed_time;
4922             else
4923                 wait_time = 0;
4924 
4925             /* Lookup the service.  */
4926             status = _nx_mdns_one_shot_query(mdns_ptr, host_name_query, NX_MDNS_RR_TYPE_AAAA, &aaaa_rr, wait_time, i);
4927 
4928             /* Check the status.  */
4929             if (status == NX_MDNS_SUCCESS)
4930             {
4931 
4932                 /* Set the IPv6 address.  */
4933                 *ipv6_address = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[0];
4934                 *(ipv6_address + 1) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[1];
4935                 *(ipv6_address + 2) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[2];
4936                 *(ipv6_address + 3) = aaaa_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa .nx_mdns_rr_aaaa_address[3];
4937                 answer = NX_TRUE;
4938             }
4939         }
4940 
4941         /* Check if get IPv4 address or IPv6 address.  */
4942         if (answer == NX_TRUE)
4943         {
4944 
4945             /* Release the mDNS mutex.  */
4946             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4947             return (NX_MDNS_SUCCESS);
4948         }
4949     }
4950 
4951     /* Release the mDNS mutex.  */
4952     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
4953     return (NX_MDNS_ERROR);
4954 }
4955 #endif /* NX_MDNS_DISABLE_CLIENT */
4956 
4957 
4958 #ifndef NX_MDNS_DISABLE_SERVER
4959 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
4960 /**************************************************************************/
4961 /*                                                                        */
4962 /*  FUNCTION                                               RELEASE        */
4963 /*                                                                        */
4964 /*    _nx_mdns_rr_a_aaaa_add                                PORTABLE C    */
4965 /*                                                           6.1          */
4966 /*  AUTHOR                                                                */
4967 /*                                                                        */
4968 /*    Yuxin Zhou, Microsoft Corporation                                   */
4969 /*                                                                        */
4970 /*  DESCRIPTION                                                           */
4971 /*                                                                        */
4972 /*    This function adds the mDNS A/AAAA resource record into local cache.*/
4973 /*                                                                        */
4974 /*  INPUT                                                                 */
4975 /*                                                                        */
4976 /*    mdns_ptr                              Pointer to mDNS instance      */
4977 /*    set                                   The resource record set       */
4978 /*    address                               The resource record address   */
4979 /*    insert_rr                             Pointer to insert resource    */
4980 /*                                            record                      */
4981 /*    name                                  Host name                     */
4982 /*    ttl                                   The resource record ttl       */
4983 /*                                                                        */
4984 /*  OUTPUT                                                                */
4985 /*                                                                        */
4986 /*    status                                Completion status             */
4987 /*                                                                        */
4988 /*  CALLS                                                                 */
4989 /*                                                                        */
4990 /*    tx_mutex_get                          Get the mDNS mutex            */
4991 /*    tx_mutex_put                          Put the mDNS mutex            */
4992 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
4993 /*    _nx_mdns_cache_add_string             Add the string into cache     */
4994 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
4995 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
4996 /*                                            into cache                  */
4997 /*                                                                        */
4998 /*  CALLED BY                                                             */
4999 /*                                                                        */
5000 /*    _nx_mdns_host_name_register           Register the host name        */
5001 /*                                                                        */
5002 /*  RELEASE HISTORY                                                       */
5003 /*                                                                        */
5004 /*    DATE              NAME                      DESCRIPTION             */
5005 /*                                                                        */
5006 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5007 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5008 /*                                            resulting in version 6.1    */
5009 /*                                                                        */
5010 /**************************************************************************/
_nx_mdns_rr_a_aaaa_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG * address,UINT addr_length,UCHAR type,UINT interface_index)5011 static UINT _nx_mdns_rr_a_aaaa_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG *address, UINT addr_length, UCHAR type, UINT interface_index)
5012 {
5013 UINT        status;
5014 NX_MDNS_RR *insert_rr;
5015 USHORT      rr_type;
5016 NX_MDNS_RR  temp_resource_record;
5017 
5018 
5019     /* Set the resource record type.  */
5020     if(addr_length == 4)
5021         rr_type = NX_MDNS_RR_TYPE_A;
5022     else
5023         rr_type = NX_MDNS_RR_TYPE_AAAA;
5024 
5025     /* Set the resource record parameters.  */
5026     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, rr_type, NX_MDNS_RR_TTL_HOST, addr_length, NX_MDNS_RR_SET_UNIQUE, type, NX_FALSE, &temp_resource_record, interface_index);
5027 
5028     /* Check for error.  */
5029     if (status)
5030     {
5031         return(status);
5032     }
5033 
5034     /* Add the parameters.  */
5035     if(rr_type == NX_MDNS_RR_TYPE_A)
5036     {
5037         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = *address;
5038     }
5039     else
5040     {
5041         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = *address;
5042         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = *(address +1);
5043         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = *(address + 2);
5044         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = *(address + 3);
5045     }
5046 
5047     /* Add the resource record.  */
5048     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5049 
5050     /* Check for error.  */
5051     if (status)
5052     {
5053 
5054         /* Delete the name strings. */
5055         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5056         return(status);
5057     }
5058 
5059     /* Set the mDNS timer.  */
5060     _nx_mdns_timer_set(mdns_ptr, insert_rr, insert_rr -> nx_mdns_rr_timer_count);
5061 
5062     /* Return a successful status.  */
5063     return(NX_SUCCESS);
5064 }
5065 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
5066 
5067 
5068 /**************************************************************************/
5069 /*                                                                        */
5070 /*  FUNCTION                                               RELEASE        */
5071 /*                                                                        */
5072 /*    _nx_mdns_rr_ptr_add                                 PORTABLE C      */
5073 /*                                                           6.1          */
5074 /*  AUTHOR                                                                */
5075 /*                                                                        */
5076 /*    Yuxin Zhou, Microsoft Corporation                                   */
5077 /*                                                                        */
5078 /*  DESCRIPTION                                                           */
5079 /*                                                                        */
5080 /*    This function adds the mDNS PTR resource record into local buffer.  */
5081 /*                                                                        */
5082 /*  INPUT                                                                 */
5083 /*                                                                        */
5084 /*    mdns_ptr                              Pointer to mDNS instance      */
5085 /*    name                                  The resource record name      */
5086 /*    ttl                                   The resource record ttl       */
5087 /*    set                                   The resource record set       */
5088 /*    ptr_name                              The domain name               */
5089 /*    insert_rr                             Pointer to insert resource    */
5090 /*                                            record                      */
5091 /*                                                                        */
5092 /*  OUTPUT                                                                */
5093 /*                                                                        */
5094 /*    status                                Completion status             */
5095 /*                                                                        */
5096 /*  CALLS                                                                 */
5097 /*                                                                        */
5098 /*    tx_mutex_get                          Get the mDNS mutex            */
5099 /*    tx_mutex_put                          Put the mDNS mutex            */
5100 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5101 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5102 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5103 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5104 /*                                            into cache                  */
5105 /*                                                                        */
5106 /*  CALLED BY                                                             */
5107 /*                                                                        */
5108 /*    Application Code                                                    */
5109 /*                                                                        */
5110 /*  RELEASE HISTORY                                                       */
5111 /*                                                                        */
5112 /*    DATE              NAME                      DESCRIPTION             */
5113 /*                                                                        */
5114 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5115 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5116 /*                                            resulting in version 6.1    */
5117 /*                                                                        */
5118 /**************************************************************************/
_nx_mdns_rr_ptr_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * ptr_name,UCHAR is_valid,NX_MDNS_RR ** insert_rr,UINT interface_index)5119 static UINT _nx_mdns_rr_ptr_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *ptr_name, UCHAR is_valid, NX_MDNS_RR **insert_rr, UINT interface_index)
5120 {
5121 
5122 UINT        status;
5123 NX_MDNS_RR  *ptr_rr;
5124 NX_MDNS_RR  temp_resource_record;
5125 UINT        ptr_name_length;
5126 
5127 
5128     if (_nx_utility_string_length_check((CHAR *)ptr_name, &ptr_name_length, NX_MDNS_NAME_MAX))
5129     {
5130         return (NX_MDNS_DATA_SIZE_ERROR);
5131     }
5132 
5133     /* Get the mDNS mutex.  */
5134     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5135 
5136     /* Set the resource record parameters. Rdata length: PTR name, string should include the first'.' and last '\0'.  */
5137     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_PTR, ttl, (ptr_name_length + 2), set, NX_TRUE, is_valid, &temp_resource_record, interface_index);
5138 
5139     /* Check for error.  */
5140     if (status)
5141     {
5142 
5143         /* Release the mDNS mutex.  */
5144         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5145 
5146         return(status);
5147     }
5148 
5149     /* Add the ptr name.  */
5150     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, ptr_name, ptr_name_length,
5151                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name),
5152                                        NX_FALSE, NX_TRUE);
5153 
5154     /* Check for error.  */
5155     if (status)
5156     {
5157 
5158         /* Delete the strings. */
5159         _nx_mdns_cache_delete_string(mdns_ptr,  NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5160 
5161         /* Release the mDNS mutex.  */
5162         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5163 
5164         return(status);
5165     }
5166 
5167     /* Add the resource record.  */
5168     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &ptr_rr, NX_NULL);
5169 
5170     /* Check for error.  */
5171     if (status)
5172     {
5173 
5174         /* Delete the same strings. */
5175         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5176 
5177         /* Delete the same strings. */
5178         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, 0);
5179 
5180         /* Release the mDNS mutex.  */
5181         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5182 
5183         return(status);
5184     }
5185 
5186     /* Set the mDNS timer.  */
5187     _nx_mdns_timer_set(mdns_ptr, ptr_rr, ptr_rr -> nx_mdns_rr_timer_count);
5188 
5189     if (insert_rr)
5190         *insert_rr = ptr_rr;
5191 
5192     /* Release the mDNS mutex.  */
5193     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5194 
5195     /* Return a successful status.  */
5196     return(NX_SUCCESS);
5197 }
5198 
5199 
5200 /**************************************************************************/
5201 /*                                                                        */
5202 /*  FUNCTION                                               RELEASE        */
5203 /*                                                                        */
5204 /*    _nx_mdns_rr_srv_add                                 PORTABLE C      */
5205 /*                                                           6.1          */
5206 /*  AUTHOR                                                                */
5207 /*                                                                        */
5208 /*    Yuxin Zhou, Microsoft Corporation                                   */
5209 /*                                                                        */
5210 /*  DESCRIPTION                                                           */
5211 /*                                                                        */
5212 /*    This function adds the mDNS SRV resource record into local buffer.  */
5213 /*                                                                        */
5214 /*  INPUT                                                                 */
5215 /*                                                                        */
5216 /*    mdns_ptr                              Pointer to mDNS instance      */
5217 /*    name                                  Service nstance name          */
5218 /*    ttl                                   The ttl of the service        */
5219 /*    set                                   The resource record set       */
5220 /*    priority                              The priority of target host   */
5221 /*    weights                               Service weight                */
5222 /*    port                                  The port on this target host  */
5223 /*    target                                The target host               */
5224 /*    insert_rr                             Pointer to insert record      */
5225 /*                                                                        */
5226 /*  OUTPUT                                                                */
5227 /*                                                                        */
5228 /*    status                                Completion status             */
5229 /*                                                                        */
5230 /*  CALLS                                                                 */
5231 /*                                                                        */
5232 /*    tx_mutex_get                          Get the mDNS mutex            */
5233 /*    tx_mutex_put                          Put the mDNS mutex            */
5234 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5235 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5236 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5237 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5238 /*                                            into cache                  */
5239 /*                                                                        */
5240 /*  CALLED BY                                                             */
5241 /*                                                                        */
5242 /*    Application Code                                                    */
5243 /*                                                                        */
5244 /*  RELEASE HISTORY                                                       */
5245 /*                                                                        */
5246 /*    DATE              NAME                      DESCRIPTION             */
5247 /*                                                                        */
5248 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5249 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5250 /*                                            resulting in version 6.1    */
5251 /*                                                                        */
5252 /**************************************************************************/
_nx_mdns_rr_srv_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,USHORT priority,USHORT weights,USHORT port,UCHAR * target,NX_MDNS_RR ** insert_rr,UINT interface_index)5253 static UINT _nx_mdns_rr_srv_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, USHORT priority,
5254                                 USHORT weights, USHORT port, UCHAR *target, NX_MDNS_RR **insert_rr, UINT interface_index)
5255 {
5256 
5257 UINT        status;
5258 NX_MDNS_RR  *srv_rr;
5259 NX_MDNS_RR  temp_resource_record;
5260 UINT        target_length;
5261 
5262     if (_nx_utility_string_length_check((CHAR *)target, &target_length, NX_MDNS_NAME_MAX))
5263     {
5264         return (NX_MDNS_DATA_SIZE_ERROR);
5265     }
5266 
5267     /* Get the mDNS mutex.  */
5268     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5269 
5270     /* Set the resource record parameters. Rdata length: PRIORITY, WEIGHTS, PORT, TARGET, name string should include the first'.' and last '\0'.  */
5271     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_SRV, ttl, target_length + 8, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5272 
5273     /* Check for error.  */
5274     if (status)
5275     {
5276         /* Release the mDNS mutex.  */
5277         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5278 
5279         return(status);
5280     }
5281 
5282     /* Add the name.  */
5283     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, target, target_length,
5284                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
5285                                        NX_FALSE, NX_TRUE);
5286 
5287     /* Check for error.  */
5288     if (status)
5289     {
5290 
5291         /* Delete the same strings. */
5292         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5293 
5294         /* Release the mDNS mutex.  */
5295         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5296 
5297         return(status);
5298     }
5299 
5300     /* Set the SRV parameters.  */
5301     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = priority;
5302     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = weights;
5303     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = port;
5304 
5305     /* Add the resource record.  */
5306     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &srv_rr, NX_NULL);
5307 
5308     /* Check for error.  */
5309     if (status)
5310     {
5311         /* Delete the same strings. */
5312         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5313 
5314         /* Delete the same strings. */
5315         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
5316 
5317         /* Release the mDNS mutex.  */
5318         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5319 
5320         return(status);
5321     }
5322 
5323     /* Set the mDNS timer.  */
5324     _nx_mdns_timer_set(mdns_ptr, srv_rr, srv_rr -> nx_mdns_rr_timer_count);
5325 
5326     if (insert_rr)
5327         *insert_rr = srv_rr;
5328 
5329     /* Release the mDNS mutex.  */
5330     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5331 
5332     /* Return a successful status.  */
5333     return(NX_SUCCESS);
5334 }
5335 
5336 
5337 /**************************************************************************/
5338 /*                                                                        */
5339 /*  FUNCTION                                               RELEASE        */
5340 /*                                                                        */
5341 /*    _nx_mdns_rr_txt_add                                 PORTABLE C      */
5342 /*                                                           6.1          */
5343 /*  AUTHOR                                                                */
5344 /*                                                                        */
5345 /*    Yuxin Zhou, Microsoft Corporation                                   */
5346 /*                                                                        */
5347 /*  DESCRIPTION                                                           */
5348 /*                                                                        */
5349 /*    This function adds the mDNS TXT resource record into local buffer.  */
5350 /*    the TXT records are formatted in a "key=value" notation with ";"    */
5351 /*    acting as separator when more then one key is available.            */
5352 /*                                                                        */
5353 /*  INPUT                                                                 */
5354 /*                                                                        */
5355 /*    mdns_ptr                              Pointer to mDNS instance      */
5356 /*    name                                  The resource record name      */
5357 /*    ttl                                   The resource record ttl       */
5358 /*    set                                   The resource record set       */
5359 /*    txt                                   The txt string                */
5360 /*    insert_rr                             Pointer to insert record      */
5361 /*                                                                        */
5362 /*  OUTPUT                                                                */
5363 /*                                                                        */
5364 /*    status                                Completion status             */
5365 /*                                                                        */
5366 /*  CALLS                                                                 */
5367 /*                                                                        */
5368 /*    tx_mutex_get                          Get the mDNS mutex            */
5369 /*    tx_mutex_put                          Put the mDNS mutex            */
5370 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5371 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5372 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5373 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5374 /*                                            into the cache              */
5375 /*                                                                        */
5376 /*  CALLED BY                                                             */
5377 /*                                                                        */
5378 /*    Application Code                                                    */
5379 /*                                                                        */
5380 /*  RELEASE HISTORY                                                       */
5381 /*                                                                        */
5382 /*    DATE              NAME                      DESCRIPTION             */
5383 /*                                                                        */
5384 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5385 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5386 /*                                            resulting in version 6.1    */
5387 /*                                                                        */
5388 /**************************************************************************/
_nx_mdns_rr_txt_add(NX_MDNS * mdns_ptr,UCHAR * name,ULONG ttl,UCHAR set,UCHAR * txt,NX_MDNS_RR ** insert_rr,UINT interface_index)5389 static UINT _nx_mdns_rr_txt_add(NX_MDNS *mdns_ptr, UCHAR *name, ULONG ttl, UCHAR set, UCHAR *txt, NX_MDNS_RR **insert_rr, UINT interface_index)
5390 {
5391 
5392 UINT        status;
5393 NX_MDNS_RR  *txt_rr;
5394 NX_MDNS_RR  temp_resource_record;
5395 UINT        txt_length;
5396 
5397 
5398     /* Get the mDNS mutex.  */
5399     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5400 
5401     /* Set the resource record parameters.  */
5402     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_TXT, ttl, 0, set, NX_TRUE, NX_FALSE, &temp_resource_record, interface_index);
5403 
5404     /* Check for error.  */
5405     if (status)
5406     {
5407         /* Release the mDNS mutex.  */
5408         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5409 
5410         return(status);
5411     }
5412 
5413     if (txt)
5414     {
5415 
5416         /* Check string length.  */
5417         if (_nx_utility_string_length_check((CHAR *)txt, &txt_length, NX_MDNS_NAME_MAX))
5418         {
5419 
5420             /* Release the mDNS mutex.  */
5421             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5422             return (NX_MDNS_DATA_SIZE_ERROR);
5423         }
5424 
5425         /* Calculate the text string.inlcude the one byte label.  */
5426         temp_resource_record.nx_mdns_rr_rdata_length = (USHORT)(txt_length + 1);
5427 
5428         /* Add the name.  */
5429         status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, txt, txt_length,
5430                                            (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data),
5431                                            NX_FALSE, NX_TRUE);
5432 
5433         /* Check for error.  */
5434         if (status)
5435         {
5436 
5437             /* Delete the same strings. */
5438             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5439 
5440             /* Release the mDNS mutex.  */
5441             tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5442 
5443             return(status);
5444         }
5445     }
5446     else
5447     {
5448         temp_resource_record.nx_mdns_rr_rdata_length = 1;
5449         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = NX_NULL;
5450     }
5451 
5452     /* Add the resource record.  */
5453     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &txt_rr, NX_NULL);
5454 
5455     /* Check for error.  */
5456     if (status)
5457     {
5458 
5459         /* Delete the same strings. */
5460         _nx_mdns_cache_delete_string(mdns_ptr,NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5461 
5462         if (txt)
5463         {
5464 
5465             /* Delete the same strings. */
5466             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data, 0);
5467         }
5468 
5469         /* Release the mDNS mutex.  */
5470         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5471 
5472         return(status);
5473     }
5474 
5475     /* Set the mDNS timer.  */
5476     _nx_mdns_timer_set(mdns_ptr, txt_rr, txt_rr -> nx_mdns_rr_timer_count);
5477 
5478     if (insert_rr)
5479         *insert_rr = txt_rr;
5480 
5481     /* Release the mDNS mutex.  */
5482     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5483 
5484     /* Return a successful status.  */
5485     return(NX_SUCCESS);
5486 }
5487 
5488 
5489 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
5490 /**************************************************************************/
5491 /*                                                                        */
5492 /*  FUNCTION                                               RELEASE        */
5493 /*                                                                        */
5494 /*    _nx_mdns_rr_nsec_add                                  PORTABLE C    */
5495 /*                                                           6.1          */
5496 /*  AUTHOR                                                                */
5497 /*                                                                        */
5498 /*    Yuxin Zhou, Microsoft Corporation                                   */
5499 /*                                                                        */
5500 /*  DESCRIPTION                                                           */
5501 /*                                                                        */
5502 /*    This function adds the mDNS A resource record into local cache.     */
5503 /*                                                                        */
5504 /*  INPUT                                                                 */
5505 /*                                                                        */
5506 /*    mdns_ptr                              Pointer to mDNS instance      */
5507 /*    name                                  The resource record name      */
5508 /*    add_a                                 Flag for adding A record      */
5509 /*    add_aaaa                              Flag for adding AAAA record   */
5510 /*    type                                  Type for host or service      */
5511 /*                                                                        */
5512 /*  OUTPUT                                                                */
5513 /*                                                                        */
5514 /*    status                                Completion status             */
5515 /*                                                                        */
5516 /*  CALLS                                                                 */
5517 /*                                                                        */
5518 /*    tx_mutex_get                          Get the mDNS mutex            */
5519 /*    tx_mutex_put                          Put the mDNS mutex            */
5520 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5521 /*    _nx_mdns_cache_add_string             Add the string into cache     */
5522 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
5523 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
5524 /*                                            into cache                  */
5525 /*                                                                        */
5526 /*  CALLED BY                                                             */
5527 /*                                                                        */
5528 /*    _nx_mdns_host_name_register           Register the host name        */
5529 /*                                                                        */
5530 /*  RELEASE HISTORY                                                       */
5531 /*                                                                        */
5532 /*    DATE              NAME                      DESCRIPTION             */
5533 /*                                                                        */
5534 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5535 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5536 /*                                            resulting in version 6.1    */
5537 /*                                                                        */
5538 /**************************************************************************/
_nx_mdns_rr_nsec_add(NX_MDNS * mdns_ptr,UCHAR * name,UCHAR add_a,UCHAR add_aaaa,UCHAR type,UINT interface_index)5539 static UINT _nx_mdns_rr_nsec_add(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR add_a, UCHAR add_aaaa, UCHAR type, UINT interface_index)
5540 {
5541 UINT        status;
5542 NX_MDNS_RR *insert_rr;
5543 UCHAR       bitmap_length = 0;
5544 ULONG       rdata_length = 0;
5545 NX_MDNS_RR  temp_resource_record;
5546 UINT        name_length;
5547 
5548 
5549     /* Check string length.  */
5550     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5551     {
5552         return (NX_MDNS_DATA_SIZE_ERROR);
5553     }
5554 
5555     /* Add the next domain name, include the first'.' and last '\0'.  */
5556     rdata_length = name_length + 2;
5557 
5558     /* Add the window block and bitmap length.  */
5559     rdata_length += 2;
5560 
5561     /* Add the NSEC with A/AAAA Bitmap.  */
5562     if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5563     {
5564         /* Set the Bitmaps length.  */
5565         if (add_aaaa == NX_TRUE)
5566             bitmap_length = 4;
5567         else
5568             bitmap_length = 1;
5569     }
5570     else
5571     {
5572 
5573         /* Add the NSEC with SRV/TXT Bitmap.   */
5574         bitmap_length = 5;
5575     }
5576 
5577     /* Add the Bitmaps.  */
5578     rdata_length += bitmap_length;
5579 
5580     /* Set the resource record parameters.  */
5581     status = _nx_mdns_rr_parameter_set(mdns_ptr, name, NX_MDNS_RR_TYPE_NSEC, NX_MDNS_RR_TTL_HOST, rdata_length,
5582                                        NX_MDNS_RR_SET_UNIQUE, NX_FALSE, NX_TRUE, &temp_resource_record, interface_index);
5583 
5584     /* Check for error.  */
5585     if (status)
5586     {
5587         return(status);
5588     }
5589 
5590     /* Add the next domain name.  */
5591     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5592                                        (VOID **)(&temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain),
5593                                        NX_FALSE, NX_TRUE);
5594 
5595     /* Check for error.  */
5596     if (status)
5597     {
5598         /* Delete the same strings. */
5599         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5600 
5601         return(status);
5602     }
5603 
5604     /* Set the window block and bitmap length.  */
5605     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block = 0;
5606     temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length = bitmap_length;
5607 
5608     /* Add the Bitmap for host.  */
5609     if (type == NX_MDNS_ADD_NSEC_FOR_HOST)
5610     {
5611 
5612         /* Encode the Bitmap.  */
5613         if ((add_a == NX_TRUE) && (add_aaaa == NX_TRUE))
5614         {
5615 
5616             /* Add the A Bitmap.  */
5617             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5618 
5619             /* Add the AAAA Bitmap.  */
5620             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5621         }
5622         else if ((add_a == NX_TRUE))
5623         {
5624 
5625             /* Add the A Bit map.  */
5626             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0] = 64;
5627         }
5628         else
5629         {
5630 
5631             /* Add the AAAA Bitmap.  */
5632             temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[3] = 8;
5633         }
5634     }
5635     else
5636     {
5637         /* Add the TXT Bitmap for service.  */
5638         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[2] =  128;
5639 
5640         /* Add the SRV Bitmap for service.  */
5641         temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[4] =  64;
5642 
5643     }
5644 
5645     /* Add the resource record.  */
5646     status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, &insert_rr, NX_NULL);
5647 
5648     /* Check for error.  */
5649     if (status)
5650     {
5651         /* Delete the same strings. */
5652         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_name, 0);
5653 
5654         /* Delete the same strings. */
5655         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, temp_resource_record.nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain, 0);
5656 
5657         return(status);
5658     }
5659 
5660     /* Return a successful status.  */
5661     return(NX_SUCCESS);
5662 }
5663 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
5664 
5665 
5666 /**************************************************************************/
5667 /*                                                                        */
5668 /*  FUNCTION                                               RELEASE        */
5669 /*                                                                        */
5670 /*    _nx_mdns_rr_parameter_set                           PORTABLE C      */
5671 /*                                                           6.1.11       */
5672 /*  AUTHOR                                                                */
5673 /*                                                                        */
5674 /*    Yuxin Zhou, Microsoft Corporation                                   */
5675 /*                                                                        */
5676 /*  DESCRIPTION                                                           */
5677 /*                                                                        */
5678 /*    This function sets the parameters of resource record.               */
5679 /*                                                                        */
5680 /*  INPUT                                                                 */
5681 /*                                                                        */
5682 /*    mdns_ptr                              Pointer to mDNS instance      */
5683 /*    name                                  The resource record name      */
5684 /*    type                                  The resource record type      */
5685 /*    ttl                                   The resource record ttl       */
5686 /*    rdata_lenth                           The resource record length    */
5687 /*    set                                   The resource record set       */
5688 /*    is_register                           Register flag                 */
5689 /*    is_valid                              Valid flag                    */
5690 /*    rr_record                             Pointer to resource record    */
5691 /*                                                                        */
5692 /*  OUTPUT                                                                */
5693 /*                                                                        */
5694 /*    status                                Completion status             */
5695 /*                                                                        */
5696 /*  CALLS                                                                 */
5697 /*                                                                        */
5698 /*    None                                                                */
5699 /*                                                                        */
5700 /*  CALLED BY                                                             */
5701 /*                                                                        */
5702 /*    Application Code                                                    */
5703 /*                                                                        */
5704 /*  RELEASE HISTORY                                                       */
5705 /*                                                                        */
5706 /*    DATE              NAME                      DESCRIPTION             */
5707 /*                                                                        */
5708 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5709 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5710 /*                                            resulting in version 6.1    */
5711 /*  04-25-2022     Yuxin Zhou               Modified comment(s),          */
5712 /*                                            fixed the issue of timer,   */
5713 /*                                            resulting in version 6.1.11 */
5714 /*                                                                        */
5715 /**************************************************************************/
_nx_mdns_rr_parameter_set(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,ULONG ttl,UINT rdata_length,UCHAR set,UCHAR is_register,UCHAR is_valid,NX_MDNS_RR * rr_record,UINT interface_index)5716 static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length,
5717                                       UCHAR set, UCHAR is_register, UCHAR is_valid, NX_MDNS_RR *rr_record, UINT interface_index)
5718 {
5719 
5720 UINT        status;
5721 UINT        name_length;
5722 
5723 
5724     /* Check string length.  */
5725     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
5726     {
5727         return (NX_MDNS_DATA_SIZE_ERROR);
5728     }
5729 
5730     /* Initialize the struct.  */
5731     memset(rr_record, 0, sizeof(NX_MDNS_RR));
5732 
5733     /* Add the name.  */
5734     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, name, name_length,
5735                                        (VOID **)(&rr_record -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
5736 
5737     /* Check for error.  */
5738     if (status)
5739         return(status);
5740 
5741     /* Set the parameters.  */
5742     rr_record -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
5743     rr_record -> nx_mdns_rr_type = type;
5744     rr_record -> nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN;
5745     rr_record -> nx_mdns_rr_ttl = ttl;
5746     rr_record -> nx_mdns_rr_rdata_length = (USHORT)rdata_length;
5747 
5748     /* Set the resource record as uniqure.  */
5749     if (set == NX_MDNS_RR_SET_UNIQUE)
5750         rr_record -> nx_mdns_rr_word = (rr_record -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_UNIQUE);
5751 
5752     /* Check for mDNS started flag.  */
5753     if (mdns_ptr -> nx_mdns_started)
5754     {
5755 
5756         /* Check the valid flag for PTR resource record.  */
5757         if (is_valid == NX_TRUE)
5758         {
5759             /* Set the resource record state.  */
5760             rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
5761         }
5762         else
5763         {
5764 
5765             /* The is_register value be used for A/AAAA type, the value being NX_TRUE indicates the operation is to register the host name(probing and announcing the A/AAAA). The value being NX_FALSE indicates the operation is an address change, (announcing the A/AAAA).  */
5766             if ((set == NX_MDNS_RR_SET_UNIQUE) && (is_register == NX_TRUE))
5767             {
5768 
5769                 /* Set the resource record status.  */
5770                 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
5771                 rr_record -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
5772                 rr_record -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
5773             }
5774             else
5775             {
5776 
5777                 /* Set the resource record state.  */
5778                 rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
5779                 rr_record -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
5780                 rr_record -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
5781 
5782                 /* Check the announcing max time.  */
5783                 if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
5784                     rr_record -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
5785                 else
5786                     rr_record -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
5787 
5788                 /* Set the retransmit count.  */
5789                 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
5790                     rr_record -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
5791                 else
5792                     rr_record -> nx_mdns_rr_retransmit_count = 1;
5793             }
5794         }
5795     }
5796     else
5797     {
5798 
5799         /* Set the resource record status.  */
5800         rr_record -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
5801     }
5802 
5803     return(NX_MDNS_SUCCESS);
5804 }
5805 #endif /* NX_MDNS_DISABLE_SERVER */
5806 
5807 
5808 /**************************************************************************/
5809 /*                                                                        */
5810 /*  FUNCTION                                               RELEASE        */
5811 /*                                                                        */
5812 /*    _nx_mdns_rr_delete                                  PORTABLE C      */
5813 /*                                                           6.1          */
5814 /*  AUTHOR                                                                */
5815 /*                                                                        */
5816 /*    Yuxin Zhou, Microsoft Corporation                                   */
5817 /*                                                                        */
5818 /*  DESCRIPTION                                                           */
5819 /*                                                                        */
5820 /*    This function deletes the mDNS resource record from the             */
5821 /*    local bufferor remote buffer according to the resource record set.  */
5822 /*                                                                        */
5823 /*  INPUT                                                                 */
5824 /*                                                                        */
5825 /*    mdns_ptr                              Pointer to mDNS instance      */
5826 /*    record_rr                             The resource record           */
5827 /*                                                                        */
5828 /*  OUTPUT                                                                */
5829 /*                                                                        */
5830 /*    status                                Completion status             */
5831 /*                                                                        */
5832 /*  CALLS                                                                 */
5833 /*                                                                        */
5834 /*    tx_mutex_get                          Get the mDNS mutex            */
5835 /*    tx_mutex_put                          Put the mDNS mutex            */
5836 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
5837 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
5838 /*                                            from cache                  */
5839 /*                                                                        */
5840 /*  CALLED BY                                                             */
5841 /*                                                                        */
5842 /*    Application Code                                                    */
5843 /*                                                                        */
5844 /*  RELEASE HISTORY                                                       */
5845 /*                                                                        */
5846 /*    DATE              NAME                      DESCRIPTION             */
5847 /*                                                                        */
5848 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5849 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5850 /*                                            resulting in version 6.1    */
5851 /*                                                                        */
5852 /**************************************************************************/
_nx_mdns_rr_delete(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)5853 static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
5854 {
5855 
5856 UINT        status = NX_MDNS_SUCCESS;
5857 
5858 #ifndef NX_MDNS_DISABLE_CLIENT
5859 ULONG       *head;
5860 NX_MDNS_RR  *p;
5861 #endif /* NX_MDNS_DISABLE_CLIENT */
5862 
5863     /* Get the mDNS mutex.  */
5864     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
5865 
5866 
5867     /* Check for mDNS started flag.  */
5868     if (mdns_ptr -> nx_mdns_started)
5869     {
5870 
5871         /* Check the RR owner.  */
5872         if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5873         {
5874 
5875 #ifndef NX_MDNS_DISABLE_SERVER
5876             if ((record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
5877                 (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
5878             {
5879 
5880                 /* Set the state to send Goodbye packet.  */
5881                 record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
5882 
5883                 /* Set the retransmit count.  */
5884                 record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
5885 
5886                 /* Set the timer count.  */
5887                 record_rr -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
5888 
5889                 /* Set the delete flag.  */
5890                 record_rr -> nx_mdns_rr_word = (record_rr -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
5891 
5892                 /* Set the mDNS timer.  */
5893                 _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
5894             }
5895             else
5896             {
5897 
5898                 /* Delete the resource records.  */
5899                 status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5900             }
5901 
5902 #endif /* NX_MDNS_DISABLE_SERVER */
5903         }
5904         else
5905         {
5906 
5907 #ifndef NX_MDNS_DISABLE_CLIENT
5908             if (record_rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
5909             {
5910 
5911                 /* Set the pointer.  */
5912                 head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
5913 
5914                 if(head)
5915                 {
5916                     head = (ULONG*)(*head);
5917 
5918                     /* Check the remote resource record, stop the updating resource record.  */
5919                     for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
5920                     {
5921 
5922                         if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
5923                             continue;
5924 
5925                         if (p == record_rr)
5926                             continue;
5927 
5928                         if ((p -> nx_mdns_rr_name  == record_rr -> nx_mdns_rr_name) &&
5929                             (p -> nx_mdns_rr_type == record_rr -> nx_mdns_rr_type) &&
5930                             (p -> nx_mdns_rr_class == record_rr -> nx_mdns_rr_class))
5931                         {
5932 
5933                             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)
5934                             {
5935 
5936                                 /* Clear the Updating flag.  */
5937                                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_UPDATING));
5938                             }
5939 
5940                             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
5941                             {
5942                                 if (p -> nx_mdns_rr_retransmit_count)
5943                                 {
5944 
5945                                     /* mDNS querier need not update the RR, The original updating ttl is at 80%, 85%, 90%, 95%. Update the timer.*/
5946                                     /* timer_count: P, timer_count: C, rr_ttl: T.
5947                                     P = P + C * T * 5%.  */
5948                                     p -> nx_mdns_rr_timer_count = (p -> nx_mdns_rr_timer_count + p -> nx_mdns_rr_retransmit_count * p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 /100);
5949 
5950                                     /* Clear the retransmit count.  */
5951                                     p -> nx_mdns_rr_retransmit_count = 0;
5952 
5953                                     /* Set the mDNS timer.  */
5954                                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
5955                                 }
5956                             }
5957                         }
5958                     }
5959                 }
5960             }
5961 
5962             /* Delete the resource record.  */
5963             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5964 
5965 #endif /* NX_MDNS_DISABLE_CLIENT */
5966         }
5967     }
5968     else
5969     {
5970         /* Check the RR owner.  */
5971         if (!(record_rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER))
5972         {
5973 
5974 #ifndef NX_MDNS_DISABLE_SERVER
5975             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, record_rr);
5976 #endif /* NX_MDNS_DISABLE_SERVER  */
5977         }
5978         else
5979         {
5980 
5981 #ifndef NX_MDNS_DISABLE_CLIENT
5982             status = _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, record_rr);
5983 #endif /* NX_MDNS_DISABLE_CLIENT  */
5984         }
5985     }
5986 
5987     /* Release the mDNS mutex.  */
5988     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
5989 
5990     /* Return status.  */
5991     return (status);
5992 }
5993 
5994 
5995 #ifndef NX_MDNS_DISABLE_SERVER
5996 /**************************************************************************/
5997 /*                                                                        */
5998 /*  FUNCTION                                               RELEASE        */
5999 /*                                                                        */
6000 /*    _nx_mdns_local_cache_clear                            PORTABLE C    */
6001 /*                                                           6.1          */
6002 /*  AUTHOR                                                                */
6003 /*                                                                        */
6004 /*    Yuxin Zhou, Microsoft Corporation                                   */
6005 /*                                                                        */
6006 /*  DESCRIPTION                                                           */
6007 /*                                                                        */
6008 /*    This function deletes the mDNS instance.                            */
6009 /*                                                                        */
6010 /*  INPUT                                                                 */
6011 /*                                                                        */
6012 /*    mdns_ptr                              Pointer to mDNS instance      */
6013 /*                                                                        */
6014 /*  OUTPUT                                                                */
6015 /*                                                                        */
6016 /*    status                                Completion status             */
6017 /*                                                                        */
6018 /*  CALLS                                                                 */
6019 /*                                                                        */
6020 /*    _nx_mdns_local_cache_clear            Actual local cache clear      */
6021 /*                                            function                    */
6022 /*                                                                        */
6023 /*  CALLED BY                                                             */
6024 /*                                                                        */
6025 /*    Application Code                                                    */
6026 /*                                                                        */
6027 /*  RELEASE HISTORY                                                       */
6028 /*                                                                        */
6029 /*    DATE              NAME                      DESCRIPTION             */
6030 /*                                                                        */
6031 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6032 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6033 /*                                            resulting in version 6.1    */
6034 /*                                                                        */
6035 /**************************************************************************/
_nxe_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6036 UINT _nxe_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6037 {
6038 
6039 UINT    status;
6040 
6041 
6042     /* Check for invalid input pointers.  */
6043     if (!mdns_ptr)
6044     {
6045         return(NX_PTR_ERROR);
6046     }
6047 
6048     /* Check for invalid server attributes. */
6049     if (mdns_ptr -> nx_mdns_id != NX_MDNS_ID)
6050     {
6051         return(NX_MDNS_PARAM_ERROR);
6052     }
6053 
6054     /* Call actual mDNS local cache clear service.  */
6055     status =  _nx_mdns_local_cache_clear(mdns_ptr);
6056 
6057     /* Return status.  */
6058     return(status);
6059 }
6060 
6061 
6062 /**************************************************************************/
6063 /*                                                                        */
6064 /*  FUNCTION                                               RELEASE        */
6065 /*                                                                        */
6066 /*    _nx_mdns_local_cache_clear                          PORTABLE C      */
6067 /*                                                           6.1          */
6068 /*  AUTHOR                                                                */
6069 /*                                                                        */
6070 /*    Yuxin Zhou, Microsoft Corporation                                   */
6071 /*                                                                        */
6072 /*  DESCRIPTION                                                           */
6073 /*                                                                        */
6074 /*    This function clears the mDNS local cache.                          */
6075 /*                                                                        */
6076 /*  INPUT                                                                 */
6077 /*                                                                        */
6078 /*    mdns_ptr                              Pointer to mDNS instance      */
6079 /*                                                                        */
6080 /*  OUTPUT                                                                */
6081 /*                                                                        */
6082 /*    status                                Completion status             */
6083 /*                                                                        */
6084 /*  CALLS                                                                 */
6085 /*                                                                        */
6086 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
6087 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
6088 /*                                            from cache                  */
6089 /*                                                                        */
6090 /*  CALLED BY                                                             */
6091 /*                                                                        */
6092 /*    Application Code                                                    */
6093 /*                                                                        */
6094 /*  RELEASE HISTORY                                                       */
6095 /*                                                                        */
6096 /*    DATE              NAME                      DESCRIPTION             */
6097 /*                                                                        */
6098 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6099 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6100 /*                                            resulting in version 6.1    */
6101 /*                                                                        */
6102 /**************************************************************************/
_nx_mdns_local_cache_clear(NX_MDNS * mdns_ptr)6103 UINT _nx_mdns_local_cache_clear(NX_MDNS *mdns_ptr)
6104 {
6105 
6106 UINT            status = NX_MDNS_SUCCESS;
6107 ULONG           *head;
6108 NX_MDNS_RR      *p;
6109 
6110 
6111     /* Get the mDNS mutex.  */
6112     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
6113 
6114     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6115     head = (ULONG*)(*head);
6116 
6117     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
6118     {
6119 
6120         /* Delete the resource records.  */
6121         status = _nx_mdns_rr_delete(mdns_ptr, p);
6122 
6123         /* Check the status.  */
6124         if (status)
6125             break;
6126     }
6127 
6128     /* Release the mDNS mutex.  */
6129     tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
6130 
6131     /* Return a successful status.  */
6132     return(status);
6133 }
6134 #endif /* NX_MDNS_DISABLE_SERVER  */
6135 
6136 
6137 /**************************************************************************/
6138 /*                                                                        */
6139 /*  FUNCTION                                               RELEASE        */
6140 /*                                                                        */
6141 /*    _nx_mdns_service_name_resolve                       PORTABLE C      */
6142 /*                                                           6.1          */
6143 /*  AUTHOR                                                                */
6144 /*                                                                        */
6145 /*    Yuxin Zhou, Microsoft Corporation                                   */
6146 /*                                                                        */
6147 /*  DESCRIPTION                                                           */
6148 /*                                                                        */
6149 /*    This function resloves the service name, type, domain.              */
6150 /*                                                                        */
6151 /*  INPUT                                                                 */
6152 /*                                                                        */
6153 /*    srv_name                              Pointer to SRV name           */
6154 /*    name                                  The name of the service       */
6155 /*    type                                  The type of to the service    */
6156 /*    domain                                The domain                    */
6157 /*                                                                        */
6158 /*  OUTPUT                                                                */
6159 /*                                                                        */
6160 /*    status                                Completion status             */
6161 /*                                                                        */
6162 /*  CALLS                                                                 */
6163 /*                                                                        */
6164 /*    tx_mutex_get                          Get the mDNS mutex            */
6165 /*    tx_mutex_put                          Put the mDNS mutex            */
6166 /*                                                                        */
6167 /*  CALLED BY                                                             */
6168 /*                                                                        */
6169 /*    mDNS component                                                      */
6170 /*                                                                        */
6171 /*  RELEASE HISTORY                                                       */
6172 /*                                                                        */
6173 /*    DATE              NAME                      DESCRIPTION             */
6174 /*                                                                        */
6175 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6176 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6177 /*                                            resulting in version 6.1    */
6178 /*                                                                        */
6179 /**************************************************************************/
_nx_mdns_service_name_resolve(UCHAR * srv_name,UCHAR ** name,UCHAR ** type,UCHAR ** domain)6180 static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain)
6181 {
6182 
6183 UINT    i;
6184 UINT    count;
6185 UINT    prepend_index;
6186 UINT    append_index;
6187 UINT    type_index;
6188 UINT    domain_index;
6189 UCHAR   *pointer;
6190 UINT     protocol_length;
6191 
6192 
6193     /* Initialize the parameters.  */
6194     count = 0;
6195     prepend_index = 0;
6196     append_index = 0;
6197     type_index = 0;
6198     domain_index = 0;
6199 
6200     /* Set the service name pointer.  */
6201     pointer = srv_name;
6202 
6203     /* Service Instance name,  */
6204     /* <Instance>.<sn>._tcp.<domain> :
6205        name: <Instance>
6206        type: <sn>._tcp
6207        domain: <domain>.  */
6208     while (*srv_name != '\0')
6209     {
6210 
6211         /* Update the index.  */
6212         append_index ++;
6213 
6214         if (*srv_name == '.')
6215         {
6216 
6217             /* Set the value.  */
6218             i = 0;
6219 
6220             while (nx_mdns_app_protocol[i])
6221             {
6222 
6223                 /* Check string length.  */
6224                 if (_nx_utility_string_length_check(nx_mdns_app_protocol[i], &protocol_length, NX_MDNS_TYPE_MAX))
6225                 {
6226                     continue;
6227                 }
6228 
6229                 /* Find the key string. "_tcp" , "_udp" etc.  */
6230                 if (!_nx_mdns_name_match(pointer + prepend_index, (UCHAR *)(nx_mdns_app_protocol[i]), protocol_length))
6231                 {
6232 
6233                     /* Get the <domain> pointer.  */
6234                     /* EL-PC.Test._http._tcp.local
6235                        type index pointer to the _http._tcp,
6236                        domain_index pointer to the local.  */
6237                     domain_index = append_index;
6238 
6239                     /* Set the name pointer.  */
6240                     if (type_index)
6241                     {
6242                         *name = pointer;
6243 
6244                         /* Set the trailing null of name.  */
6245                         *(pointer + type_index -1) = '\0';
6246                     }
6247                     else
6248                     {
6249                         *name = NX_NULL;
6250                     }
6251 
6252                     /* Set the type pointer.  */
6253                     *type = pointer + type_index;
6254 
6255                     /* Set the trailing null of type.  */
6256                     *(pointer + domain_index -1) = '\0';
6257 
6258                     /* Set the type pointer.  */
6259                     *domain = pointer + domain_index;
6260 
6261                     return(NX_MDNS_SUCCESS);
6262                 }
6263                 i ++;
6264             }
6265 
6266             /* Update the '.' count.  */
6267             count ++;
6268 
6269             /* The type index is pointer to the <sn>.  */
6270             if (count != 1)
6271             {
6272 
6273                 /* Update the type index.  */
6274                 type_index = prepend_index;
6275             }
6276 
6277             prepend_index = append_index;
6278         }
6279 
6280         srv_name ++;
6281     }
6282 
6283     return(NX_MDNS_ERROR);
6284 }
6285 
6286 
6287 /**************************************************************************/
6288 /*                                                                        */
6289 /*  FUNCTION                                               RELEASE        */
6290 /*                                                                        */
6291 /*    _nx_mdns_service_name_assemble                      PORTABLE C      */
6292 /*                                                           6.1          */
6293 /*  AUTHOR                                                                */
6294 /*                                                                        */
6295 /*    Yuxin Zhou, Microsoft Corporation                                   */
6296 /*                                                                        */
6297 /*  DESCRIPTION                                                           */
6298 /*                                                                        */
6299 /*    This function resloves the service name, type, domain.              */
6300 /*                                                                        */
6301 /*  INPUT                                                                 */
6302 /*                                                                        */
6303 /*    srv_name                              Pointer to SRV name           */
6304 /*    name                                  The name of the service       */
6305 /*    type                                  The type of to the service    */
6306 /*    domain                                The domain                    */
6307 /*                                                                        */
6308 /*  OUTPUT                                                                */
6309 /*                                                                        */
6310 /*    status                                Completion status             */
6311 /*                                                                        */
6312 /*  CALLS                                                                 */
6313 /*                                                                        */
6314 /*    tx_mutex_get                          Get the mDNS mutex            */
6315 /*    tx_mutex_put                          Put the mDNS mutex            */
6316 /*                                                                        */
6317 /*  CALLED BY                                                             */
6318 /*                                                                        */
6319 /*    mDNS component                                                      */
6320 /*                                                                        */
6321 /*  RELEASE HISTORY                                                       */
6322 /*                                                                        */
6323 /*    DATE              NAME                      DESCRIPTION             */
6324 /*                                                                        */
6325 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6326 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
6327 /*                                            buffer length verification, */
6328 /*                                            verified memcpy use cases,  */
6329 /*                                            resulting in version 6.1    */
6330 /*                                                                        */
6331 /**************************************************************************/
_nx_mdns_service_name_assemble(UCHAR * name,UCHAR * type,UCHAR * sub_type,UCHAR * domain,UCHAR * record_buffer,UINT buffer_size,UINT * type_index)6332 static UINT _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index)
6333 {
6334 
6335 UINT        index;
6336 UINT        length;
6337 
6338     /* Initialize the struct.  */
6339     index = 0;
6340     memset(record_buffer, 0, buffer_size);
6341     if (type_index)
6342     {
6343         *type_index = 0;
6344     }
6345 
6346     /* Construct the service name.  */
6347 
6348     /* Add the name.  */
6349     if (name)
6350     {
6351 
6352         /* Check string length.  */
6353         if (_nx_utility_string_length_check((CHAR *)name, &length, NX_MDNS_NAME_MAX))
6354         {
6355             return (NX_MDNS_DATA_SIZE_ERROR);
6356         }
6357 
6358         /* Verify buffer length. */
6359         if (index + length + 1 > buffer_size)
6360         {
6361             return (NX_MDNS_DATA_SIZE_ERROR);
6362         }
6363 
6364         memcpy((CHAR *)(record_buffer + index), (const char*)name, length); /* Use case of memcpy is verified. */
6365         index += length;
6366 
6367         *(record_buffer + index) = '.';
6368         index ++;
6369     }
6370 
6371     /* Add the sub type.  */
6372     if (sub_type)
6373     {
6374 
6375         /* Check string length.  */
6376         if (_nx_utility_string_length_check((CHAR *)sub_type, &length, NX_MDNS_LABEL_MAX))
6377         {
6378             return (NX_MDNS_DATA_SIZE_ERROR);
6379         }
6380 
6381         /* Verify buffer length. */
6382         if (index + length + 1 + 4 + 1 > buffer_size)
6383         {
6384             return (NX_MDNS_DATA_SIZE_ERROR);
6385         }
6386 
6387         if (type_index)
6388         {
6389             *type_index = index;
6390         }
6391         memcpy((CHAR *)(record_buffer + index), (const char*)sub_type, length); /* Use case of memcpy is verified. */
6392         index += length;
6393         *(record_buffer + index) = '.';
6394         index ++;
6395 
6396         /* Add the key word "_sub".  */
6397         memcpy((CHAR *)(record_buffer + index), (const char*)"_sub", 4); /* Use case of memcpy is verified. */
6398         index += 4;
6399         *(record_buffer + index) = '.';
6400         index ++;
6401     }
6402 
6403     /* Add the type.  */
6404     if (type)
6405     {
6406 
6407         /* Check string length.  */
6408         if (_nx_utility_string_length_check((CHAR *)type, &length, NX_MDNS_TYPE_MAX))
6409         {
6410             return (NX_MDNS_DATA_SIZE_ERROR);
6411         }
6412 
6413         /* Verify buffer length. */
6414         if (index + length + 1 > buffer_size)
6415         {
6416             return (NX_MDNS_DATA_SIZE_ERROR);
6417         }
6418 
6419         /* Set the type index.  */
6420         if ((type_index) &&
6421             (!sub_type))
6422         {
6423             *type_index = index;
6424         }
6425 
6426         memcpy((CHAR *)record_buffer + index, (const char*)type, length); /* Use case of memcpy is verified. */
6427         index += length;
6428         *(record_buffer + index) = '.';
6429         index ++;
6430     }
6431 
6432     /* Add the domain. */
6433     if (domain)
6434     {
6435 
6436         /* Check string length.  */
6437         if (_nx_utility_string_length_check((CHAR *)domain, &length, NX_MDNS_DOMAIN_NAME_MAX))
6438         {
6439             return (NX_MDNS_DATA_SIZE_ERROR);
6440         }
6441 
6442         /* Verify buffer length. */
6443         if (index + length > buffer_size)
6444         {
6445             return (NX_MDNS_DATA_SIZE_ERROR);
6446         }
6447 
6448         memcpy((CHAR *)(record_buffer + index), (const char*)domain, length); /* Use case of memcpy is verified. */
6449         index += length;
6450     }
6451 
6452     return(NX_MDNS_SUCCESS);
6453 }
6454 
6455 
6456 #ifndef NX_MDNS_DISABLE_SERVER
6457 /**************************************************************************/
6458 /*                                                                        */
6459 /*  FUNCTION                                               RELEASE        */
6460 /*                                                                        */
6461 /*    nx_mdns_host_name_register                          PORTABLE C      */
6462 /*                                                           6.1          */
6463 /*  AUTHOR                                                                */
6464 /*                                                                        */
6465 /*    Yuxin Zhou, Microsoft Corporation                                   */
6466 /*                                                                        */
6467 /*  DESCRIPTION                                                           */
6468 /*                                                                        */
6469 /*    This function resloves the service name, type, domain.              */
6470 /*                                                                        */
6471 /*  INPUT                                                                 */
6472 /*                                                                        */
6473 /*    mdns_ptr                              Pointer to mDNS instance      */
6474 /*    type                                  The type of operation         */
6475 /*    interface_index                       The interface index           */
6476 /*                                                                        */
6477 /*  OUTPUT                                                                */
6478 /*                                                                        */
6479 /*    status                                Completion status             */
6480 /*                                                                        */
6481 /*  CALLS                                                                 */
6482 /*                                                                        */
6483 /*    tx_mutex_get                          Get the mDNS mutex            */
6484 /*    tx_mutex_put                          Put the mDNS mutex            */
6485 /*    _nx_mdns_rr_a_aaaa_add                Add the A/AAAA resource record*/
6486 /*                                                                        */
6487 /*  CALLED BY                                                             */
6488 /*                                                                        */
6489 /*    _nx_mdns_enable                       Enable mDNS                   */
6490 /*    _nx_mdns_address_change_process       Process address change        */
6491 /*                                                                        */
6492 /*  RELEASE HISTORY                                                       */
6493 /*                                                                        */
6494 /*    DATE              NAME                      DESCRIPTION             */
6495 /*                                                                        */
6496 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6497 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
6498 /*                                            verified memcpy use cases,  */
6499 /*                                            resulting in version 6.1    */
6500 /*                                                                        */
6501 /**************************************************************************/
_nx_mdns_host_name_register(NX_MDNS * mdns_ptr,UCHAR type,UINT interface_index)6502 static UINT _nx_mdns_host_name_register(NX_MDNS *mdns_ptr, UCHAR type, UINT interface_index)
6503 {
6504 
6505 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
6506 UINT    status;
6507 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6 */
6508 NX_IP   *ip_ptr;
6509 UINT    index = 0;
6510 UCHAR   add_a = NX_FALSE;
6511 UCHAR   add_aaaa = NX_FALSE;
6512 UINT    host_name_length;
6513 
6514 #ifdef NX_MDNS_ENABLE_IPV6
6515 NXD_IPV6_ADDRESS *ipv6_address_ptr;
6516 #endif /* NX_MDNS_ENABLE_IPV6  */
6517 
6518 
6519 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
6520     NX_PARAMETER_NOT_USED(type);
6521 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6  */
6522 
6523     /* Check string length.  */
6524     if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_host_name, &host_name_length, NX_MDNS_HOST_NAME_MAX))
6525     {
6526         return (NX_MDNS_DATA_SIZE_ERROR);
6527     }
6528 
6529     /* Construct the A/AAAA name.  */
6530     memcpy((CHAR *)(&temp_string_buffer[index]), (const char*)mdns_ptr -> nx_mdns_host_name, host_name_length); /* Use case of memcpy is verified. */
6531     index += host_name_length;
6532 
6533     temp_string_buffer[index] = '.';
6534     index ++;
6535     memcpy((CHAR *)(&temp_string_buffer[index]), (CHAR *)"local", sizeof("local")); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h.*/
6536 
6537     /* Set the ip pointer.  */
6538     ip_ptr = mdns_ptr -> nx_mdns_ip_ptr;
6539 
6540     /* Get the IP mutex.  */
6541     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
6542 
6543 #ifndef NX_DISABLE_IPV4
6544     /* Add the A resource records message.  */
6545     if (ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address)
6546     {
6547 
6548         /* Add the A resource records message.  */
6549         status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], &(ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address),
6550                                         NX_MDNS_IPV4_ADDRESS_LENGTH, type, interface_index);
6551 
6552         /* Check the status.  */
6553         if (status)
6554         {
6555 
6556             /* Release the IP mutex.  */
6557             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6558 
6559             return(status);
6560         }
6561 
6562         /* Set the flag.  */
6563         add_a = NX_TRUE;
6564     }
6565 #endif /* NX_DISABLE_IPV4  */
6566 
6567 #ifdef NX_MDNS_ENABLE_IPV6
6568     /* Get the IPv6 address pointer.*/
6569     ipv6_address_ptr = ip_ptr -> nx_ip_interface[interface_index].nxd_interface_ipv6_address_list_head;
6570 
6571     while(ipv6_address_ptr)
6572     {
6573 
6574         if (ipv6_address_ptr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)
6575         {
6576 
6577             /* Add the AAAA resource records message.  */
6578             status = _nx_mdns_rr_a_aaaa_add(mdns_ptr, &temp_string_buffer[0], (ULONG *)(&ipv6_address_ptr -> nxd_ipv6_address[0]),
6579                                             NX_MDNS_IPV6_ADDRESS_LENGTH, type, interface_index);
6580 
6581             /* Check the status.  */
6582             if (status)
6583             {
6584 
6585                 /* Release the IP mutex.  */
6586                 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6587 
6588                 return(status);
6589             }
6590 
6591             /* Set the flag.  */
6592             add_aaaa = NX_TRUE;
6593         }
6594 
6595         /* Update the pointer.  */
6596         ipv6_address_ptr = ipv6_address_ptr -> nxd_ipv6_address_next;
6597     }
6598 #endif /* NX_MDNS_ENABLE_IPV6  */
6599 
6600 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
6601 
6602     /* Add the NSEC resource record.  */
6603     if ((add_a == NX_TRUE) || (add_aaaa == NX_TRUE))
6604         _nx_mdns_rr_nsec_add(mdns_ptr, &temp_string_buffer[0], add_a, add_aaaa, NX_MDNS_ADD_NSEC_FOR_HOST, interface_index);
6605 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
6606 
6607     /* Release the IP mutex.  */
6608     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
6609 
6610     /* Return a successful status.  */
6611     return(NX_SUCCESS);
6612 }
6613 #endif /* NX_MDNS_DISABLE_SERVER */
6614 
6615 
6616 /**************************************************************************/
6617 /*                                                                        */
6618 /*  FUNCTION                                               RELEASE        */
6619 /*                                                                        */
6620 /*    _nx_mdns_timer_entry                                PORTABLE C      */
6621 /*                                                           6.1          */
6622 /*  AUTHOR                                                                */
6623 /*                                                                        */
6624 /*    Yuxin Zhou, Microsoft Corporation                                   */
6625 /*                                                                        */
6626 /*  DESCRIPTION                                                           */
6627 /*                                                                        */
6628 /*    This function handles waking up the mDNS helper thread to process   */
6629 /*    the timer event on a periodic basis.                                */
6630 /*                                                                        */
6631 /*  INPUT                                                                 */
6632 /*                                                                        */
6633 /*    mdns_value                            mDNS instance for a ulong     */
6634 /*                                                                        */
6635 /*  OUTPUT                                                                */
6636 /*                                                                        */
6637 /*    None                                                                */
6638 /*                                                                        */
6639 /*  CALLS                                                                 */
6640 /*                                                                        */
6641 /*    tx_event_flags_set                    Set event flags               */
6642 /*                                                                        */
6643 /*  CALLED BY                                                             */
6644 /*                                                                        */
6645 /*    ThreadX system timer thread                                         */
6646 /*                                                                        */
6647 /*  RELEASE HISTORY                                                       */
6648 /*                                                                        */
6649 /*    DATE              NAME                      DESCRIPTION             */
6650 /*                                                                        */
6651 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6652 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6653 /*                                            resulting in version 6.1    */
6654 /*                                                                        */
6655 /**************************************************************************/
_nx_mdns_timer_entry(ULONG mdns_value)6656 static VOID _nx_mdns_timer_entry(ULONG mdns_value)
6657 {
6658 
6659 NX_MDNS     *mdns_ptr;
6660 
6661 
6662     /* Setup mDNS pointer from the input value.  */
6663     mdns_ptr = (NX_MDNS *) mdns_value;
6664 
6665     /* Set the timer event.  */
6666     tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_TIMER_EVENT, TX_OR);
6667 
6668     return;
6669 }
6670 
6671 
6672 /**************************************************************************/
6673 /*                                                                        */
6674 /*  FUNCTION                                               RELEASE        */
6675 /*                                                                        */
6676 /*    _nx_mdns_timer_set                                  PORTABLE C      */
6677 /*                                                           6.1          */
6678 /*  AUTHOR                                                                */
6679 /*                                                                        */
6680 /*    Yuxin Zhou, Microsoft Corporation                                   */
6681 /*                                                                        */
6682 /*  DESCRIPTION                                                           */
6683 /*                                                                        */
6684 /*    This function process all resource records according to the state,  */
6685 /*    Set the flags to send the probing, announcing, query, response and  */
6686 /*    goodbye mDNS message. Delete the resource record when the resource  */
6687 /*    record is invalid.                                                  */
6688 /*                                                                        */
6689 /*  INPUT                                                                 */
6690 /*                                                                        */
6691 /*    mdns_ptr                              Pointer to mDNS instance      */
6692 /*                                                                        */
6693 /*  OUTPUT                                                                */
6694 /*                                                                        */
6695 /*    status                                Completion status             */
6696 /*                                                                        */
6697 /*  CALLS                                                                 */
6698 /*                                                                        */
6699 /*    tx_timer_info_get                     Get the timer info            */
6700 /*    tx_timer_deactivate                   Deactivate the timer          */
6701 /*    tx_timer_change                       Change the timer              */
6702 /*    tx_timer_activate                     Activate the timer            */
6703 /*                                                                        */
6704 /*  CALLED BY                                                             */
6705 /*                                                                        */
6706 /*    _nx_mdns_enable                       Enable the mDNS               */
6707 /*    _nx_mdns_rr_a_aaaa_add                Add the A/AAAA resource record*/
6708 /*    _nx_mdns_rr_ptr_add                   Add the ptr resource record   */
6709 /*    _nx_mdns_rr_srv_add                   Add the srv resource record   */
6710 /*    _nx_mdns_rr_txt_add                   Add the txt resource record   */
6711 /*    _nx_mdns_rr_delete                    Delete the resource record    */
6712 /*    _nx_mdns_local_cache_clear            Clear the local cache         */
6713 /*    _nx_mdns_query                        Send the continuous query     */
6714 /*    _nx_mdns_packet_process               Process mDNS packet           */
6715 /*    _nx_mdns_conflict_process             Process the conflict          */
6716 /*                                                                        */
6717 /*  RELEASE HISTORY                                                       */
6718 /*                                                                        */
6719 /*    DATE              NAME                      DESCRIPTION             */
6720 /*                                                                        */
6721 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6722 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6723 /*                                            resulting in version 6.1    */
6724 /*                                                                        */
6725 /**************************************************************************/
_nx_mdns_timer_set(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr,ULONG timer_count)6726 static VOID _nx_mdns_timer_set(NX_MDNS *mdns_ptr, NX_MDNS_RR  *record_rr, ULONG timer_count)
6727 {
6728 
6729 
6730 TX_INTERRUPT_SAVE_AREA
6731 ULONG       remaining_ticks;
6732 ULONG       schedule_count;
6733 UINT        active;
6734 
6735     if (timer_count)
6736     {
6737 
6738         /* Disable interrupt */
6739         TX_DISABLE
6740 
6741         /* Get the remaining_ticks of mDNS timer;*/
6742         tx_timer_info_get(&mdns_ptr -> nx_mdns_timer, TX_NULL, &active, &remaining_ticks, TX_NULL, TX_NULL);
6743 
6744         /* If the timer is not active, the remaining ticks and schedule count are set to 0. */
6745         if(active == NX_FALSE)
6746         {
6747             remaining_ticks = 0;
6748             schedule_count = 0;
6749         }
6750         else
6751         {
6752 
6753             /* Get the reschedule timer count of last timer.  */
6754             schedule_count = mdns_ptr -> nx_mdns_timer_min_count;
6755         }
6756 
6757         /* Check the timer.  if exceed the timer count range, update the timer. */
6758         if((timer_count < remaining_ticks) || active == NX_FALSE)
6759         {
6760 
6761             /* Set the minimum timer count.
6762             The minimum timer count indicate the intervals between last timer event and next timer event. */
6763             mdns_ptr -> nx_mdns_timer_min_count = (schedule_count - remaining_ticks) + timer_count;
6764 
6765             /* Change the timer ticks with minimum timer count.*/
6766             tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
6767             tx_timer_change(&(mdns_ptr -> nx_mdns_timer), timer_count, timer_count );
6768             tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
6769         }
6770 
6771         /* Update the Resource record life timer count*/
6772         record_rr -> nx_mdns_rr_timer_count = (schedule_count - remaining_ticks) + timer_count;
6773 
6774         /* Restore interrupts.  */
6775         TX_RESTORE
6776     }
6777 }
6778 
6779 
6780 /**************************************************************************/
6781 /*                                                                        */
6782 /*  FUNCTION                                               RELEASE        */
6783 /*                                                                        */
6784 /*    _nx_mdns_timer_event_process                        PORTABLE C      */
6785 /*                                                           6.1.11       */
6786 /*  AUTHOR                                                                */
6787 /*                                                                        */
6788 /*    Yuxin Zhou, Microsoft Corporation                                   */
6789 /*                                                                        */
6790 /*  DESCRIPTION                                                           */
6791 /*                                                                        */
6792 /*    This function process all resource records according to the state,  */
6793 /*    Set the flags to send the probing, announcing, query, response and  */
6794 /*    goodbye mDNS message. Delete the resource record when the resource  */
6795 /*    record is invalid.                                                  */
6796 /*                                                                        */
6797 /*  INPUT                                                                 */
6798 /*                                                                        */
6799 /*    mdns_ptr                              Pointer to mDNS instance      */
6800 /*                                                                        */
6801 /*  OUTPUT                                                                */
6802 /*                                                                        */
6803 /*    status                                Completion status             */
6804 /*                                                                        */
6805 /*  CALLS                                                                 */
6806 /*                                                                        */
6807 /*    tx_event_flags_set                    Set event flags to wake mDNS  */
6808 /*    tx_timer_deactivate                   Deactivate the timer          */
6809 /*    tx_timer_change                       Change the timer              */
6810 /*    tx_timer_activate                     Activate the timer            */
6811 /*    _nx_mdns_service_name_resolve         Resolve the service name      */
6812 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
6813 /*                                            from the cache              */
6814 /*                                                                        */
6815 /*  CALLED BY                                                             */
6816 /*                                                                        */
6817 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
6818 /*                                                                        */
6819 /*  RELEASE HISTORY                                                       */
6820 /*                                                                        */
6821 /*    DATE              NAME                      DESCRIPTION             */
6822 /*                                                                        */
6823 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6824 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
6825 /*                                            verified memcpy use cases,  */
6826 /*                                            resulting in version 6.1    */
6827 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
6828 /*                                            corrected the random value, */
6829 /*                                            fixed the issue of timer,   */
6830 /*                                            resulting in version 6.1.11 */
6831 /*                                                                        */
6832 /**************************************************************************/
_nx_mdns_timer_event_process(NX_MDNS * mdns_ptr)6833 static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr)
6834 {
6835 
6836 ULONG       event_flags = 0;
6837 ULONG       timer_min_count = 0xFFFFFFFF;
6838 ULONG       *head, *tail;
6839 NX_MDNS_RR  *p;
6840 UCHAR       i;
6841 
6842 #ifndef NX_MDNS_DISABLE_CLIENT
6843 ULONG       remaining_ticks;
6844 #endif /* NX_MDNS_DISABLE_CLIENT  */
6845 
6846 #ifndef NX_MDNS_DISABLE_SERVER
6847 UINT        status;
6848 NX_MDNS_RR  *p1;
6849 UCHAR       *service_name;
6850 UCHAR       *service_type;
6851 UCHAR       *service_domain;
6852 UINT        rr_name_length;
6853 #endif /* NX_MDNS_DISABLE_SERVER */
6854 
6855 
6856     for(i = 0; i < 2; i++)
6857     {
6858 
6859         /* Set the pointer. */
6860         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
6861         {
6862 #ifndef NX_MDNS_DISABLE_SERVER
6863             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
6864 #else
6865             continue;
6866 #endif /* NX_MDNS_DISABLE_SERVER */
6867         }
6868         else
6869         {
6870 #ifndef NX_MDNS_DISABLE_CLIENT
6871             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
6872 #else
6873             continue;
6874 #endif /* NX_MDNS_DISABLE_CLIENT  */
6875         }
6876 
6877         if(head == NX_NULL)
6878             continue;
6879 
6880         tail = (ULONG*)(*head);
6881 
6882         /* Check the remote resource record lifetime.  */
6883         for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
6884         {
6885 
6886             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
6887                 continue;
6888 
6889             /* Update the remaining ticks of peer resource record.  */
6890             if (((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
6891                  (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)))
6892             {
6893                 if (p -> nx_mdns_rr_remaining_ticks > mdns_ptr -> nx_mdns_timer_min_count)
6894                 {
6895                     p -> nx_mdns_rr_remaining_ticks -= mdns_ptr -> nx_mdns_timer_min_count;
6896                 }
6897                 else
6898                 {
6899                     p -> nx_mdns_rr_remaining_ticks = 0;
6900                 }
6901             }
6902 
6903             /* Calculate the time interval for two responses.*/
6904             if (p -> nx_mdns_rr_response_interval > mdns_ptr -> nx_mdns_timer_min_count)
6905             {
6906                 p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count);
6907 
6908                 /* Compare the timer count.and set the minimum timer count. */
6909                 if ((p -> nx_mdns_rr_response_interval != 0) &&
6910                     (p -> nx_mdns_rr_response_interval < timer_min_count))
6911                 {
6912                     timer_min_count = p -> nx_mdns_rr_response_interval;
6913                 }
6914             }
6915             else
6916             {
6917                 p -> nx_mdns_rr_response_interval = 0;
6918             }
6919 
6920             /* If the timer count is zero, means do not do anything */
6921             if (p -> nx_mdns_rr_timer_count == 0)
6922                 continue;
6923 
6924             if (p -> nx_mdns_rr_timer_count > mdns_ptr -> nx_mdns_timer_min_count)
6925             {
6926                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_timer_count - mdns_ptr -> nx_mdns_timer_min_count;
6927 
6928                 /* Check the timer count range.  */
6929                 if (p -> nx_mdns_rr_timer_count <= NX_MDNS_TIMER_COUNT_RANGE)
6930                 {
6931                     p -> nx_mdns_rr_timer_count = 0;
6932                 }
6933                 else
6934                 {
6935                     /* Compare the timer count.and set the minimum timer count. */
6936                     if (p -> nx_mdns_rr_timer_count < timer_min_count)
6937                     {
6938                         timer_min_count = p -> nx_mdns_rr_timer_count;
6939                     }
6940                 }
6941             }
6942             else
6943             {
6944                 p -> nx_mdns_rr_timer_count = 0;
6945             }
6946 
6947             /* If the timer count is zero, means the timeout. */
6948             if (p -> nx_mdns_rr_timer_count != 0)
6949                 continue;
6950 
6951             /* Check the state. */
6952             switch (p -> nx_mdns_rr_state)
6953             {
6954 
6955 #ifndef NX_MDNS_DISABLE_SERVER
6956                 case NX_MDNS_RR_STATE_PROBING:
6957                 {
6958 
6959                     /* mDNS Server probing the RRs at 0ms, 250ms, 500ms. RFC6762, Section8.1, Page26.  */
6960                     if (p -> nx_mdns_rr_retransmit_count)
6961                     {
6962 
6963                         /* Set the send flag.*/
6964                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
6965 
6966                         /* Set the probing flag.  */
6967                         event_flags = event_flags | NX_MDNS_PROBING_SEND_EVENT;
6968 
6969                         /* Set the timer count. 250ms.  */
6970                         p -> nx_mdns_rr_timer_count = NX_MDNS_PROBING_TIMER_COUNT;
6971 
6972                         /* Compare the timer count.and set the minimum timer count. */
6973                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
6974                         {
6975                             timer_min_count = p -> nx_mdns_rr_timer_count;
6976                         }
6977                     }
6978                     else
6979                     {
6980 
6981                         /* Probing complete, and move to the next step, Announcing. */
6982                         p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_ANNOUNCING;
6983 
6984                         /* Set the first announcing timer interval.  */
6985                         p -> nx_mdns_rr_timer_count = NX_MDNS_ANNOUNCING_TIMER_COUNT;
6986 
6987                         /* Set the retransmit count.  */
6988                         if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
6989                             p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
6990                         else
6991                             p -> nx_mdns_rr_retransmit_count = 1;
6992 
6993                         /* Set the next timer count.  */
6994                         p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period;
6995 
6996                         /* Check the announcing max time.  */
6997                         if (mdns_ptr -> nx_mdns_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
6998                             p -> nx_mdns_rr_announcing_max_time = (UCHAR)(mdns_ptr -> nx_mdns_announcing_max_time - 1);
6999                         else
7000                             p -> nx_mdns_rr_announcing_max_time = NX_MDNS_ANNOUNCING_FOREVER;
7001 
7002                         /* Yes, probing complete, add the related PTR resource records.  */
7003                         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
7004                         {
7005 
7006                             /* Check string length.  */
7007                             if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
7008                             {
7009                                 break;
7010                             }
7011 
7012                             /* Store the service name.  */
7013                             memcpy((CHAR *)(&temp_string_buffer[0]), (const char*)p -> nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
7014 
7015                             /* Reslove the service name.  */
7016                             status = _nx_mdns_service_name_resolve(&temp_string_buffer[0], &service_name, &service_type, &service_domain);
7017 
7018                             /* Check the status.  */
7019                             if (status)
7020                             {
7021                                 break;
7022                             }
7023 
7024                             /* Service name registered success, invoke the notify function.  */
7025                             if (mdns_ptr -> nx_mdns_probing_notify)
7026                             {
7027                                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, service_name, NX_MDNS_LOCAL_SERVICE_REGISTERED_SUCCESS);
7028                             }
7029                         }
7030 
7031                         if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A)
7032                         {
7033 
7034                             /* Service name registered success, invoke the notify function.  */
7035                             if (mdns_ptr -> nx_mdns_probing_notify)
7036                             {
7037                                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, mdns_ptr -> nx_mdns_host_name, NX_MDNS_LOCAL_HOST_REGISTERED_SUCCESS);
7038                             }
7039                         }
7040 
7041                         /* Probing complete, Has been wating for 250ms, Directly announcing the resource record.  */
7042                         p --;
7043                     }
7044                     break;
7045                 }
7046 
7047                 case NX_MDNS_RR_STATE_ANNOUNCING:
7048                 {
7049 
7050                     /* mDNS Server Announcing the Resource records.  */
7051                     if (p -> nx_mdns_rr_retransmit_count)
7052                     {
7053 
7054                         /* Set the send flag to send the probing. */
7055                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7056 
7057                         /* Set the announcing flag.  */
7058                         event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7059 
7060                         /* Yes, probing complete, add the related PTR resource records and NSEC resource records. */
7061                         if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
7062                             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
7063                             (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
7064                         {
7065 
7066                             for (p1 = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p1 < tail; p1++)
7067                             {
7068 
7069                                 /* Check the state.  */
7070                                 if (p1 -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
7071                                     continue;
7072 
7073                                 /* Check the interface.  */
7074                                 if (p1 -> nx_mdns_rr_interface_index != p -> nx_mdns_rr_interface_index)
7075                                     continue;
7076 
7077 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7078                                 if ((p1 ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
7079                                     (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name))
7080                                 {
7081 
7082                                     /* Set the send flag to send the probing. */
7083                                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7084                                 }
7085 #endif /*NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7086 
7087                                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
7088                                     (p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
7089                                     (p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == p -> nx_mdns_rr_name))
7090                                 {
7091 
7092                                     /* Set the send flag to send the probing. */
7093                                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7094                                 }
7095                             }
7096                         }
7097 
7098                         /* Check last the retransmit in this period announcing.  */
7099                         if (p -> nx_mdns_rr_retransmit_count - 1)
7100                         {
7101 
7102                             if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7103                             {
7104 
7105                                 /* Set the timer count.  */
7106                                 p -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_announcing_retrans_interval;
7107 
7108                                 /* Compare the timer count and set the minimum timer count. */
7109                                 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7110                                 {
7111                                     timer_min_count = p -> nx_mdns_rr_timer_count;
7112                                 }
7113                             }
7114                         }
7115                         else
7116                         {
7117                             if (p -> nx_mdns_rr_announcing_max_time)
7118                             {
7119 
7120                                 /* Update the timer count.  */
7121                                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7122 
7123                                 /* Calculate the next timer count.   */
7124                                 p -> nx_mdns_rr_retransmit_lifetime = (ULONG)(p -> nx_mdns_rr_retransmit_lifetime * (ULONG)(2 << (mdns_ptr -> nx_mdns_announcing_factor - 1)));
7125 
7126                                 /* Check the announcing period time interval.  */
7127                                 if (p -> nx_mdns_rr_retransmit_lifetime > mdns_ptr -> nx_mdns_announcing_period_interval)
7128                                     p -> nx_mdns_rr_retransmit_lifetime = mdns_ptr -> nx_mdns_announcing_period_interval;
7129 
7130                                 /* Set the retransmit count.  */
7131                                 if (mdns_ptr -> nx_mdns_announcing_retrans_interval)
7132                                     p -> nx_mdns_rr_retransmit_count = mdns_ptr -> nx_mdns_announcing_count;
7133                                 else
7134                                     p -> nx_mdns_rr_retransmit_count = 1;
7135 
7136                                 /* Set the retransmit count.  */
7137                                 p -> nx_mdns_rr_retransmit_count++;
7138 
7139                                 /* Check the announcing time.  */
7140                                 if (p -> nx_mdns_rr_announcing_max_time != NX_MDNS_ANNOUNCING_FOREVER)
7141                                     p -> nx_mdns_rr_announcing_max_time--;
7142 
7143                                 /* Compare the timer count and set the minimum timer count. */
7144                                 if (p -> nx_mdns_rr_timer_count < timer_min_count)
7145                                 {
7146                                     timer_min_count = p -> nx_mdns_rr_timer_count;
7147                                 }
7148                             }
7149                             else
7150                             {
7151 
7152                                 /* Announcing complete, Update the resource record state valid,  . */
7153                                 p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
7154 
7155                                 /* Clear the timer count.  */
7156                                 p -> nx_mdns_rr_timer_count = 0;
7157                             }
7158                         }
7159                     }
7160                     break;
7161                 }
7162 
7163                 case NX_MDNS_RR_STATE_GOODBYE:
7164                 {
7165 
7166                     /* mDNS Server send Goodbye packet.  */
7167                     if (p -> nx_mdns_rr_retransmit_count)
7168                     {
7169 
7170                         /* Set the send flag to send the probing. */
7171                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7172 
7173                         /* Set the announcing flag.  */
7174                         event_flags = event_flags | NX_MDNS_ANNOUNCING_SEND_EVENT;
7175 
7176                         /* Set the timer count.  */
7177                         p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
7178 
7179                         /* Compare the timer count.and set the minimum timer count. */
7180                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7181                         {
7182                             timer_min_count = p -> nx_mdns_rr_timer_count;
7183                         }
7184                     }
7185                     else
7186                     {
7187 
7188                         /* Check for RR delete flag.  */
7189                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DELETE)
7190                         {
7191 
7192                             /* Delete the resource records.  */
7193                             _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
7194                         }
7195                         else
7196                         {
7197 
7198                             /* Suspend the resource record.  */
7199                             p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_SUSPEND;
7200                             p -> nx_mdns_rr_timer_count = 0;
7201                         }
7202                     }
7203                     break;
7204                 }
7205 #endif /* NX_MDNS_DISABLE_SERVER */
7206 
7207 
7208                 case NX_MDNS_RR_STATE_VALID:
7209                 {
7210 
7211                     if(i == NX_MDNS_CACHE_TYPE_PEER)
7212                     {
7213                         /* Set the resource record status.  */
7214                         p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_UPDATING;
7215 
7216                         /* Check the updating flag.  */
7217                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UPDATING)
7218                         {
7219 
7220                             /* Set the retransmit count.  */
7221                             p -> nx_mdns_rr_retransmit_count = NX_MDNS_RR_UPDATE_COUNT;
7222 
7223                             /* 50% of the record lifetime has elapsed,the querier should plan to issure a query at 80%-82% of the record lifetime */
7224                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (((ULONG)NX_RAND()) % 3)) / 100;
7225                         }
7226                         else
7227                         {
7228                             /* Set the retransmit count.  */
7229                             p -> nx_mdns_rr_retransmit_count = 0;
7230 
7231                             /* 50% of the record lifetime has elapsed, Delete the resource record at 100% of the record lifetime */
7232                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
7233                         }
7234 
7235                         /* Compare the timer count.and set the minimum timer count. */
7236                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7237                         {
7238                             timer_min_count = p -> nx_mdns_rr_timer_count;
7239                         }
7240                     }
7241 
7242                     /* Check the send flag.  */
7243                     else
7244                     {
7245                         if (p -> nx_mdns_rr_send_flag)
7246                         {
7247 
7248                             /* Set the send flag to send the response. */
7249                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7250 
7251 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7252                             /* Clear the NSEC additional send.  */
7253                             if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7254                                 p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7255 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7256 
7257                             /* mDNS Responder MUST NOT multicast a record until at least one second has elapsed since the last time that record was multicast. RFC6762, Section6, Page16.  */
7258                             /* Set the next response time interval.  */
7259                             p -> nx_mdns_rr_response_interval = (ULONG)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE);
7260 
7261                             /* Compare the timer count.and set the minimum timer count. */
7262                             if (p -> nx_mdns_rr_response_interval < timer_min_count)
7263                             {
7264                                 timer_min_count = p -> nx_mdns_rr_response_interval;
7265                             }
7266 
7267                             /* Set the announcing flag.  */
7268                             event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7269                         }
7270 
7271 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7272                         else
7273                         {
7274                             if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
7275                             {
7276                                 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send)
7277                                 {
7278                                     p -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_ADDITIONAL;
7279                                     p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_FALSE;
7280 
7281                                     /* Set the announcing flag.  */
7282                                     event_flags = event_flags | NX_MDNS_RESPONSE_SEND_EVENT;
7283                                 }
7284                             }
7285                         }
7286 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7287                     }
7288                     break;
7289                 }
7290 
7291 
7292 #ifndef NX_MDNS_DISABLE_CLIENT
7293                 case NX_MDNS_RR_STATE_QUERY:
7294                 {
7295 
7296                     /* mDNS Client did not receive the response, send the query again.  */
7297                     if (!p -> nx_mdns_rr_timer_count)
7298                     {
7299 
7300                         /* Check the Duplicate Question. If the flag set, Host should not send the query until the next timeout.  */
7301                         if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_DUPLICATE_QUERY))
7302                         {
7303 
7304                             /* Set the send flag to send the query. */
7305                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7306 
7307                             /* Set the query flag.  */
7308                             event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7309                         }
7310 
7311                         /* Clear the duplicate flag.  */
7312                         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
7313 
7314                         /* Double the next timer count.   */
7315                         p -> nx_mdns_rr_retransmit_lifetime = p -> nx_mdns_rr_retransmit_lifetime << 1;
7316 
7317                         /* The interval between the first two queries MUST be at least one second. RFC6762, Section5.2, Page9.  */
7318                         if (p -> nx_mdns_rr_retransmit_lifetime < NX_MDNS_QUERY_MIN_TIMER_COUNT)
7319                         {
7320                             p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MIN_TIMER_COUNT;
7321                         }
7322 
7323                         /* When the interval between queries reaches or exceeds 60 minutes, a querier MAY cap the interval to a maximum of 60 minutes. RFC6762, Section5.2, Page10.  */
7324                         if (p -> nx_mdns_rr_retransmit_lifetime > NX_MDNS_QUERY_MAX_TIMER_COUNT)
7325                         {
7326                             p -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_QUERY_MAX_TIMER_COUNT;
7327                         }
7328 
7329                         /* Update the timer count.  */
7330                         p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_retransmit_lifetime;
7331 
7332                         /* Compare the timer count.and set the minimum timer count. */
7333                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7334                         {
7335                             timer_min_count = p -> nx_mdns_rr_timer_count;
7336                         }
7337                     }
7338                     break;
7339                 }
7340 
7341                 case NX_MDNS_RR_STATE_UPDATING:
7342                 {
7343 
7344                     /* The querier should plan to issure a query at 80%-82% of the record lifetime, and then if no answer is received,
7345                        at 85%-87%, 90%-92% and 95%-97%. the record is deleted when it reaches 100% of its lifetime. RFC6762, Section5.2, Page10.  */
7346                     if (p -> nx_mdns_rr_retransmit_count)
7347                     {
7348 
7349                         /* Set the send flag to retransmit its query. */
7350                         p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
7351 
7352                         /* Set the query flag.  */
7353                         event_flags = event_flags | NX_MDNS_QUERY_SEND_EVENT;
7354 
7355                         /* Update the timer count. Client should send the updating message every 5% of ttl.   */
7356                         if (p -> nx_mdns_rr_retransmit_count == 1)
7357                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_remaining_ticks;
7358                         else
7359                         {
7360                             remaining_ticks = p -> nx_mdns_rr_remaining_ticks;
7361                             p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 5 / 100;
7362 
7363                             /* Get the remaining ticks in 5% of TTL. */
7364                             while(remaining_ticks > p -> nx_mdns_rr_timer_count)
7365                                 remaining_ticks -= p -> nx_mdns_rr_timer_count;
7366 
7367                             p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(((ULONG)NX_RAND()) % 3) / 100);
7368                         }
7369 
7370                         /* Compare the timer count.and set the minimum timer count. */
7371                         if (p -> nx_mdns_rr_timer_count < timer_min_count)
7372                         {
7373                             timer_min_count = p -> nx_mdns_rr_timer_count;
7374                         }
7375                     }
7376                     else
7377                     {
7378 
7379                         /* Delete the resource record.  */
7380                         _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7381                     }
7382                     break;
7383                 }
7384 
7385                 case NX_MDNS_RR_STATE_DELETE:
7386                 case NX_MDNS_RR_STATE_POOF_DELETE:
7387                 {
7388 
7389                     /* Delete the resource record.  */
7390                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
7391                     break;
7392                 }
7393 #endif /* NX_MDNS_DISABLE_CLIENT  */
7394 
7395                 default:
7396                 {
7397                     break;
7398                 }
7399             }
7400         }
7401     }
7402 
7403     /* If the specified timer rate is different with the new timer min count,then update it.*/
7404     if (mdns_ptr -> nx_mdns_timer_min_count != timer_min_count)
7405     {
7406 
7407         /* Set the minimum timer count.*/
7408         mdns_ptr -> nx_mdns_timer_min_count = timer_min_count;
7409 
7410         /* Deactivate the timer. */
7411         tx_timer_deactivate(&(mdns_ptr -> nx_mdns_timer));
7412 
7413         if (timer_min_count != 0xFFFFFFFF)
7414         {
7415 
7416             /* Change the timer ticks with minimum timer count.*/
7417             tx_timer_change(&(mdns_ptr -> nx_mdns_timer),
7418                             mdns_ptr -> nx_mdns_timer_min_count,
7419                             mdns_ptr -> nx_mdns_timer_min_count);
7420             tx_timer_activate(&(mdns_ptr -> nx_mdns_timer));
7421         }
7422     }
7423 
7424     /* Set the event to send mDNS query.  */
7425     tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), event_flags, TX_OR);
7426 }
7427 
7428 
7429 /**************************************************************************/
7430 /*                                                                        */
7431 /*  FUNCTION                                               RELEASE        */
7432 /*                                                                        */
7433 /*    _nx_mdns_udp_receive_notify                         PORTABLE C      */
7434 /*                                                           6.1          */
7435 /*  AUTHOR                                                                */
7436 /*                                                                        */
7437 /*    Yuxin Zhou, Microsoft Corporation                                   */
7438 /*                                                                        */
7439 /*  DESCRIPTION                                                           */
7440 /*                                                                        */
7441 /*    This function is the mDNS UDP receive notify callback.              */
7442 /*                                                                        */
7443 /*  INPUT                                                                 */
7444 /*                                                                        */
7445 /*    socket_ptr                            Pointer to udp socket         */
7446 /*                                                                        */
7447 /*  OUTPUT                                                                */
7448 /*                                                                        */
7449 /*    None                                                                */
7450 /*                                                                        */
7451 /*  CALLS                                                                 */
7452 /*                                                                        */
7453 /*    tx_event_flags_set                    Set event flags               */
7454 /*                                                                        */
7455 /*  CALLED BY                                                             */
7456 /*                                                                        */
7457 /*    UDP receive callback                                                */
7458 /*                                                                        */
7459 /*  RELEASE HISTORY                                                       */
7460 /*                                                                        */
7461 /*    DATE              NAME                      DESCRIPTION             */
7462 /*                                                                        */
7463 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7464 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7465 /*                                            resulting in version 6.1    */
7466 /*                                                                        */
7467 /**************************************************************************/
_nx_mdns_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)7468 static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
7469 {
7470 
7471 
7472     NX_PARAMETER_NOT_USED(socket_ptr);
7473 
7474     /* Check the mDNS.  */
7475     if(_nx_mdns_created_ptr)
7476     {
7477 
7478         /* Set the receive UDP packet notify. */
7479         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_PKT_RX_EVENT, TX_OR);
7480     }
7481 
7482     return;
7483 }
7484 
7485 #ifndef NX_MDNS_DISABLE_SERVER
7486 #ifndef NX_DISABLE_IPV4
7487 /**************************************************************************/
7488 /*                                                                        */
7489 /*  FUNCTION                                               RELEASE        */
7490 /*                                                                        */
7491 /*    _nx_mdns_ip_address_change_notify                   PORTABLE C      */
7492 /*                                                           6.1          */
7493 /*  AUTHOR                                                                */
7494 /*                                                                        */
7495 /*    Yuxin Zhou, Microsoft Corporation                                   */
7496 /*                                                                        */
7497 /*  DESCRIPTION                                                           */
7498 /*                                                                        */
7499 /*    This function is the mDNS UDP receive notify callback.              */
7500 /*                                                                        */
7501 /*  INPUT                                                                 */
7502 /*                                                                        */
7503 /*    socket_ptr                            Pointer to udp socket         */
7504 /*                                                                        */
7505 /*  OUTPUT                                                                */
7506 /*                                                                        */
7507 /*    None                                                                */
7508 /*                                                                        */
7509 /*  CALLS                                                                 */
7510 /*                                                                        */
7511 /*    tx_event_flags_set                    Set event flags               */
7512 /*                                                                        */
7513 /*  CALLED BY                                                             */
7514 /*                                                                        */
7515 /*    UDP receive callback                                                */
7516 /*                                                                        */
7517 /*  RELEASE HISTORY                                                       */
7518 /*                                                                        */
7519 /*    DATE              NAME                      DESCRIPTION             */
7520 /*                                                                        */
7521 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7522 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7523 /*                                            resulting in version 6.1    */
7524 /*                                                                        */
7525 /**************************************************************************/
_nx_mdns_ip_address_change_notify(NX_IP * ip_ptr,VOID * additional_info)7526 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info)
7527 {
7528 
7529 
7530     NX_PARAMETER_NOT_USED(ip_ptr);
7531     NX_PARAMETER_NOT_USED(additional_info);
7532 
7533     /* Check the mDNS.  */
7534     if(_nx_mdns_created_ptr)
7535     {
7536 
7537         /* Set the address change event event. */
7538         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7539     }
7540 
7541     return;
7542 }
7543 #endif /* NX_DISABLE_IPV4 */
7544 
7545 
7546 /**************************************************************************/
7547 /*                                                                        */
7548 /*  FUNCTION                                               RELEASE        */
7549 /*                                                                        */
7550 /*    _nx_mdns_ipv6_address_change_notify                 PORTABLE C      */
7551 /*                                                           6.1          */
7552 /*  AUTHOR                                                                */
7553 /*                                                                        */
7554 /*    Yuxin Zhou, Microsoft Corporation                                   */
7555 /*                                                                        */
7556 /*  DESCRIPTION                                                           */
7557 /*                                                                        */
7558 /*    This function is the mDNS UDP receive notify callback.              */
7559 /*                                                                        */
7560 /*  INPUT                                                                 */
7561 /*                                                                        */
7562 /*    socket_ptr                            Pointer to udp socket         */
7563 /*                                                                        */
7564 /*  OUTPUT                                                                */
7565 /*                                                                        */
7566 /*    None                                                                */
7567 /*                                                                        */
7568 /*  CALLS                                                                 */
7569 /*                                                                        */
7570 /*    tx_event_flags_set                    Set event flags               */
7571 /*                                                                        */
7572 /*  CALLED BY                                                             */
7573 /*                                                                        */
7574 /*    UDP receive callback                                                */
7575 /*                                                                        */
7576 /*  RELEASE HISTORY                                                       */
7577 /*                                                                        */
7578 /*    DATE              NAME                      DESCRIPTION             */
7579 /*                                                                        */
7580 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7581 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7582 /*                                            resulting in version 6.1    */
7583 /*                                                                        */
7584 /**************************************************************************/
7585 #ifdef NX_MDNS_ENABLE_IPV6
_nx_mdns_ipv6_address_change_notify(NX_IP * ip_ptr,UINT method,UINT interface_index,UINT index,ULONG * ipv6_address)7586 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address)
7587 {
7588 
7589     NX_PARAMETER_NOT_USED(ip_ptr);
7590     NX_PARAMETER_NOT_USED(method);
7591     NX_PARAMETER_NOT_USED(interface_index);
7592     NX_PARAMETER_NOT_USED(index);
7593     NX_PARAMETER_NOT_USED(ipv6_address);
7594 
7595     /* Check the mDNS.  */
7596     if(_nx_mdns_created_ptr)
7597     {
7598 
7599         /* Set the address change event. */
7600         tx_event_flags_set(&(_nx_mdns_created_ptr -> nx_mdns_events), NX_MDNS_ADDRESS_CHANGE_EVENT, TX_OR);
7601     }
7602     return;
7603 }
7604 #endif /* NX_MDNS_ENABLE_IPV6  */
7605 #endif /* NX_MDNS_DISABLE_SERVER  */
7606 
7607 
7608 /**************************************************************************/
7609 /*                                                                        */
7610 /*  FUNCTION                                               RELEASE        */
7611 /*                                                                        */
7612 /*    _nx_mdns_thread_entry                               PORTABLE C      */
7613 /*                                                           6.1          */
7614 /*  AUTHOR                                                                */
7615 /*                                                                        */
7616 /*    Yuxin Zhou, Microsoft Corporation                                   */
7617 /*                                                                        */
7618 /*  DESCRIPTION                                                           */
7619 /*                                                                        */
7620 /*    This function is the entry point for the mDNS helper thread.        */
7621 /*    mDNS helper thread is responsible for processing mDNS events.       */
7622 /*    Receive and send the mDNS packet.                                   */
7623 /*                                                                        */
7624 /*  INPUT                                                                 */
7625 /*                                                                        */
7626 /*    mdns_value                            Pointer to mDNS instance      */
7627 /*                                                                        */
7628 /*  OUTPUT                                                                */
7629 /*                                                                        */
7630 /*    None                                                                */
7631 /*                                                                        */
7632 /*  CALLS                                                                 */
7633 /*                                                                        */
7634 /*    tx_mutex_get                          Get the mDNS mutex            */
7635 /*    tx_mutex_put                          Put the mDNS mutex            */
7636 /*    tx_event_flags_get                    Get the mDNS events           */
7637 /*    nx_udp_socket_receive                 Receive the mDNS packet       */
7638 /*    nx_packet_release                     Release the mDNS packet       */
7639 /*    _nx_mdns_packet_process               Process mDNS packet           */
7640 /*    _nx_mdns_announcing_send              Send announcing message       */
7641 /*    _nx_mdns_probing_send                 Send probing message          */
7642 /*    _nx_mdns_query_send                   Send query message            */
7643 /*    _nx_mdns_response_send                Send response message         */
7644 /*    _nx_mdns_timer_event_process          Process the mDNS timer event  */
7645 /*    _nx_mdns_address_change_process       Process the address change    */
7646 /*                                                                        */
7647 /*  CALLED BY                                                             */
7648 /*                                                                        */
7649 /*    ThreadX Scheduler                                                   */
7650 /*                                                                        */
7651 /*  RELEASE HISTORY                                                       */
7652 /*                                                                        */
7653 /*    DATE              NAME                      DESCRIPTION             */
7654 /*                                                                        */
7655 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7656 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7657 /*                                            resulting in version 6.1    */
7658 /*                                                                        */
7659 /**************************************************************************/
_nx_mdns_thread_entry(ULONG mdns_value)7660 static VOID  _nx_mdns_thread_entry(ULONG mdns_value)
7661 {
7662 
7663 NX_MDNS         *mdns_ptr;
7664 NX_PACKET       *packet_ptr;
7665 ULONG            mdns_events;
7666 UINT             status;
7667 UINT             interface_index;
7668 
7669 
7670     /* Setup mDNS pointer from the input value.  */
7671     mdns_ptr =  (NX_MDNS *) mdns_value;
7672 
7673     /* Get the mDNS mutex.  */
7674     tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7675 
7676     /* Loop to process events for this mDNS instance.  */
7677     while(1)
7678     {
7679 
7680         /* Release the mDNS mutex.  */
7681         tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex));
7682 
7683         /* Pickup mDNS event flags.  */
7684         tx_event_flags_get(&mdns_ptr -> nx_mdns_events,
7685                            NX_MDNS_ALL_EVENTS, TX_OR_CLEAR,
7686                            &mdns_events, TX_WAIT_FOREVER);
7687 
7688         /* Get the mDNS mutex.  */
7689         tx_mutex_get(&(mdns_ptr -> nx_mdns_mutex), TX_WAIT_FOREVER);
7690 
7691         /* Check for an UDP packet receive event. */
7692         if (mdns_events & NX_MDNS_PKT_RX_EVENT)
7693         {
7694             while (1)
7695             {
7696 
7697                 /* Receive a UDP packet.  */
7698                 status =  _nx_udp_socket_receive(&mdns_ptr -> nx_mdns_socket,
7699                                                  &packet_ptr, TX_NO_WAIT);
7700 
7701                 /* Check status.  */
7702                 if (status != NX_SUCCESS)
7703                     break;
7704 
7705 #ifndef NX_DISABLE_PACKET_CHAIN
7706 
7707                 /* Discard the chained packets.  */
7708                 if (packet_ptr -> nx_packet_next)
7709                 {
7710                     nx_packet_release(packet_ptr);
7711                     continue;
7712                 }
7713 #endif
7714 
7715                 /* Get the interface.  */
7716                 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
7717                 {
7718                     interface_index = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
7719                 }
7720                 else
7721                 {
7722                     interface_index = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached -> nx_interface_index;
7723                 }
7724 
7725                 /* Check the interface.  */
7726                 if (!mdns_ptr -> nx_mdns_interface_enabled[interface_index])
7727                 {
7728                     /* Release the packet since mDNS is not enabled on this interface. */
7729                     nx_packet_release(packet_ptr);
7730                     continue;
7731                 }
7732 
7733                 /* Yes, Get the mDNS packet, process it.  */
7734                 _nx_mdns_packet_process(mdns_ptr, packet_ptr, interface_index);
7735 
7736                 /* Release the packet. */
7737                 nx_packet_release(packet_ptr);
7738             }
7739         }
7740 
7741         /* Loop to send mDNS message for each interface.  */
7742         for (interface_index = 0; interface_index < NX_MAX_PHYSICAL_INTERFACES; interface_index++)
7743         {
7744 
7745             /* Check if this interface is enabled.
7746                Exception: Goodbye message can be sent out after disable.  */
7747             if ((!mdns_ptr -> nx_mdns_interface_enabled[interface_index]) &&
7748                 (!(mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)))
7749                 continue;
7750 
7751 #ifndef NX_MDNS_DISABLE_SERVER
7752 
7753             /* Check for an mDNS probing send event. */
7754             if (mdns_events & NX_MDNS_PROBING_SEND_EVENT)
7755             {
7756 
7757                 /* Send probing.  */
7758                 _nx_mdns_probing_send(mdns_ptr, interface_index);
7759             }
7760 
7761             /* Check for an mDNS announcing send event. */
7762             if (mdns_events & NX_MDNS_ANNOUNCING_SEND_EVENT)
7763             {
7764 
7765                 /* Send announcing.  */
7766                 _nx_mdns_announcing_send(mdns_ptr, interface_index);
7767             }
7768 
7769             /* Check for an mDNS response send event. */
7770             if (mdns_events & NX_MDNS_RESPONSE_SEND_EVENT)
7771             {
7772 
7773                 /* Send response.  */
7774                 _nx_mdns_response_send(mdns_ptr, interface_index);
7775             }
7776 #endif /* NX_MDNS_DISABLE_SERVER */
7777 
7778 #ifndef NX_MDNS_DISABLE_CLIENT
7779             /* Check for an mDNS query send event. */
7780             if (mdns_events & NX_MDNS_QUERY_SEND_EVENT)
7781             {
7782 
7783                 /* Send query.  */
7784                 _nx_mdns_query_send(mdns_ptr, interface_index);
7785             }
7786 #endif /* NX_MDNS_DISABLE_CLIENT */
7787         }
7788 
7789 #ifndef NX_MDNS_DISABLE_SERVER
7790 
7791         /* Check for an mDNS address change event. */
7792         if (mdns_events & NX_MDNS_ADDRESS_CHANGE_EVENT)
7793         {
7794 
7795             /* Process the address change event.  */
7796             _nx_mdns_address_change_process(mdns_ptr);
7797         }
7798 #endif /* NX_MDNS_DISABLE_SERVER */
7799 
7800         /* Check for an mDNS timer process event. */
7801         if (mdns_events & NX_MDNS_TIMER_EVENT)
7802         {
7803 
7804             /* Process the timer event.  */
7805             _nx_mdns_timer_event_process(mdns_ptr);
7806         }
7807     }
7808 }
7809 
7810 
7811 /**************************************************************************/
7812 /*                                                                        */
7813 /*  FUNCTION                                               RELEASE        */
7814 /*                                                                        */
7815 /*    _nx_mdns_packet_process                             PORTABLE C      */
7816 /*                                                           6.1.11       */
7817 /*  AUTHOR                                                                */
7818 /*                                                                        */
7819 /*    Yuxin Zhou, Microsoft Corporation                                   */
7820 /*                                                                        */
7821 /*  DESCRIPTION                                                           */
7822 /*                                                                        */
7823 /*    This function checks the interface and the IP address of received   */
7824 /*    packet, then preocesses the packet.                                 */
7825 /*                                                                        */
7826 /*  INPUT                                                                 */
7827 /*                                                                        */
7828 /*    mdns_ptr                              Pointer to mDNS instance      */
7829 /*    packet_ptr                            Pointer to mDNS packet        */
7830 /*                                                                        */
7831 /*  OUTPUT                                                                */
7832 /*                                                                        */
7833 /*    status                                Completion status             */
7834 /*                                                                        */
7835 /*  CALLS                                                                 */
7836 /*                                                                        */
7837 /*    nx_packet_release                     Release the mDNS packet       */
7838 /*    _tx_thread_system_resume              Resume thread service         */
7839 /*    _nx_mdns_timer_set                    Set the mDNS timer            */
7840 /*    _nx_mdns_name_string_decode           Decode the name size          */
7841 /*    _nx_mdns_name_size_calculate          Calculate the name size       */
7842 /*    _nx_mdns_rr_size_get                  Get the resource record size  */
7843 /*    _nx_mdns_conflict_process             Process the mDNS conflict     */
7844 /*    _nx_mdns_cache_find_resource_record   Find the mDNS resource record */
7845 /*    _nx_mdns_packet_address_check         Check the address and port    */
7846 /*    _nx_mdns_packet_rr_process            Process resource record       */
7847 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
7848 /*                                            from cache                  */
7849 /*    nxd_udp_packet_info_extract           Extract the packet info       */
7850 /*                                                                        */
7851 /*  CALLED BY                                                             */
7852 /*                                                                        */
7853 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
7854 /*                                                                        */
7855 /*  RELEASE HISTORY                                                       */
7856 /*                                                                        */
7857 /*    DATE              NAME                      DESCRIPTION             */
7858 /*                                                                        */
7859 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7860 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7861 /*                                            resulting in version 6.1    */
7862 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
7863 /*                                            packet length verification, */
7864 /*                                            resulting in version 6.1.4  */
7865 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
7866 /*                                            corrected the random value, */
7867 /*                                            fixed the issue of timer,   */
7868 /*                                            resulting in version 6.1.11 */
7869 /*                                                                        */
7870 /**************************************************************************/
_nx_mdns_packet_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)7871 static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
7872 {
7873 
7874 USHORT              mdns_flags;
7875 UCHAR              *data_ptr;
7876 USHORT              question_count;
7877 USHORT              authority_count;
7878 USHORT              answer_count;
7879 UINT                index;
7880 NX_MDNS_RR         *rr_search;
7881 NX_MDNS_RR          temp_resource_record;
7882 
7883 #ifndef NX_MDNS_DISABLE_SERVER
7884 ULONG              *head;
7885 NX_MDNS_RR         *p;
7886 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
7887 ULONG               match_count;
7888 NX_MDNS_RR         *nsec_rr;
7889 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
7890 #endif /* NX_MDNS_DISABLE_SERVER  */
7891 
7892 
7893 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
7894     /* Check the address and port.  */
7895     if (_nx_mdns_packet_address_check(packet_ptr))
7896     {
7897         return(NX_MDNS_ERROR);
7898     }
7899 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
7900 
7901     /* Check the packet length.  */
7902     if (packet_ptr -> nx_packet_length < NX_MDNS_QDSECT_OFFSET)
7903     {
7904         return(NX_MDNS_ERROR);
7905     }
7906 
7907     /* Extract the message type which should be the first byte.  */
7908     mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
7909 
7910     /* Get the question count.  */
7911     question_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET);
7912 
7913     /* Determine if we have any 'answers' to our DNS query. */
7914     answer_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET);
7915 
7916     /* Also check if there are any 'hints' from the Authoritative nameserver. */
7917     authority_count = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET);
7918 
7919     /* Update the answer count. Ignore the authority count and additional count for query message.  */
7920     if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7921     {
7922         answer_count = (USHORT)(answer_count + authority_count);
7923 
7924         /* Include Additional section as well */
7925         answer_count = (USHORT)(answer_count + NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET));
7926     }
7927 
7928     /* Skip the Header. Point at the start of the question.  */
7929     data_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
7930 
7931     /* Process all the Question Section.  */
7932     for (index = 0; index < question_count; index++)
7933     {
7934 
7935         /* Check for data_ptr.  */
7936         if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
7937             break;
7938 
7939         if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
7940         {
7941 
7942             /* Multicast DNS responses MUST NOT contain any question in the Question Section,
7943                Any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. RFC6762, Section6, Page14.  */
7944             data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
7945         }
7946         else
7947         {
7948 
7949 #ifndef NX_MDNS_DISABLE_CLIENT
7950 
7951             /* Step1, mDNS Client process the Duplicate Question Suppression, RFC6762, Section7.3, Page24.  */
7952             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
7953             {
7954 
7955                 /* Check the class top bit "QM".   */
7956                 if ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_RR_CLASS_TOP_BIT) != NX_MDNS_RR_CLASS_TOP_BIT)
7957                 {
7958 
7959                     /* Find the same resource record in remote buffer.  */
7960                     if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
7961                     {
7962 
7963                         /* Duplicate Question Suppression.  */
7964                         if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
7965                         {
7966 
7967                             if (_nx_mdns_known_answer_find(mdns_ptr, rr_search) == NX_MDNS_NO_KNOWN_ANSWER)
7968                             {
7969 
7970                                 /* Yes, set the duplicate flag. process this flag in timer event process function.  */
7971                                 rr_search -> nx_mdns_rr_word = rr_search -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DUPLICATE_QUERY;
7972                             }
7973                         }
7974 
7975 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
7976                         /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
7977                         if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
7978                             (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
7979                         {
7980                             rr_search -> nx_mdns_rr_poof_count ++;
7981 
7982                             /* After seeing two or more of these queries, and seeing no multicast response containing the expected anser within ten seconds, the record should be flushed from the cache.  */
7983                             if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
7984                                 (rr_search -> nx_mdns_rr_poof_count >= NX_MDNS_POOF_MIN_COUNT))
7985                             {
7986                                 rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_POOF_DELETE;
7987                                 rr_search -> nx_mdns_rr_timer_count = NX_MDNS_POOF_TIMER_COUNT;
7988 
7989                                 /* Set the mDNS timer.  */
7990                                 _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
7991                             }
7992                         }
7993 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
7994                     }
7995                 }
7996             }
7997 #endif /* NX_MDNS_DISABLE_CLIENT */
7998 
7999 #ifndef NX_MDNS_DISABLE_SERVER
8000 
8001             /* Step2, mDNS Server process the normal query.  */
8002             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8003             {
8004 
8005 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8006                 /* Set the match count.  */
8007                 match_count = 0;
8008                 nsec_rr = NX_NULL;
8009 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8010 
8011                 /* Get head. */
8012                 head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8013                 head = (ULONG*)(*head);
8014 
8015                 /* Find the same record.  */
8016                 for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
8017                 {
8018 
8019                     /* Check the interface index.  */
8020                     if (p -> nx_mdns_rr_interface_index != interface_index)
8021                         continue;
8022 
8023                     /* Check whether the resource record is valid. */
8024                     if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
8025                         continue;
8026 
8027                     /* Check whether the same record it is. RFC6762, Section6, Page13. */
8028                     /* The rules: rrname must match the question name.
8029                     rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
8030                     rrclass must match the question qclass unless the qclass is "ANY". */
8031                     if (p -> nx_mdns_rr_name != temp_resource_record.nx_mdns_rr_name)
8032                         continue;
8033 
8034 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8035 
8036                     /* Check the NSEC type.  */
8037                     if (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
8038                         nsec_rr = p;
8039 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8040 
8041                     if ((p -> nx_mdns_rr_type != temp_resource_record.nx_mdns_rr_type) &&
8042                         (temp_resource_record.nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
8043                         (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
8044                         continue;
8045 
8046                     /* Check the RR class, Ignore the top bit.  */
8047                     if ((p -> nx_mdns_rr_class != (temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
8048                         ((temp_resource_record.nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)!= NX_MDNS_RR_CLASS_ALL))
8049                         continue;
8050 
8051 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8052 
8053                     /* Update the match count.  */
8054                     match_count ++;
8055 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8056 
8057                     /* Check the state.  */
8058                     if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8059                         (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING))
8060                     {
8061 
8062                         /* Check the send flag, Flag is set indicate this resource record shoud be sent.  */
8063                         if (p -> nx_mdns_rr_send_flag)
8064                         {
8065 
8066                             /* Set the flag to send this Resource records via multicast.
8067                             Store the old flag into the top bits.
8068                             Store the new flag into the low bits.
8069                             Format: 0001 0001 */
8070                             p -> nx_mdns_rr_send_flag = ((NX_MDNS_RR_SEND_MULTICAST << 4) | NX_MDNS_RR_SEND_MULTICAST);
8071                         }
8072                         else
8073                         {
8074 
8075                             /* Set the flag to send this Resource records via multicast.*/
8076                             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8077                         }
8078 
8079                         /* In the case where the query has the TC (truncated) bit set, indicating that subsequent Known-Answer packets will follow,
8080                            Responders SHOULD delay their responses by a random amount of time selected with uniform random distribution in the range 400-500ms. RFC6762, Section6, Page 15.  */
8081                         if (mdns_flags & NX_MDNS_TC_FLAG)
8082                         {
8083                             p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_TC_DELAY_RANGE));
8084                         }
8085                         else
8086                         {
8087 
8088                             /* A mDNS responder is only required to delay its transmission as necessary to ensure an interval of at least 250ms
8089                             since the last time the record was multicast on that interface.  RFC6762, Section6, Page16 */
8090                             if (authority_count)
8091                             {
8092                                 if (p -> nx_mdns_rr_response_interval > (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT))
8093                                     p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT));
8094                                 else
8095                                     p -> nx_mdns_rr_response_interval = 0;
8096                             }
8097 
8098                             /* Check the response interval.  */
8099                             if (p -> nx_mdns_rr_response_interval <= NX_MDNS_TIMER_COUNT_RANGE)
8100                             {
8101 
8102                                 /* Set the timer count according to the resource record set.RFC6762, Section6, Page14.  */
8103                                 if ((p ->nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) == NX_MDNS_RR_FLAG_UNIQUE)
8104                                 {
8105                                     p -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8106                                 }
8107                                 else
8108                                 {
8109                                     /* Set the timer count, delay 20-120ms.  */
8110                                     p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8111                                 }
8112                             }
8113                             else
8114                             {
8115                                 p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_response_interval;
8116                             }
8117                         }
8118 
8119                         /* Set the mDNS timer.  */
8120                         _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
8121                     }
8122                 }
8123 
8124 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
8125                 /* Send this NSEC response as additional answer.  */
8126                 if ((match_count == 0) && (nsec_rr))
8127                 {
8128                     nsec_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_additional_send = NX_TRUE;
8129                     nsec_rr -> nx_mdns_rr_timer_count = NX_MDNS_RESPONSE_UNIQUE_DELAY;
8130                     _nx_mdns_timer_set(mdns_ptr, nsec_rr, nsec_rr -> nx_mdns_rr_timer_count);
8131                 }
8132 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
8133             }
8134 #endif /* NX_MDNS_DISABLE_SERVER */
8135 
8136             /* Update the data_ptr.  */
8137             data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4);
8138         }
8139     }
8140 
8141     /* Process all the Known-Answer records.  */
8142     for (index = 0; index < answer_count; index++)
8143     {
8144 
8145         /* Check for data_ptr.  */
8146         if (data_ptr >= packet_ptr -> nx_packet_append_ptr)
8147             break;
8148 
8149         if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
8150         {
8151 
8152 #ifndef NX_MDNS_DISABLE_SERVER
8153             /* Step1, Cooperating Multicast DNS Responders, RFC6762, Section6.6, Page21. */
8154             /* Does the same rname and rdata name of resource record exist in the local buffer.  */
8155             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8156             {
8157 
8158                 /* Find the same rname, rrtype, rrclass of resource record in local buffer.  */
8159                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8160                 {
8161 
8162                     /* Probing state, conflict Resolution.  */
8163                     if ((rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) &&
8164                         (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING))
8165                     {
8166                         _nx_mdns_conflict_process(mdns_ptr, rr_search);
8167 
8168                         /* Update the data_ptr.  */
8169                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8170 
8171                         continue;
8172                     }
8173                 }
8174 
8175                 /* Find the same rname, rrtype, rrclass and identical rdata of resource record in local buffer.  */
8176                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8177                 {
8178 
8179                     /* If the TTL in this record(B) is less than half the true TTL in local record(A), A MUST announce local record via multicast. RFC6762, Section6.6,Page21.  */
8180                     if ((temp_resource_record.nx_mdns_rr_ttl << 1) < rr_search -> nx_mdns_rr_ttl)
8181                     {
8182 
8183                         /* Set the flag.  */
8184                         rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST;
8185 
8186                         /* Set the timer count, delay 20-120ms.  */
8187                         rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE));
8188 
8189                         /* Set the mDNS timer.  */
8190                         _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count);
8191                     }
8192 
8193                     /* Duplicate Answer Suppression, RFC6762, Section7.4,Page24.
8194                        The TTL in that record is not less than the TTL this host would have given. Host should not send this response again.  */
8195                     if (temp_resource_record.nx_mdns_rr_ttl >= rr_search -> nx_mdns_rr_ttl)
8196                     {
8197 
8198                         if (rr_search -> nx_mdns_rr_send_flag)
8199                         {
8200 
8201                             /* Clear the flag.  */
8202                             rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8203                         }
8204                     }
8205 
8206                     /* Check the resource records set.  */
8207                     if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8208                     {
8209 
8210                         /* Update the data_ptr.  */
8211                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8212 
8213                         continue;
8214                     }
8215                 }
8216             }
8217 
8218             /* Did the same name of resource record have existed in local buffer.  */
8219             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8220             {
8221 
8222                 /* Find the same name, rrtype, rrclass and different rdata of resource record in local buffer.  */
8223                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8224                 {
8225 
8226                     /* Check the resource records set. RFC6762, Section6.6, Page21.  */
8227                     if (rr_search -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
8228                     {
8229                         _nx_mdns_conflict_process(mdns_ptr, rr_search);
8230 
8231                         /* Update the data_ptr.  */
8232                         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8233 
8234                         continue;
8235                     }
8236                 }
8237             }
8238 #endif /* NX_MDNS_DISABLE_SERVER */
8239 
8240 #ifndef NX_MDNS_DISABLE_CLIENT
8241             /* Step2. Add the response resource records in remote buffer.  */
8242             _nx_mdns_packet_rr_process(mdns_ptr, packet_ptr, data_ptr, interface_index);
8243 #endif /* NX_MDNS_DISABLE_CLIENT */
8244         }
8245         else
8246         {
8247 #ifndef NX_MDNS_DISABLE_CLIENT
8248             /* Clear the record.  */
8249 
8250             /* Step1, mDNS Client process the Known-Answer about Duplicate Question Suppression.  */
8251             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_PEER_SET_QUESTION, interface_index) == NX_MDNS_SUCCESS)
8252             {
8253 
8254                 /* Find the same resource record in remote buffer.  */
8255                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, NX_MDNS_RR_MATCH_EXCEPT_RDATA, &rr_search) == NX_MDNS_SUCCESS)
8256                 {
8257 
8258                     /* Duplicate Question Suppression.  */
8259                     if (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
8260                     {
8261 
8262                         /* Yes, the query includes the Known-Answer Section, clear the duplicate flag.  */
8263                         rr_search -> nx_mdns_rr_word = (USHORT)(rr_search -> nx_mdns_rr_word & ~NX_MDNS_RR_FLAG_DUPLICATE_QUERY);
8264                     }
8265 
8266 #ifdef NX_MDNS_ENABLE_CLIENT_POOF
8267                     /* Passive Observation Of Failures, RFC6762, Section10.5, Page38. */
8268                     if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8269                         (rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE))
8270                     {
8271                         rr_search -> nx_mdns_rr_poof_count --;
8272 
8273                         /* Check the count.  */
8274                         if ((rr_search -> nx_mdns_rr_state == NX_MDNS_RR_STATE_POOF_DELETE) &&
8275                             (rr_search -> nx_mdns_rr_poof_count < NX_MDNS_POOF_MIN_COUNT))
8276                         {
8277                             rr_search -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
8278                             rr_search -> nx_mdns_rr_timer_count = 0;
8279                         }
8280                     }
8281 #endif /* NX_MDNS_ENABLE_CLIENT_POOF */
8282                 }
8283             }
8284 #endif /* NX_MDNS_DISABLE_CLIENT */
8285 
8286 #ifndef NX_MDNS_DISABLE_SERVER
8287 
8288             /* Step2. mDNS Server process the Known-Answer of normal query.  */
8289             if (_nx_mdns_packet_rr_set(mdns_ptr, packet_ptr, data_ptr, &temp_resource_record, NX_MDNS_RR_OP_LOCAL_SET_ANSWER, interface_index) == NX_MDNS_SUCCESS)
8290             {
8291 
8292                 /* Find the same resource record.  */
8293                 if(_nx_mdns_cache_find_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_resource_record, NX_MDNS_RR_MATCH_ALL, &rr_search) == NX_MDNS_SUCCESS)
8294                 {
8295 
8296                     /* mDNS responder Must Not answer a mDNS query if the answer included the Answer Section with an RR TTL at least half the correct value.  RFC6762, Section7.1, Page23.  */
8297                     if ((!(rr_search -> nx_mdns_rr_send_flag & NX_MDNS_RR_SEND_FLAG_MASK)) &&
8298                         ((temp_resource_record.nx_mdns_rr_ttl << 1) >= rr_search -> nx_mdns_rr_ttl))
8299                     {
8300 
8301                         /* Top four bit is zero and this resource reocrd is Known answer.
8302                         Clear the send flag. */
8303                         rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8304                     }
8305                 }
8306             }
8307 #endif /* NX_MDNS_DISABLE_SERVER */
8308         }
8309 
8310         /* Update the data_ptr.  */
8311         data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr);
8312     }
8313 
8314     return(NX_MDNS_SUCCESS);
8315 }
8316 
8317 
8318 #ifndef NX_MDNS_DISABLE_SERVER
8319 /**************************************************************************/
8320 /*                                                                        */
8321 /*  FUNCTION                                               RELEASE        */
8322 /*                                                                        */
8323 /*    _nx_mdns_probing_send                               PORTABLE C      */
8324 /*                                                           6.1          */
8325 /*  AUTHOR                                                                */
8326 /*                                                                        */
8327 /*    Yuxin Zhou, Microsoft Corporation                                   */
8328 /*                                                                        */
8329 /*  DESCRIPTION                                                           */
8330 /*                                                                        */
8331 /*    This function sends mDNS probing message.                           */
8332 /*                                                                        */
8333 /*  INPUT                                                                 */
8334 /*                                                                        */
8335 /*    mdns_ptr                              Pointer to mDNS instance      */
8336 /*                                                                        */
8337 /*  OUTPUT                                                                */
8338 /*                                                                        */
8339 /*    none                                                                */
8340 /*                                                                        */
8341 /*  CALLS                                                                 */
8342 /*                                                                        */
8343 /*                                                                        */
8344 /*  CALLED BY                                                             */
8345 /*                                                                        */
8346 /*                                                                        */
8347 /*  RELEASE HISTORY                                                       */
8348 /*                                                                        */
8349 /*    DATE              NAME                      DESCRIPTION             */
8350 /*                                                                        */
8351 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8352 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8353 /*                                            resulting in version 6.1    */
8354 /*                                                                        */
8355 /**************************************************************************/
_nx_mdns_probing_send(NX_MDNS * mdns_ptr,UINT interface_index)8356 static VOID    _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8357 {
8358 
8359 UINT                status;
8360 NX_PACKET           *packet_ptr;
8361 ULONG               *head;
8362 NX_MDNS_RR          *p;
8363 USHORT              question_count = 0;
8364 USHORT              answer_count = 0;
8365 USHORT              authority_count = 0;
8366 USHORT              additional_count = 0;
8367 UCHAR               resend_flag = NX_FALSE;
8368 USHORT              total_size;
8369 USHORT              rr_size;
8370 UINT                name_size;
8371 NX_MDNS_RR          *p1;
8372 UINT                rr_name_length;
8373 
8374 
8375     /* Create the mdns packet and add the mDNS header.  */
8376     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8377 
8378     /* Check for errors. */
8379     if (status != NX_SUCCESS)
8380     {
8381         return;
8382     }
8383 
8384     /* Set the total size.  */
8385     total_size = (USHORT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
8386 
8387     /* Set the head pointer. */
8388     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8389 
8390     /* Add the answer resource record.  */
8391     for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8392     {
8393 
8394         /* Check the interface index.  */
8395         if (p -> nx_mdns_rr_interface_index != interface_index)
8396             continue;
8397 
8398         /* Check the send flag.  */
8399         if (p -> nx_mdns_rr_send_flag == 0)
8400             continue;
8401 
8402         /* Check the state. */
8403         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8404             continue;
8405 
8406         /* Add the resource record into packet.  */
8407 
8408         /* Calculate the question and answer size before sending the probing message, make sure the question and authority in one packet.  */
8409 
8410         /* Check string length.  */
8411         if (_nx_utility_string_length_check((CHAR *)p -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
8412         {
8413             continue;
8414         }
8415 
8416         /* Calculate the name size. The name should plus the '.' and '\0'. */
8417         name_size = rr_name_length + 2;
8418 
8419         /* Calculate the resource record size for question. QNAME, QTYPE, QCLASS.  */
8420         rr_size = (USHORT)(name_size + 4);
8421 
8422         /* Calcuate the resource record size for authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
8423         rr_size = (USHORT)(rr_size + (name_size + 10 + p -> nx_mdns_rr_rdata_length));
8424 
8425         /* Check if need add other authority answers for this same question.  */
8426         for(p1 = (NX_MDNS_RR*)(head + 1); (ULONG)p1 < *head; p1++)
8427         {
8428 
8429             /* Check the interface index.  */
8430             if (p1 -> nx_mdns_rr_interface_index != interface_index)
8431                 continue;
8432 
8433             /* Check the state.  */
8434             if (p1 -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
8435                 continue;
8436 
8437             /* Check the name and flag.  */
8438             if ((p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_name) &&
8439                 (p1 -> nx_mdns_rr_send_flag) &&
8440                 (p1 != p))
8441             {
8442 
8443                 /* Calculate the resource record size for other authority. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
8444                 rr_size = (USHORT)(rr_size + (name_size + 10 + p1 -> nx_mdns_rr_rdata_length));
8445 
8446                 /* Check the packet size.  */
8447                 if (rr_size <= total_size)
8448                 {
8449 
8450                     /* Set the authority answer flag.  */
8451                     p1 -> nx_mdns_rr_word = p1 -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8452 
8453                     /* Clear the send flag.  */
8454                     p1 -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8455                 }
8456                 else
8457                 {
8458                     resend_flag = NX_TRUE;
8459                     break;
8460                 }
8461             }
8462         }
8463 
8464         /* Check the packet size.  */
8465         if (rr_size > total_size)
8466         {
8467             resend_flag = NX_TRUE;
8468             continue;
8469         }
8470         else
8471             total_size = (USHORT)(total_size - rr_size);
8472 
8473         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_PROBING);
8474 
8475         if (status)
8476         {
8477             resend_flag = NX_TRUE;
8478         }
8479         else
8480         {
8481 
8482             /* Set the authority answer flag.  */
8483             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_AUTHORIY_ANSWER;
8484 
8485             /* Update the question count.  */
8486             question_count ++;
8487 
8488             /* Clear the flag.  */
8489             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8490         }
8491     }
8492 
8493     /* Add the authority answer resource record.  */
8494     for (p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8495     {
8496 
8497         /* Check the interface index.  */
8498         if (p -> nx_mdns_rr_interface_index != interface_index)
8499             continue;
8500 
8501         /* Check whether set the resource record send flag. */
8502         if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_PROBING) &&
8503             (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_AUTHORIY_ANSWER))
8504         {
8505 
8506             /* Add the resource record into packet.  */
8507             status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_PROBING);
8508             if (status)
8509                 resend_flag = NX_TRUE;
8510             else
8511             {
8512 
8513                 /* Update the retransmit count.  */
8514                 p -> nx_mdns_rr_retransmit_count --;
8515 
8516                 /* Update the authority count.  */
8517                 authority_count ++;
8518 
8519                 /* Clear the additional flag.  */
8520                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_AUTHORIY_ANSWER));
8521             }
8522         }
8523 
8524         /* Clear the answer flag.  */
8525         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8526     }
8527 
8528     if (!question_count &&
8529         !answer_count &&
8530         !authority_count &&
8531         !additional_count)
8532     {
8533 
8534         /* Release the packet.  */
8535         nx_packet_release(packet_ptr);
8536         return;
8537     }
8538 
8539     /* Update the question count in header.  */
8540     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8541 
8542     /* Update the answer count in header.  */
8543     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8544     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8545     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8546 
8547     /* Send the mDNS packet.  */
8548     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8549 
8550     /* Resend the packet.  */
8551     if (resend_flag)
8552         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_PROBING_SEND_EVENT, TX_OR);
8553 }
8554 
8555 
8556 /**************************************************************************/
8557 /*                                                                        */
8558 /*  FUNCTION                                               RELEASE        */
8559 /*                                                                        */
8560 /*    _nx_mdns_announcing_send                            PORTABLE C      */
8561 /*                                                           6.1          */
8562 /*  AUTHOR                                                                */
8563 /*                                                                        */
8564 /*    Yuxin Zhou, Microsoft Corporation                                   */
8565 /*                                                                        */
8566 /*  DESCRIPTION                                                           */
8567 /*                                                                        */
8568 /*    This function sends mDNS announcing message.                        */
8569 /*                                                                        */
8570 /*  INPUT                                                                 */
8571 /*                                                                        */
8572 /*    mdns_ptr                              Pointer to mDNS instance      */
8573 /*                                                                        */
8574 /*  OUTPUT                                                                */
8575 /*                                                                        */
8576 /*    status                                Completion status             */
8577 /*                                                                        */
8578 /*  CALLS                                                                 */
8579 /*                                                                        */
8580 /*                                                                        */
8581 /*  CALLED BY                                                             */
8582 /*                                                                        */
8583 /*                                                                        */
8584 /*  RELEASE HISTORY                                                       */
8585 /*                                                                        */
8586 /*    DATE              NAME                      DESCRIPTION             */
8587 /*                                                                        */
8588 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8589 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8590 /*                                            resulting in version 6.1    */
8591 /*                                                                        */
8592 /**************************************************************************/
_nx_mdns_announcing_send(NX_MDNS * mdns_ptr,UINT interface_index)8593 static VOID    _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index)
8594 {
8595 
8596 UINT                status;
8597 NX_PACKET           *packet_ptr;
8598 NX_PACKET           *new_packet_ptr;
8599 ULONG               *head;
8600 NX_MDNS_RR          *p;
8601 USHORT              question_count = 0;
8602 USHORT              answer_count = 0;
8603 USHORT              authority_count = 0;
8604 USHORT              additional_count = 0;
8605 UINT                i;
8606 UCHAR               resend_flag = NX_FALSE;
8607 
8608 
8609     /* Create the mdns packet and add the mDNS header.  */
8610     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8611 
8612     /* Check for errors. */
8613     if (status != NX_SUCCESS)
8614     {
8615         return;
8616     }
8617 
8618     /* Set the head pointer. */
8619     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8620 
8621     /* Add the answer resource record.  */
8622     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8623     {
8624 
8625         /* Check the interface index.  */
8626         if (p -> nx_mdns_rr_interface_index != interface_index)
8627             continue;
8628 
8629         if(p -> nx_mdns_rr_send_flag == 0)
8630             continue;
8631 
8632         /* Check valid state. */
8633         if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE) ||
8634               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8635               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID))))
8636             continue;
8637 
8638         /* Add the resource record into packet.  */
8639         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8640 
8641         if (status)
8642         {
8643             resend_flag = NX_TRUE;
8644         }
8645         else
8646         {
8647 
8648             /* Update the retransmit count.  */
8649             p -> nx_mdns_rr_retransmit_count --;
8650 
8651             /* Update the count.  */
8652             answer_count++;
8653 
8654             /* Clear the flag.  */
8655             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8656         }
8657     }
8658 
8659     if (!question_count &&
8660         !answer_count &&
8661         !authority_count &&
8662         !additional_count)
8663     {
8664 
8665         /* Release the packet.  */
8666         nx_packet_release(packet_ptr);
8667         return;
8668     }
8669 
8670     /* Update the question count in header.  */
8671     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8672 
8673     /* Update the answer count in header.  */
8674     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8675     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8676     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8677 
8678     /* If the interval time is 0, repeat advertise.  */
8679     if (!mdns_ptr -> nx_mdns_announcing_retrans_interval)
8680     {
8681         for (i = 1; i < mdns_ptr -> nx_mdns_announcing_count; i ++)
8682         {
8683 
8684             /* Allocate new packet.  */
8685             status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
8686 
8687             /* Check for errors. */
8688             if (status)
8689             {
8690                 break;
8691             }
8692 
8693             /* Send the mDNS packet.  */
8694             _nx_mdns_packet_send(mdns_ptr, new_packet_ptr, interface_index);
8695         }
8696     }
8697 
8698     /* Send the mDNS packet.  */
8699     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8700 
8701     /* Resend the packet.  */
8702     if (resend_flag)
8703         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_ANNOUNCING_SEND_EVENT, TX_OR);
8704 
8705     return;
8706 }
8707 
8708 
8709 /**************************************************************************/
8710 /*                                                                        */
8711 /*  FUNCTION                                               RELEASE        */
8712 /*                                                                        */
8713 /*    _nx_mdns_response_send                              PORTABLE C      */
8714 /*                                                           6.1          */
8715 /*  AUTHOR                                                                */
8716 /*                                                                        */
8717 /*    Yuxin Zhou, Microsoft Corporation                                   */
8718 /*                                                                        */
8719 /*  DESCRIPTION                                                           */
8720 /*                                                                        */
8721 /*    This function sends mDNS response.                                  */
8722 /*                                                                        */
8723 /*  INPUT                                                                 */
8724 /*                                                                        */
8725 /*    mdns_ptr                              Pointer to mDNS instance      */
8726 /*                                                                        */
8727 /*  OUTPUT                                                                */
8728 /*                                                                        */
8729 /*    none                                                                */
8730 /*                                                                        */
8731 /*  CALLS                                                                 */
8732 /*                                                                        */
8733 /*                                                                        */
8734 /*  CALLED BY                                                             */
8735 /*                                                                        */
8736 /*                                                                        */
8737 /*  RELEASE HISTORY                                                       */
8738 /*                                                                        */
8739 /*    DATE              NAME                      DESCRIPTION             */
8740 /*                                                                        */
8741 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8742 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8743 /*                                            resulting in version 6.1    */
8744 /*                                                                        */
8745 /**************************************************************************/
_nx_mdns_response_send(NX_MDNS * mdns_ptr,UINT interface_index)8746 static VOID    _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index)
8747 {
8748 
8749 UINT                status;
8750 NX_PACKET           *packet_ptr;
8751 ULONG               *head;
8752 NX_MDNS_RR          *p;
8753 USHORT              question_count = 0;
8754 USHORT              answer_count = 0;
8755 USHORT              authority_count = 0;
8756 USHORT              additional_count = 0;
8757 UCHAR               resend_flag = NX_FALSE;
8758 
8759 
8760     /* Create the mdns packet and add the mDNS header.  */
8761     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_FALSE);
8762 
8763     /* Check for errors. */
8764     if (status != NX_SUCCESS)
8765     {
8766         return;
8767     }
8768 
8769     /* Set the head pointer. */
8770     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8771 
8772     /* Add the answer resource record.  */
8773     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8774     {
8775 
8776         /* Check the interface index.  */
8777         if (p -> nx_mdns_rr_interface_index != interface_index)
8778             continue;
8779 
8780         if(p -> nx_mdns_rr_send_flag == 0)
8781             continue;
8782 
8783         /* Check valid state. */
8784         if ((p -> nx_mdns_rr_timer_count != 0) ||
8785              !((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING) ||
8786                (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID)))
8787             continue;
8788 
8789         /* Add the resource record into packet.  */
8790         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8791 
8792         if (status)
8793         {
8794             resend_flag = NX_TRUE;
8795         }
8796         else
8797         {
8798 
8799             /* Set the answer flag to skip the resource record which has been added in answer section when find the additional records.  */
8800             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ANSWER;
8801 
8802             /* When including a DNS-SD Service Instance Enumeration or Selective Instance Enumeration PTR record in a response packet,
8803                the server/responder SHOULD include the folowing additional records, SRV,TXT, A and AAAA.RFC3763, Section12.1, Page30.  */
8804             _nx_mdns_additional_resource_record_find(mdns_ptr, p);
8805 
8806             /* Update the count.  */
8807             answer_count++;
8808 
8809             /* Clear the flag.  */
8810             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8811         }
8812     }
8813 
8814     /* Add the additional answer resource record.  */
8815     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8816     {
8817 
8818         /* Check the interface index.  */
8819         if (p -> nx_mdns_rr_interface_index != interface_index)
8820             continue;
8821 
8822         /* Check whether set the resource record send flag. */
8823         if ((p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ADDITIONAL) &&
8824             ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
8825              (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)))
8826         {
8827 
8828             /* Add the resource record into packet.  */
8829             status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_RESPONSE);
8830             if (status)
8831             {
8832                 resend_flag = NX_TRUE;
8833             }
8834             else
8835             {
8836 
8837                 /* Update the additional count.  */
8838                 additional_count++;
8839 
8840                 /* Clear the additional flag.  */
8841                 p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ADDITIONAL));
8842             }
8843         }
8844 
8845         /* Clear the answer flag.  */
8846         p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
8847     }
8848 
8849     if (!question_count &&
8850         !answer_count &&
8851         !authority_count &&
8852         !additional_count)
8853     {
8854 
8855         /* Release the packet.  */
8856         nx_packet_release(packet_ptr);
8857         return;
8858     }
8859 
8860     /* Update the question count in header.  */
8861     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
8862 
8863     /* Update the answer count in header.  */
8864     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
8865     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
8866     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
8867 
8868     /* Send the mDNS packet.  */
8869     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
8870 
8871     /* Resend the packet.  */
8872     if (resend_flag)
8873         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_RESPONSE_SEND_EVENT, TX_OR);
8874 }
8875 #endif /* NX_MDNS_DISABLE_SERVER */
8876 
8877 
8878 #ifndef NX_MDNS_DISABLE_CLIENT
8879 /**************************************************************************/
8880 /*                                                                        */
8881 /*  FUNCTION                                               RELEASE        */
8882 /*                                                                        */
8883 /*    _nx_mdns_query_send                                 PORTABLE C      */
8884 /*                                                           6.1          */
8885 /*  AUTHOR                                                                */
8886 /*                                                                        */
8887 /*    Yuxin Zhou, Microsoft Corporation                                   */
8888 /*                                                                        */
8889 /*  DESCRIPTION                                                           */
8890 /*                                                                        */
8891 /*    This function sends mDNS query message.                             */
8892 /*                                                                        */
8893 /*  INPUT                                                                 */
8894 /*                                                                        */
8895 /*    mdns_ptr                              Pointer to mDNS instance      */
8896 /*                                                                        */
8897 /*  OUTPUT                                                                */
8898 /*                                                                        */
8899 /*    none                                                                */
8900 /*                                                                        */
8901 /*  CALLS                                                                 */
8902 /*                                                                        */
8903 /*                                                                        */
8904 /*  CALLED BY                                                             */
8905 /*                                                                        */
8906 /*                                                                        */
8907 /*  RELEASE HISTORY                                                       */
8908 /*                                                                        */
8909 /*    DATE              NAME                      DESCRIPTION             */
8910 /*                                                                        */
8911 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8912 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8913 /*                                            resulting in version 6.1    */
8914 /*                                                                        */
8915 /**************************************************************************/
_nx_mdns_query_send(NX_MDNS * mdns_ptr,UINT interface_index)8916 static VOID    _nx_mdns_query_send(NX_MDNS *mdns_ptr, UINT interface_index)
8917 {
8918 
8919 UINT                status;
8920 NX_PACKET           *packet_ptr;
8921 ULONG               *head;
8922 NX_MDNS_RR          *p;
8923 USHORT              question_count = 0;
8924 USHORT              answer_count = 0;
8925 USHORT              authority_count = 0;
8926 USHORT              additional_count = 0;
8927 UCHAR               resend_flag = NX_FALSE;
8928 USHORT              tc_bit;
8929 UCHAR               more_known_answer = NX_FALSE;
8930 UINT                i;
8931 
8932 
8933     /* Create the mdns packet and add the mDNS header.  */
8934     status = _nx_mdns_packet_create(mdns_ptr, &packet_ptr, NX_TRUE);
8935 
8936     /* Check for errors. */
8937     if (status != NX_SUCCESS)
8938     {
8939         return;
8940     }
8941 
8942     /* Set the head pointer. */
8943     head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
8944 
8945     /* Add the query resource record.  */
8946     for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
8947     {
8948 
8949         /* Check the interface index.  */
8950         if (p -> nx_mdns_rr_interface_index != interface_index)
8951             continue;
8952 
8953         if(p -> nx_mdns_rr_send_flag == 0)
8954             continue;
8955 
8956         /* Check valid state. */
8957         if(!(((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY) ||
8958               (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING))))
8959             continue;
8960 
8961         /* Add the resource record into packet.  */
8962         status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_QUESTION, NX_MDNS_PACKET_QUERY);
8963 
8964         if (status)
8965         {
8966             resend_flag = NX_TRUE;
8967         }
8968         else
8969         {
8970 
8971             /* Update the retransmit count for UPDATING state.  */
8972             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_UPDATING)
8973                 p -> nx_mdns_rr_retransmit_count --;
8974 
8975             /* Update the count.  */
8976             question_count++;
8977 
8978             /* Find the known answer resource records.  */
8979             _nx_mdns_known_answer_find(mdns_ptr, p);
8980 
8981             /* Clear the flag.  */
8982             p -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_FLAG_CLEAR;
8983         }
8984     }
8985 
8986     /* Add the known answer resource record.  */
8987     for (i = 0; i < 2; i++)
8988     {
8989         if (i == 0)
8990         {
8991 #ifndef NX_MDNS_DISABLE_SERVER
8992             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
8993 #else
8994             continue;
8995 #endif /* NX_MDNS_DISABLE_SERVER  */
8996         }
8997         else
8998         {
8999             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
9000         }
9001 
9002         /* Add the peer resource code as known answer for query.  */
9003         for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
9004         {
9005 
9006             /* Check the interface index.  */
9007             if (p -> nx_mdns_rr_interface_index != interface_index)
9008                 continue;
9009 
9010             /* Check whether set the resource record send flag. */
9011             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) &&
9012                 (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_KNOWN_ANSWER))
9013             {
9014 
9015                 /* Add the resource record into packet.  */
9016                 status = _nx_mdns_packet_rr_add(packet_ptr, p, NX_MDNS_PACKET_ADD_RR_ANSWER, NX_MDNS_PACKET_QUERY);
9017                 if (status)
9018                 {
9019                     more_known_answer = NX_TRUE;
9020                     resend_flag = NX_TRUE;
9021                 }
9022                 else
9023                 {
9024                     /* Update the count.  */
9025                     answer_count ++;
9026 
9027                     /* Clear the additional flag.  */
9028                     p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_KNOWN_ANSWER));
9029                 }
9030             }
9031 
9032             /* Clear the answer flag.  */
9033             p -> nx_mdns_rr_word = (USHORT)(p -> nx_mdns_rr_word & (~NX_MDNS_RR_FLAG_ANSWER));
9034         }
9035     }
9036 
9037     if (!question_count &&
9038         !answer_count &&
9039         !authority_count &&
9040         !additional_count)
9041     {
9042 
9043         /* Release the packet.  */
9044         nx_packet_release(packet_ptr);
9045         return;
9046     }
9047 
9048     /* Set the TC bit.  */
9049     if (more_known_answer)
9050     {
9051         tc_bit = NX_MDNS_TC_FLAG;
9052          *(USHORT *)(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) |= NX_CHANGE_USHORT_ENDIAN(tc_bit);
9053     }
9054 
9055     /* Update the question count in header.  */
9056     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET, question_count);
9057 
9058     /* Update the answer count in header.  */
9059     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ANCOUNT_OFFSET, answer_count);
9060     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET, authority_count);
9061     _nx_mdns_short_to_network_convert(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_ARCOUNT_OFFSET, additional_count);
9062 
9063     /* Send the mDNS packet.  */
9064     _nx_mdns_packet_send(mdns_ptr, packet_ptr, interface_index);
9065 
9066     /* Resend the packet.  */
9067     if (resend_flag)
9068         tx_event_flags_set(&(mdns_ptr -> nx_mdns_events), NX_MDNS_QUERY_SEND_EVENT, TX_OR);
9069 }
9070 #endif /* NX_MDNS_DISABLE_CLIENT  */
9071 
9072 
9073 /**************************************************************************/
9074 /*                                                                        */
9075 /*  FUNCTION                                               RELEASE        */
9076 /*                                                                        */
9077 /*    _nx_mdns_packet_create                              PORTABLE C      */
9078 /*                                                           6.1          */
9079 /*  AUTHOR                                                                */
9080 /*                                                                        */
9081 /*    Yuxin Zhou, Microsoft Corporation                                   */
9082 /*                                                                        */
9083 /*  DESCRIPTION                                                           */
9084 /*                                                                        */
9085 /*    This function creates the mDNS packet and add the mDNS header data. */
9086 /*                                                                        */
9087 /*  INPUT                                                                 */
9088 /*                                                                        */
9089 /*    mdns_ptr                              Pointer to mDNS instance      */
9090 /*    packet_ptr                            Pointer to mDNS packet        */
9091 /*    is_query                              Query flag                    */
9092 /*                                                                        */
9093 /*  OUTPUT                                                                */
9094 /*                                                                        */
9095 /*    status                                Completion status             */
9096 /*                                                                        */
9097 /*  CALLS                                                                 */
9098 /*                                                                        */
9099 /*    nx_packet_allocate                    Allocate the mDNS packet      */
9100 /*    nx_packet_release                     Release the mDNS packet       */
9101 /*    _nx_mdns_short_to_network_convert     Add the data into the packet  */
9102 /*                                                                        */
9103 /*  CALLED BY                                                             */
9104 /*                                                                        */
9105 /*    _nx_mdns_announcing_send              Send announcing message       */
9106 /*    _nx_mdns_probing_send                 Send probing message          */
9107 /*    _nx_mdns_query_send                   Send query message            */
9108 /*    _nx_mdns_response_send                Send response message         */
9109 /*                                                                        */
9110 /*  RELEASE HISTORY                                                       */
9111 /*                                                                        */
9112 /*    DATE              NAME                      DESCRIPTION             */
9113 /*                                                                        */
9114 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9115 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9116 /*                                            resulting in version 6.1    */
9117 /*                                                                        */
9118 /**************************************************************************/
_nx_mdns_packet_create(NX_MDNS * mdns_ptr,NX_PACKET ** packet_ptr,UCHAR is_query)9119 static UINT    _nx_mdns_packet_create(NX_MDNS *mdns_ptr, NX_PACKET **packet_ptr, UCHAR is_query)
9120 {
9121 
9122 UINT        status;
9123 USHORT      flags;
9124 
9125 
9126     /* Allocate the mDNS packet.  */
9127 #ifdef NX_MDNS_ENABLE_IPV6
9128     status =  nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv6_UDP_PACKET, NX_NO_WAIT);
9129 #else
9130     status =  nx_packet_allocate(mdns_ptr -> nx_mdns_packet_pool_ptr, packet_ptr, NX_IPv4_UDP_PACKET, NX_NO_WAIT);
9131 #endif /* NX_MDNS_ENABLE_IPV6  */
9132 
9133     /* Check for errors. */
9134     if (status)
9135     {
9136 
9137         /* Return error.  */
9138         return(status);
9139     }
9140 
9141     /* Check if there is enough room to fill with mDNS header.  */
9142     if ((UINT)((*packet_ptr) -> nx_packet_data_end - (*packet_ptr) -> nx_packet_append_ptr) < NX_MDNS_QDSECT_OFFSET)
9143     {
9144 
9145         /* Release the packet.  */
9146         nx_packet_release(*packet_ptr);
9147         return(NX_MDNS_PACKET_ERROR);
9148     }
9149 
9150     /* Add the mDNS header.  */
9151 
9152     /* Set the transaction ID.  */
9153     *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_ID_OFFSET) = 0;
9154 
9155     /* Set the flags and Command.  */
9156     if (is_query == NX_TRUE)
9157     {
9158         flags = NX_MDNS_QUERY_FLAG;
9159     }
9160     else
9161     {
9162         flags = (NX_MDNS_RESPONSE_FLAG | NX_MDNS_AA_FLAG);
9163     }
9164 
9165     /* Adjust for endianness. */
9166     NX_CHANGE_USHORT_ENDIAN(flags);
9167 
9168     /* Set the flags and Command.  */
9169     *(USHORT *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET) = flags;
9170 
9171     /* Initialize counts to 0.  */
9172     *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDCOUNT_OFFSET) = 0;
9173     *(ULONG *)((*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_NSCOUNT_OFFSET) = 0;
9174 
9175     /* Set the pointer.  */
9176     (*packet_ptr) -> nx_packet_append_ptr = (*packet_ptr) -> nx_packet_prepend_ptr + NX_MDNS_QDSECT_OFFSET;
9177     (*packet_ptr) -> nx_packet_length = NX_MDNS_QDSECT_OFFSET;
9178 
9179     return(NX_MDNS_SUCCESS);
9180 }
9181 
9182 
9183 /**************************************************************************/
9184 /*                                                                        */
9185 /*  FUNCTION                                               RELEASE        */
9186 /*                                                                        */
9187 /*    _nx_mdns_packet_send                                PORTABLE C      */
9188 /*                                                           6.1          */
9189 /*  AUTHOR                                                                */
9190 /*                                                                        */
9191 /*    Yuxin Zhou, Microsoft Corporation                                   */
9192 /*                                                                        */
9193 /*  DESCRIPTION                                                           */
9194 /*                                                                        */
9195 /*    This function sends the mDNS packet.                                */
9196 /*                                                                        */
9197 /*  INPUT                                                                 */
9198 /*                                                                        */
9199 /*    mdns_ptr                              Pointer to mDNS instance      */
9200 /*    packet_ptr                            Pointer to mDNS packet        */
9201 /*                                                                        */
9202 /*  OUTPUT                                                                */
9203 /*                                                                        */
9204 /*    status                                Completion status             */
9205 /*                                                                        */
9206 /*  CALLS                                                                 */
9207 /*                                                                        */
9208 /*    nx_packet_copy                        Copy the mDNS packet          */
9209 /*    nx_packet_release                     Release the mDNS packet       */
9210 /*    nx_udp_socket_send                    Send the udp packet           */
9211 /*    nxd_udp_socket_send                   Send the udp packet           */
9212 /*                                                                        */
9213 /*  CALLED BY                                                             */
9214 /*                                                                        */
9215 /*    _nx_mdns_announcing_send              Send announcing message       */
9216 /*    _nx_mdns_probing_send                 Send probing message          */
9217 /*    _nx_mdns_query_send                   Send query message            */
9218 /*    _nx_mdns_response_send                Send response message         */
9219 /*                                                                        */
9220 /*  RELEASE HISTORY                                                       */
9221 /*                                                                        */
9222 /*    DATE              NAME                      DESCRIPTION             */
9223 /*                                                                        */
9224 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9225 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9226 /*                                            resulting in version 6.1    */
9227 /*                                                                        */
9228 /**************************************************************************/
_nx_mdns_packet_send(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UINT interface_index)9229 static VOID    _nx_mdns_packet_send(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index)
9230 {
9231 
9232 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
9233 UINT                status;
9234 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
9235 #ifdef NX_MDNS_ENABLE_IPV6
9236 UINT                ipv6_packet = NX_FALSE;
9237 NX_PACKET           *new_packet_ptr;
9238 UINT                address_index = mdns_ptr -> nx_mdns_ipv6_address_index[interface_index];
9239 #endif /*  NX_MDNS_ENABLE_IPV6  */
9240 
9241 
9242 #if defined NX_DISABLE_IPV4 && !defined NX_MDNS_ENABLE_IPV6
9243     NX_PARAMETER_NOT_USED(mdns_ptr);
9244     NX_PARAMETER_NOT_USED(interface_index);
9245 #endif /* NX_DISABLE_IPV4 && ! NX_MDNS_ENABLE_IPV6  */
9246 
9247 #ifdef NX_MDNS_ENABLE_IPV6
9248     if (address_index != 0xFFFFFFFF)
9249     {
9250 
9251         /* Allocate new IPv6 packet.  */
9252         status = nx_packet_copy(packet_ptr, &new_packet_ptr, mdns_ptr -> nx_mdns_packet_pool_ptr, NX_NO_WAIT);
9253 
9254         /* Check for errors. */
9255         if (!status)
9256         {
9257             ipv6_packet = NX_TRUE;
9258         }
9259     }
9260 #endif /* NX_MDNS_ENABLE_IPV6  */
9261 
9262 #ifndef NX_DISABLE_IPV4
9263     /* Send the IPv4 mDNS message.  */
9264     status =  nx_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, packet_ptr, NX_MDNS_IPV4_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, interface_index);
9265 
9266     /* If an error is detected, the packet was not sent and we have to release the packet. */
9267     if (status != NX_SUCCESS)
9268     {
9269 
9270         /* Release the packet.  */
9271         nx_packet_release(packet_ptr);
9272     }
9273 #else
9274 
9275     /* Release the packet.  */
9276     nx_packet_release(packet_ptr);
9277 #endif /* NX_DISABLE_IPV4  */
9278 
9279 #ifdef NX_MDNS_ENABLE_IPV6
9280 
9281     /* Check if send IPv6 packet.  */
9282     if (ipv6_packet == NX_TRUE)
9283     {
9284 
9285         /* Send the IPv6 mDNS message.  */
9286         status =  nxd_udp_socket_source_send(&mdns_ptr -> nx_mdns_socket, new_packet_ptr, &NX_MDNS_IPV6_MULTICAST_ADDRESS, NX_MDNS_UDP_PORT, address_index);
9287 
9288         /* If an error is detected, the packet was not sent and we have to release the packet. */
9289         if (status != NX_SUCCESS)
9290         {
9291 
9292             /* Release the packet.  */
9293             nx_packet_release(new_packet_ptr);
9294         }
9295     }
9296 #endif /* NX_MDNS_ENABLE_IPV6  */
9297 }
9298 
9299 
9300 /**************************************************************************/
9301 /*                                                                        */
9302 /*  FUNCTION                                               RELEASE        */
9303 /*                                                                        */
9304 /*    _nx_mdns_packet_rr_add                              PORTABLE C      */
9305 /*                                                           6.1          */
9306 /*  AUTHOR                                                                */
9307 /*                                                                        */
9308 /*    Yuxin Zhou, Microsoft Corporation                                   */
9309 /*                                                                        */
9310 /*  DESCRIPTION                                                           */
9311 /*                                                                        */
9312 /*    This function adds the mDNS resource record into the packet.        */
9313 /*                                                                        */
9314 /*  INPUT                                                                 */
9315 /*                                                                        */
9316 /*    mdns_ptr                              Pointer to mDNS instance      */
9317 /*    packet_ptr                            Pointer to mDNS packet        */
9318 /*    rr                                    Pointer to mDNS record        */
9319 /*    op                                    RR adding Operation           */
9320 /*    packet_type                           Packet type                   */
9321 /*                                                                        */
9322 /*  OUTPUT                                                                */
9323 /*                                                                        */
9324 /*    status                                Completion status             */
9325 /*                                                                        */
9326 /*  CALLS                                                                 */
9327 /*                                                                        */
9328 /*    _nx_mdns_name_string_encode           Encode the name string        */
9329 /*    _nx_mdns_short_to_network_convert     Convert and add the data      */
9330 /*    _nx_mdns_txt_string_encode            Encode the txt string         */
9331 /*                                                                        */
9332 /*  CALLED BY                                                             */
9333 /*                                                                        */
9334 /*    _nx_mdns_announcing_send              Send announcing message       */
9335 /*    _nx_mdns_probing_send                 Send probing message          */
9336 /*    _nx_mdns_query_send                   Send query message            */
9337 /*    _nx_mdns_response_send                Send response message         */
9338 /*                                                                        */
9339 /*  RELEASE HISTORY                                                       */
9340 /*                                                                        */
9341 /*    DATE              NAME                      DESCRIPTION             */
9342 /*                                                                        */
9343 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9344 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9345 /*                                            verified memcpy use cases,  */
9346 /*                                            resulting in version 6.1    */
9347 /*                                                                        */
9348 /**************************************************************************/
_nx_mdns_packet_rr_add(NX_PACKET * packet_ptr,NX_MDNS_RR * rr,UINT op,UINT packet_type)9349 static UINT    _nx_mdns_packet_rr_add(NX_PACKET *packet_ptr, NX_MDNS_RR *rr, UINT op, UINT packet_type)
9350 {
9351 
9352 USHORT      size = 0;
9353 USHORT      index = 0;
9354 USHORT      rr_size = 0;
9355 USHORT      rdata_length_index = 0;
9356 UCHAR       *data_ptr = packet_ptr -> nx_packet_append_ptr;
9357 UINT        rr_name_length;
9358 
9359 
9360     /* Check string length.  */
9361     if (_nx_utility_string_length_check((CHAR *)rr -> nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9362     {
9363         return (NX_MDNS_DATA_SIZE_ERROR);
9364     }
9365 
9366     /* Check whether set the resource record send flag. */
9367     if(op ==  NX_MDNS_PACKET_ADD_RR_QUESTION)
9368     {
9369 
9370         /* The name size is should add the '.' and '\0',  Calcuate the resource record size. QNAME, QTYPE, QCLASS.  */
9371         rr_size = (USHORT)(rr_name_length + 2 + 4);
9372 
9373         if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9374         {
9375             return(NX_MDNS_PACKET_ERROR);
9376         }
9377 
9378         /* Encode and add the name.  */
9379         size = (USHORT)_nx_mdns_name_string_encode(data_ptr, rr -> nx_mdns_rr_name);
9380 
9381         /* Updat the index.  */
9382         index = (USHORT)(index + size);
9383 
9384         /* Add the type.  */
9385         if(packet_type == NX_MDNS_PACKET_PROBING)
9386         {
9387             _nx_mdns_short_to_network_convert(data_ptr + index, NX_MDNS_RR_TYPE_ALL);
9388         }
9389         else
9390         {
9391             _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9392         }
9393         index = (USHORT)(index + 2);
9394 
9395         /* Add the class.  */
9396         _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9397         index = (USHORT)(index + 2);
9398     }
9399 
9400     /* Check whether set the resource record send flag. */
9401     else
9402     {
9403 
9404         /* Calcuate the resource record size. NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA.  */
9405         rr_size = (USHORT)(rr_name_length + 2 + 10 + rr -> nx_mdns_rr_rdata_length);
9406 
9407         if ((data_ptr + rr_size) > packet_ptr -> nx_packet_data_end)
9408         {
9409             return(NX_MDNS_PACKET_ERROR);
9410         }
9411 
9412         /* Encode and add the name.  */
9413         size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_name);
9414 
9415         /* Updat the index.  */
9416         index = (USHORT)(index + size);
9417 
9418         /* Add the type and class.  */
9419         _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_type);
9420         index = (USHORT)(index + 2);
9421 
9422         /* Add the class.  */
9423         if ((!(rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)) &&
9424             (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE))
9425         {
9426             _nx_mdns_short_to_network_convert(data_ptr + index, ((rr -> nx_mdns_rr_class) | NX_MDNS_RR_CLASS_TOP_BIT));
9427         }
9428         else
9429         {
9430 
9431             _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_class);
9432         }
9433         index = (USHORT)(index + 2);
9434 
9435         /* Add the ttl.  */
9436         /* Check the resource record owner.  */
9437         if (rr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_PEER)
9438         {
9439             /* Add the remaining ttl of peer resource reocrd.  */
9440             _nx_mdns_long_to_network_convert(data_ptr + index, (rr -> nx_mdns_rr_remaining_ticks / NX_IP_PERIODIC_RATE));
9441         }
9442         else
9443         {
9444             if (rr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_GOODBYE)
9445             {
9446                 _nx_mdns_long_to_network_convert(data_ptr + index, 0);
9447             }
9448             else
9449             {
9450                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_ttl);
9451             }
9452         }
9453         index = (USHORT)(index + 4);
9454 
9455         /* Compare the RDATA. */
9456         switch (rr -> nx_mdns_rr_type)
9457         {
9458 
9459             case NX_MDNS_RR_TYPE_A:
9460             {
9461 
9462                 /* Add the rdata length.  */
9463                 _nx_mdns_short_to_network_convert(data_ptr + index, 4);
9464                 index = (USHORT)(index + 2);
9465 
9466                 /* Add the rdata.  */
9467                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address);
9468                 index = (USHORT)(index + 4);
9469 
9470                 break;
9471             }
9472             case NX_MDNS_RR_TYPE_AAAA:
9473             {
9474 
9475                 /* Add the rdata length.  */
9476                 _nx_mdns_short_to_network_convert(data_ptr + index, 16);
9477                 index = (USHORT)(index + 2);
9478 
9479                 /* Add the rdata.  */
9480                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0]);
9481                 index = (USHORT)(index + 4);
9482                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1]);
9483                 index = (USHORT)(index + 4);
9484                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2]);
9485                 index = (USHORT)(index + 4);
9486                 _nx_mdns_long_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3]);
9487                 index = (USHORT)(index + 4);
9488 
9489                 break;
9490             }
9491             case NX_MDNS_RR_TYPE_PTR:
9492             {
9493 
9494                 /* Record the rdata length index then skip the rdata length.  */
9495                 rdata_length_index = index;
9496                 index = (USHORT)(index + 2);
9497 
9498                 /* Encode and add the name.  */
9499                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name);
9500                 index = (USHORT)(index + size);
9501 
9502                 /* Add the rdata length.  */
9503                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9504 
9505                 break;
9506             }
9507             case NX_MDNS_RR_TYPE_SRV:
9508             {
9509 
9510                 /* Record the rdata length index then skip the rdata length.  */
9511                 rdata_length_index = index;
9512                 index = (USHORT)(index + 2);
9513 
9514                 /* Add the prority.  */
9515                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority);
9516                 index = (USHORT)(index + 2);
9517 
9518                 /* Add the weights.  */
9519                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights);
9520                 index = (USHORT)(index + 2);
9521 
9522                 /* Add the port.  */
9523                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port);
9524                 index = (USHORT)(index + 2);
9525 
9526                 /* Encode and add the name.  */
9527                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target);
9528                 index = (USHORT)(index + size);
9529 
9530                 /* Add the rdata length.  */
9531                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 6));
9532 
9533                 break;
9534             }
9535             case NX_MDNS_RR_TYPE_TXT:
9536             {
9537 
9538                 /* Record the rdata length index then skip the rdata length.  */
9539                 rdata_length_index = index;
9540                 index = (USHORT)(index + 2);
9541 
9542                 if (rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
9543                 {
9544 
9545                     /* Encode and add the text.  */
9546                     size = (USHORT)_nx_mdns_txt_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data);
9547                 }
9548                 else
9549                 {
9550 
9551                     /* Encode the null.  */
9552                     *(data_ptr + index) = 0;
9553                     size = 1;
9554                 }
9555                 index = (USHORT)(index + size);
9556 
9557                 /* Add the rdata length.  */
9558                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9559 
9560                 break;
9561             }
9562 
9563 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
9564             case NX_MDNS_RR_TYPE_CNAME:
9565             {
9566 
9567                 /* Record the rdata length index then skip the rdata length.  */
9568                 rdata_length_index = index;
9569                 index = (USHORT)(index + 2);
9570 
9571                 /* Encode and add the name.  */
9572                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_cname.nx_mdns_rr_cname_name);
9573                 index = (USHORT)(index + size);
9574 
9575                 /* Add the rdata length.  */
9576                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9577 
9578                 break;
9579             }
9580             case NX_MDNS_RR_TYPE_NS:
9581             {
9582 
9583                 /* Record the rdata length index then skip the rdata length.  */
9584                 rdata_length_index = index;
9585                 index = (USHORT)(index + 2);
9586 
9587                 /* Encode and add the name.  */
9588                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ns.nx_mdns_rr_ns_name);
9589                 index = (USHORT)(index + size);
9590 
9591                 /* Add the rdata length.  */
9592                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, size);
9593 
9594                 break;
9595             }
9596             case NX_MDNS_RR_TYPE_MX:
9597             {
9598 
9599                 /* Record the rdata length index then skip the rdata length.  */
9600                 rdata_length_index = index;
9601                 index = (USHORT)(index + 2);
9602 
9603                 /* Add the preference.  */
9604                 _nx_mdns_short_to_network_convert(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference);
9605                 index = (USHORT)(index + 2);
9606 
9607                 /* Encode and add the name.  */
9608                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name);
9609                 index = (USHORT)(index + size);
9610 
9611                 /* Add the rdata length.  */
9612                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2));
9613 
9614                 break;
9615             }
9616 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
9617 
9618 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
9619             case NX_MDNS_RR_TYPE_NSEC:
9620             {
9621 
9622                 /* Record the rdata length index then skip the rdata length.  */
9623                 rdata_length_index = index;
9624                 index = (USHORT)(index + 2);
9625 
9626                 /* Encode and add the next domain name.  */
9627                 size = (USHORT)_nx_mdns_name_string_encode(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain);
9628                 index = (USHORT)(index + size);
9629 
9630                 /* Add the window block.  */
9631                 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block;
9632                 index++;
9633 
9634                 /* Add the bitmap length.  */
9635                 *(data_ptr + index) = rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length;
9636                 index++;
9637 
9638                 /* Add the type bit maps.  */
9639                 memcpy(data_ptr + index, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap, rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length); /* Use case of memcpy is verified. */
9640                 index = (USHORT)(index + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length);
9641 
9642                 /* Add the rdata length.  */
9643                 _nx_mdns_short_to_network_convert(data_ptr + rdata_length_index, (USHORT)(size + 2 + rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length));
9644 
9645                 break;
9646             }
9647 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
9648         }
9649     }
9650 
9651     /* Update the append pointer and packet length.  */
9652     packet_ptr -> nx_packet_append_ptr += index;
9653     packet_ptr -> nx_packet_length += index;
9654 
9655     return(NX_MDNS_SUCCESS);
9656 }
9657 
9658 
9659 /**************************************************************************/
9660 /*                                                                        */
9661 /*  FUNCTION                                               RELEASE        */
9662 /*                                                                        */
9663 /*    _nx_mdns_packet_rr_set                              PORTABLE C      */
9664 /*                                                           6.1.11       */
9665 /*  AUTHOR                                                                */
9666 /*                                                                        */
9667 /*    Yuxin Zhou, Microsoft Corporation                                   */
9668 /*                                                                        */
9669 /*  DESCRIPTION                                                           */
9670 /*                                                                        */
9671 /*    This function sets the resource record info from packet.            */
9672 /*                                                                        */
9673 /*  INPUT                                                                 */
9674 /*                                                                        */
9675 /*    mdns_ptr                              Pointer to mDNS instance.     */
9676 /*    packet_ptr                            Pointer to the packet.        */
9677 /*    data_ptr                              Pointer to the data.          */
9678 /*    rr_ptr                                Pointer to the record         */
9679 /*    op                                    Operation:                    */
9680 /*                                            set question or set answer. */
9681 /*                                                                        */
9682 /*  OUTPUT                                                                */
9683 /*                                                                        */
9684 /*    status                                Completion status             */
9685 /*                                                                        */
9686 /*  CALLS                                                                 */
9687 /*                                                                        */
9688 /*    _nx_mdns_name_string_decode           Decode the name string        */
9689 /*    _nx_mdns_cache_add_string             Add the name string           */
9690 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
9691 /*                                                                        */
9692 /*  CALLED BY                                                             */
9693 /*                                                                        */
9694 /*    _nx_mdns_packet_process               Process mDNS packet           */
9695 /*                                                                        */
9696 /*  RELEASE HISTORY                                                       */
9697 /*                                                                        */
9698 /*    DATE              NAME                      DESCRIPTION             */
9699 /*                                                                        */
9700 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9701 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9702 /*                                            resulting in version 6.1    */
9703 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
9704 /*                                            buffer length verification, */
9705 /*                                            resulting in version 6.1.3  */
9706 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
9707 /*                                            packet length verification, */
9708 /*                                            resulting in version 6.1.4  */
9709 /*  04-25-2022     Yuxin Zhou               Modified comment(s), improved */
9710 /*                                            fixed the issue of timer,   */
9711 /*                                            resulting in version 6.1.11 */
9712 /*                                                                        */
9713 /**************************************************************************/
_nx_mdns_packet_rr_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op,UINT interface_index)9714 static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index)
9715 {
9716 
9717 UCHAR          *cache_ptr;
9718 UINT            cache_size;
9719 UINT            cache_type;
9720 USHORT          record_class;
9721 UINT            status;
9722 UINT            temp_string_length;
9723 
9724 
9725     /* Initialize.  */
9726     memset(rr_ptr, 0, sizeof(NX_MDNS_RR));
9727 
9728     /* Get cache type and size. */
9729     if ((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) ||
9730         (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER))
9731     {
9732         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
9733         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
9734         cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
9735     }
9736     else
9737     {
9738         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
9739         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
9740         cache_type = NX_MDNS_CACHE_TYPE_PEER;
9741     }
9742 
9743     /* Check cache pointer and cache size.  */
9744     if ((cache_ptr == NX_NULL) || (cache_size == 0))
9745     {
9746         return(NX_MDNS_ERROR);
9747     }
9748 
9749     /* Set the interface.  */
9750     rr_ptr -> nx_mdns_rr_interface_index = (UCHAR)interface_index;
9751 
9752     /* Process the name string.  */
9753     if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9754                                     (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9755                                     packet_ptr -> nx_packet_length,
9756                                     temp_string_buffer, NX_MDNS_NAME_MAX))
9757     {
9758 
9759         /* Check string length.  */
9760         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9761         {
9762             return(NX_MDNS_DATA_SIZE_ERROR);
9763         }
9764 
9765          /* Add the string .  */
9766         if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
9767                                     (VOID **)(&rr_ptr -> nx_mdns_rr_name), NX_TRUE, NX_TRUE) != NX_MDNS_SUCCESS)
9768         {
9769             return(NX_MDNS_ERROR);
9770         }
9771     }
9772     else
9773     {
9774         return(NX_MDNS_ERROR);
9775     }
9776 
9777     /* Plus 4 for 2 bytes type and 2 bytes class. */
9778     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9779     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9780     {
9781         return(NX_MDNS_ERROR);
9782     }
9783 
9784     /* Set the resource record type. */
9785     rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9786 
9787     /* Get the resource record class.*/
9788     record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9789 
9790     /* Remote RR, set the RR owner flag.*/
9791     if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
9792         rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9793 
9794     /* Unique RR, Set the RR set flag.  */
9795     if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9796     {
9797         rr_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9798     }
9799 
9800     /* Check the operation and update the record class.  */
9801     if((op == NX_MDNS_RR_OP_LOCAL_SET_QUESTION) || (op == NX_MDNS_RR_OP_PEER_SET_QUESTION))
9802     {
9803         rr_ptr -> nx_mdns_rr_class = record_class;
9804         return(NX_MDNS_SUCCESS);
9805     }
9806     else
9807     {
9808         rr_ptr -> nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9809     }
9810 
9811     /* Set the rdata information for answer record.  */
9812     status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, rr_ptr, op);
9813 
9814     /* Return success.  */
9815     return (status);
9816 }
9817 
9818 
9819 #ifndef NX_MDNS_DISABLE_CLIENT
9820 /**************************************************************************/
9821 /*                                                                        */
9822 /*  FUNCTION                                               RELEASE        */
9823 /*                                                                        */
9824 /*    _nx_mdns_packet_rr_process                          PORTABLE C      */
9825 /*                                                           6.1.11       */
9826 /*  AUTHOR                                                                */
9827 /*                                                                        */
9828 /*    Yuxin Zhou, Microsoft Corporation                                   */
9829 /*                                                                        */
9830 /*  DESCRIPTION                                                           */
9831 /*                                                                        */
9832 /*    This function processes the resource record of packet, and add the  */
9833 /*    record into peer cache.                                             */
9834 /*                                                                        */
9835 /*  INPUT                                                                 */
9836 /*                                                                        */
9837 /*    mdns_ptr                              Pointer to mDNS instance.     */
9838 /*    packet_ptr                            Pointer to the packet.        */
9839 /*    data_ptr                              Pointer to the data.          */
9840 /*    insert_ptr                            Pointer to the insert record  */
9841 /*    op                                    Operation: add answer, set    */
9842 /*                                            question or set answer.     */
9843 /*    cache_ptr                             The record buffer.            */
9844 /*                                                                        */
9845 /*  OUTPUT                                                                */
9846 /*                                                                        */
9847 /*    status                                Completion status             */
9848 /*                                                                        */
9849 /*  CALLS                                                                 */
9850 /*                                                                        */
9851 /*    _nx_mdns_name_string_decode           Decode the name string        */
9852 /*    _nx_mdns_cache_add_string             Add the name string           */
9853 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
9854 /*                                                                        */
9855 /*  CALLED BY                                                             */
9856 /*                                                                        */
9857 /*    _nx_mdns_packet_process               Process mDNS packet           */
9858 /*                                                                        */
9859 /*  RELEASE HISTORY                                                       */
9860 /*                                                                        */
9861 /*    DATE              NAME                      DESCRIPTION             */
9862 /*                                                                        */
9863 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9864 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9865 /*                                            verified memcpy use cases,  */
9866 /*                                            resulting in version 6.1    */
9867 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
9868 /*                                            buffer length verification, */
9869 /*                                            resulting in version 6.1.3  */
9870 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
9871 /*                                            packet length verification, */
9872 /*                                            resulting in version 6.1.4  */
9873 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
9874 /*                                            corrected the random value, */
9875 /*                                            fixed the issue of timer,   */
9876 /*                                            resulting in version 6.1.11 */
9877 /*                                                                        */
9878 /**************************************************************************/
_nx_mdns_packet_rr_process(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,UINT interface_index)9879 static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index)
9880 {
9881 
9882 UINT            status;
9883 USHORT          record_class;
9884 UCHAR           is_present;
9885 NX_MDNS_RR      rr_ptr;
9886 NX_MDNS_RR     *insert_ptr;
9887 NX_MDNS_RR     *p;
9888 ULONG          *head;
9889 UCHAR          *service_name,*service_type,*service_domain;
9890 UINT            temp_string_length;
9891 UINT            rr_name_length;
9892 
9893 
9894     /* Check the peer cache.  */
9895     if ((mdns_ptr -> nx_mdns_peer_service_cache == NX_NULL) ||
9896         (mdns_ptr -> nx_mdns_peer_service_cache_size == 0))
9897     {
9898         return(NX_MDNS_ERROR);
9899     }
9900 
9901     /* Initialize.  */
9902     memset(&rr_ptr, 0, sizeof(NX_MDNS_RR));
9903 
9904     /* Process the name string.  */
9905     if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
9906                                     (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
9907                                     packet_ptr -> nx_packet_length,
9908                                     temp_string_buffer, NX_MDNS_NAME_MAX))
9909     {
9910 
9911         /* Check string length.  */
9912         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
9913         {
9914             return(NX_MDNS_DATA_SIZE_ERROR);
9915         }
9916 
9917          /* Add the string .  */
9918         if(_nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, temp_string_buffer, temp_string_length,
9919                                      (VOID **)(&rr_ptr.nx_mdns_rr_name), NX_FALSE, NX_TRUE))
9920         {
9921             return(NX_MDNS_ERROR);
9922         }
9923     }
9924     else
9925     {
9926         return(NX_MDNS_ERROR);
9927     }
9928 
9929     /* Plus 4 for 2 bytes type and 2 bytes class. */
9930     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
9931     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr))
9932     {
9933         return(NX_MDNS_ERROR);
9934     }
9935 
9936     /* Set the resource record type. */
9937     rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length);
9938 
9939     /* Get the resource record class.*/
9940     record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2);
9941 
9942     /* Set the resource record class.  */
9943     rr_ptr.nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK;
9944 
9945     /* Remote RR, set the RR owner flag.*/
9946     rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_PEER;
9947 
9948     /* Unique RR, Set the RR set flag.  */
9949     if (record_class & (~NX_MDNS_TOP_BIT_MASK))
9950     {
9951         rr_ptr.nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UNIQUE;
9952     }
9953 
9954     /* Set the interface index.  */
9955     rr_ptr.nx_mdns_rr_interface_index = (UCHAR)interface_index;
9956 
9957     /* Set the rdata information for answer record.  */
9958     status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, &rr_ptr, NX_MDNS_RR_OP_PEER_ADD_ANSWER);
9959 
9960     /* Check status.  */
9961     if(status)
9962     {
9963 
9964         /* Delete the name strings. */
9965         _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, rr_ptr.nx_mdns_rr_name, 0);
9966         return (NX_MDNS_ERROR);
9967     }
9968 
9969     /* Check if need to ignore this source reocrd.  */
9970     if ((mdns_ptr -> nx_mdns_service_ignore_mask) &&
9971         ((rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
9972          (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
9973          (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)))
9974     {
9975 
9976         /* Get the service.  */
9977         if (rr_ptr.nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
9978         {
9979 
9980             /* Check string length.  */
9981             if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9982             {
9983                 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
9984                 return(NX_MDNS_DATA_SIZE_ERROR);
9985             }
9986             memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9987         }
9988         else
9989         {
9990 
9991             /* Check string length.  */
9992             if (_nx_utility_string_length_check((CHAR *)rr_ptr.nx_mdns_rr_name, &rr_name_length, NX_MDNS_NAME_MAX))
9993             {
9994                 _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
9995                 return(NX_MDNS_DATA_SIZE_ERROR);
9996             }
9997             memcpy((CHAR *)temp_string_buffer, (const char *)rr_ptr.nx_mdns_rr_name, rr_name_length + 1); /* Use case of memcpy is verified. */
9998         }
9999 
10000         /* Resolve the service type.  */
10001         if (_nx_mdns_service_name_resolve(temp_string_buffer, &service_name, &service_type, &service_domain))
10002         {
10003             _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
10004             return (status);
10005         }
10006 
10007         /* Check if this service type should be ignored.  */
10008         if (_nx_mdns_service_mask_match(mdns_ptr, service_type, mdns_ptr -> nx_mdns_service_ignore_mask) == NX_MDNS_SUCCESS)
10009         {
10010             _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER,  &rr_ptr);
10011             return (NX_MDNS_ERROR);
10012         }
10013     }
10014 
10015     /* Add the resource record into remote buffer.  */
10016     if (_nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr, &insert_ptr, &is_present))
10017     {
10018 
10019         /* Delete the name strings. */
10020         _nx_mdns_cache_delete_rr_string(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &rr_ptr);
10021         return (NX_MDNS_ERROR);
10022     }
10023 
10024     /* Check the ttl.  */
10025     if (insert_ptr -> nx_mdns_rr_ttl)
10026     {
10027 
10028         /* Step1. Process answer record.  */
10029         /* Update the state.  */
10030         insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_VALID;
10031 
10032         /* Update the timer count. The querier should not include records in the Known-Answer list whose remaining TTL is less than half of their original TTL.  */
10033         insert_ptr -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * 50 / 100;
10034 
10035         /* Record the remaining ticks of resource record. */
10036         if (insert_ptr -> nx_mdns_rr_ttl >= NX_MDNS_RR_MAX_TTL)
10037         {
10038             /* If the ttl of resource resource record is outside the range, set as 0xFFFFFFFF.  */
10039             insert_ptr -> nx_mdns_rr_remaining_ticks = 0xFFFFFFFF;
10040         }
10041         else
10042         {
10043             /* Convert units(seconds to ticks). */
10044             insert_ptr -> nx_mdns_rr_remaining_ticks = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE;
10045         }
10046 
10047         /* Step2. Process query record.  */
10048         /* Set the pointer.  */
10049         head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
10050         head = (ULONG*)(*head);
10051 
10052         /* Check the remote resource record state.  */
10053         for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10054         {
10055 
10056             /* Check the state.  */
10057             if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
10058                 continue;
10059 
10060             /* Check the interface index.  */
10061             if (p -> nx_mdns_rr_interface_index != insert_ptr -> nx_mdns_rr_interface_index)
10062                 continue;
10063 
10064             /* Check the name.  */
10065             if (p -> nx_mdns_rr_name != insert_ptr -> nx_mdns_rr_name)
10066                 continue;
10067 
10068             /* Check the type.  */
10069             if ((p -> nx_mdns_rr_type != insert_ptr -> nx_mdns_rr_type) &&
10070                 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL))
10071                 continue;
10072 
10073             /* Check the class.  */
10074             if (p -> nx_mdns_rr_class != insert_ptr -> nx_mdns_rr_class)
10075                 continue;
10076 
10077             /* Check the query type.  */
10078             if (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_CONTINUOUS_QUERY))
10079             {
10080 
10081                 /* Determine if we need to wake a thread suspended.  */
10082                 if (mdns_ptr -> nx_mdns_rr_receive_suspension_list)
10083                 {
10084 
10085                     /* Resume suspended thread.  */
10086                     _nx_mdns_query_thread_resume(&(mdns_ptr -> nx_mdns_rr_receive_suspension_list), mdns_ptr, insert_ptr);
10087                 }
10088 
10089                 /* Get the answer, we need not send the question again. Delete the resource record.  */
10090                 _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, p);
10091 
10092             }
10093             else
10094             {
10095 
10096                 /* There is no need for the querier to continue issuing a stream of queries when a mDNS response
10097                     is received containing a unique answer.  mDNS querier should send the next query at 80%-82% of the
10098                     record's TTL. RFC6762, Section5.2,Page11.  */
10099                 if ((insert_ptr -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE) && (insert_ptr -> nx_mdns_rr_ttl))
10100                 {
10101 
10102                     /* Set the timer count. */
10103                     p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (((ULONG)NX_RAND()) % 3)) / 100;
10104 
10105                     /* Set the mDNS timer.  */
10106                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10107                 }
10108 
10109                 /* Set the updating flag to update the resource record at 80% of the record's TTL.  */
10110                 insert_ptr -> nx_mdns_rr_word |= NX_MDNS_RR_FLAG_UPDATING;
10111             }
10112         }
10113     }
10114     else
10115     {
10116 
10117         /* Update the state to delete this record from peer cache. .  */
10118         insert_ptr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_DELETE;
10119 
10120         /* Delete the resource record one second later.  */
10121         insert_ptr -> nx_mdns_rr_timer_count = NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT;
10122     }
10123 
10124     /* Set the mDNS timer for insert RR.  */
10125     _nx_mdns_timer_set(mdns_ptr, insert_ptr, insert_ptr -> nx_mdns_rr_timer_count);
10126 
10127     /* Service name registered success, invoke the notify function.  */
10128     if (mdns_ptr -> nx_mdns_service_change_notify)
10129     {
10130 
10131         /* Process the service notify function.  */
10132         _nx_mdns_service_change_notify_process(mdns_ptr, insert_ptr, is_present);
10133     }
10134 
10135     /* Return success.  */
10136     return (NX_MDNS_SUCCESS);
10137 }
10138 #endif /* NX_MDNS_DISABLE_CLIENT  */
10139 
10140 
10141 /**************************************************************************/
10142 /*                                                                        */
10143 /*  FUNCTION                                               RELEASE        */
10144 /*                                                                        */
10145 /*    _nx_mdns_packet_rr_data_set                         PORTABLE C      */
10146 /*                                                           6.1.4        */
10147 /*  AUTHOR                                                                */
10148 /*                                                                        */
10149 /*    Yuxin Zhou, Microsoft Corporation                                   */
10150 /*                                                                        */
10151 /*  DESCRIPTION                                                           */
10152 /*                                                                        */
10153 /*    This function processes the packet, and sets the data of            */
10154 /*    resource record.                                                    */
10155 /*                                                                        */
10156 /*  INPUT                                                                 */
10157 /*                                                                        */
10158 /*    mdns_ptr                              Pointer to mDNS instance.     */
10159 /*    packet_ptr                            Pointer to the packet.        */
10160 /*    data_ptr                              Pointer to the data.          */
10161 /*    rr_ptr                                Pointer to the record         */
10162 /*    op                                    Operation:                    */
10163 /*                                            set answer in local cache.  */
10164 /*                                            or add answer in peer cache.*/
10165 /*    cache_ptr                             The record buffer.            */
10166 /*                                                                        */
10167 /*  OUTPUT                                                                */
10168 /*                                                                        */
10169 /*    status                                Completion status             */
10170 /*                                                                        */
10171 /*  CALLS                                                                 */
10172 /*                                                                        */
10173 /*    _nx_mdns_name_string_decode           Decode the name string        */
10174 /*    _nx_mdns_cache_add_string             Add the name string           */
10175 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
10176 /*                                                                        */
10177 /*  CALLED BY                                                             */
10178 /*                                                                        */
10179 /*    _nx_mdns_packet_process               Process mDNS packet           */
10180 /*                                                                        */
10181 /*  RELEASE HISTORY                                                       */
10182 /*                                                                        */
10183 /*    DATE              NAME                      DESCRIPTION             */
10184 /*                                                                        */
10185 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10186 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10187 /*                                            resulting in version 6.1    */
10188 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
10189 /*                                            buffer length verification, */
10190 /*                                            resulting in version 6.1.3  */
10191 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
10192 /*                                            packet length verification, */
10193 /*                                            resulting in version 6.1.4  */
10194 /*                                                                        */
10195 /**************************************************************************/
_nx_mdns_packet_rr_data_set(NX_MDNS * mdns_ptr,NX_PACKET * packet_ptr,UCHAR * data_ptr,NX_MDNS_RR * rr_ptr,UINT op)10196 static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op)
10197 {
10198 
10199 UCHAR          *string_search = NX_NULL;
10200 UINT            cache_type;
10201 UCHAR           find_string;
10202 UCHAR           continue_process = NX_FALSE;
10203 UINT            status = NX_MDNS_UNSUPPORTED_TYPE;
10204 UINT            temp_string_length;
10205 
10206 
10207     /* Get cache type and size. */
10208     if (op == NX_MDNS_RR_OP_LOCAL_SET_ANSWER)
10209     {
10210         cache_type = NX_MDNS_CACHE_TYPE_LOCAL;
10211         find_string = NX_TRUE;
10212     }
10213     else
10214     {
10215         cache_type = NX_MDNS_CACHE_TYPE_PEER;
10216         find_string = NX_FALSE;
10217     }
10218 
10219     /* Plus 10 for 2 bytes type, 2 bytes class, 4 bytes ttl and 2 bytes rdata length. */
10220     temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr);
10221     if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 10) > packet_ptr -> nx_packet_append_ptr))
10222     {
10223         return(NX_MDNS_ERROR);
10224     }
10225 
10226     /* Set the resource record time to live.*/
10227     rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + temp_string_length + 4);
10228 
10229     /* Set the resource record rdata length.  */
10230     rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 8);;
10231 
10232     /* Update the pointer to point at the resource data.  */
10233     data_ptr = data_ptr + temp_string_length + 10;
10234 
10235     /* Check the type.  */
10236     switch (rr_ptr -> nx_mdns_rr_type)
10237     {
10238         case NX_MDNS_RR_TYPE_A:
10239         {
10240 
10241             /* 4 bytes IP address. */
10242             if (data_ptr + 4 > packet_ptr -> nx_packet_append_ptr)
10243             {
10244                 return(NX_MDNS_ERROR);
10245             }
10246 
10247             /* Get the rdata.  */
10248             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = NX_MDNS_GET_ULONG_DATA(data_ptr);
10249             rr_ptr -> nx_mdns_rr_rdata_length = 4;
10250 
10251             /* Update the status.  */
10252             status = NX_MDNS_SUCCESS;
10253             break;
10254         }
10255         case NX_MDNS_RR_TYPE_AAAA:
10256         {
10257 
10258             /* 16 bytes IPv6 address. */
10259             if (data_ptr + 16 > packet_ptr -> nx_packet_append_ptr)
10260             {
10261                 return(NX_MDNS_ERROR);
10262             }
10263 
10264             /* Get the rdata.  */
10265             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = NX_MDNS_GET_ULONG_DATA(data_ptr);
10266             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = NX_MDNS_GET_ULONG_DATA(data_ptr + 4);
10267             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2] = NX_MDNS_GET_ULONG_DATA(data_ptr + 8);
10268             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3] = NX_MDNS_GET_ULONG_DATA(data_ptr + 12);
10269             rr_ptr -> nx_mdns_rr_rdata_length = 16;
10270 
10271             /* Update the status.  */
10272             status = NX_MDNS_SUCCESS;
10273             break;
10274         }
10275         case NX_MDNS_RR_TYPE_TXT:
10276         {
10277 
10278             /* Process the txt string. An empty TXT record contaning zero strings is not allowed. RFC6763, Page12.  */
10279             if (rr_ptr -> nx_mdns_rr_rdata_length == 1)
10280             {
10281 
10282                 /* Update the status.  */
10283                 status = NX_MDNS_SUCCESS;
10284             }
10285             else if (rr_ptr -> nx_mdns_rr_rdata_length > 1)
10286             {
10287 
10288                 if (data_ptr + rr_ptr -> nx_mdns_rr_rdata_length > packet_ptr -> nx_packet_append_ptr)
10289                 {
10290                     return(NX_MDNS_ERROR);
10291                 }
10292 
10293                 /* Add the txt string.  */
10294                 if (_nx_mdns_txt_string_decode(data_ptr, rr_ptr -> nx_mdns_rr_rdata_length, temp_string_buffer, NX_MDNS_NAME_MAX) == NX_MDNS_SUCCESS)
10295                 {
10296 
10297                     /* Check string length.  */
10298                     if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10299                     {
10300                         return(NX_MDNS_DATA_SIZE_ERROR);
10301                     }
10302 
10303                     /* Find the same string .  */
10304                     if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10305                                                  (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10306                     {
10307 
10308                         /* Update the name pointer.  */
10309                         rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data = string_search;
10310 
10311                         /* Calculate the text string.inlcude the one byte label.  */
10312                         rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(temp_string_length + 1);
10313 
10314                         /* Update the status.  */
10315                         status = NX_MDNS_SUCCESS;
10316                     }
10317                 }
10318             }
10319 
10320             break;
10321         }
10322         case NX_MDNS_RR_TYPE_SRV:
10323         {
10324 
10325             /* Plus 6 bytes for 2 bytes priority, 2 bytes weights and 2 bytes port. */
10326             if (data_ptr + 6 > packet_ptr -> nx_packet_append_ptr)
10327             {
10328                 return(NX_MDNS_ERROR);
10329             }
10330 
10331             /* Get the priority.  */
10332             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = NX_MDNS_GET_USHORT_DATA(data_ptr);
10333             data_ptr += 2;
10334 
10335             /* Get the weights.  */
10336             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights = NX_MDNS_GET_USHORT_DATA(data_ptr);
10337             data_ptr += 2;
10338 
10339             /* Get the port.  */
10340             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port = NX_MDNS_GET_USHORT_DATA(data_ptr);
10341             data_ptr += 2;
10342 
10343             /* Update the rdata length.  */
10344             rr_ptr -> nx_mdns_rr_rdata_length = 6;
10345 
10346             /* Continue to process target name.  */
10347             continue_process = NX_TRUE;
10348             break;
10349         }
10350         case NX_MDNS_RR_TYPE_PTR:
10351 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10352         case NX_MDNS_RR_TYPE_CNAME:
10353         case NX_MDNS_RR_TYPE_NS:
10354 #endif
10355         {
10356 
10357             /* Update the rdata length.  */
10358             rr_ptr -> nx_mdns_rr_rdata_length = 0;
10359 
10360             /* Continue to process the domain name.  */
10361             continue_process = NX_TRUE;
10362             break;
10363         }
10364 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
10365         case NX_MDNS_RR_TYPE_MX:
10366         {
10367 
10368             /* Plus 2 bytes for preference. */
10369             if (data_ptr + 2 > packet_ptr -> nx_packet_append_ptr)
10370             {
10371                 return(NX_MDNS_ERROR);
10372             }
10373 
10374             /* Set the preference.  */
10375             rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference = NX_MDNS_GET_USHORT_DATA(data_ptr);
10376             data_ptr += 2;
10377 
10378             /* Update the rdata length.  */
10379             rr_ptr ->  nx_mdns_rr_rdata_length = 2;
10380 
10381             /* Continue to process the domain name.  */
10382             continue_process = NX_TRUE;
10383             break;
10384         }
10385 #endif
10386     }
10387 
10388     /* Check if need to continue process rdata.  */
10389     if(continue_process == NX_TRUE)
10390     {
10391 
10392         /* Process the target/domain name string.  */
10393         if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr,
10394                                        (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr),
10395                                         packet_ptr -> nx_packet_length,
10396                                        temp_string_buffer, NX_MDNS_NAME_MAX))
10397         {
10398 
10399             /* Check string length.  */
10400             if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_NAME_MAX))
10401             {
10402                 return(NX_MDNS_DATA_SIZE_ERROR);
10403             }
10404 
10405             /* Add the string.  */
10406             if(_nx_mdns_cache_add_string(mdns_ptr, cache_type, temp_string_buffer, temp_string_length,
10407                                          (VOID **)&string_search, find_string, NX_TRUE) == NX_MDNS_SUCCESS)
10408             {
10409 
10410                 /* Update the name pointer for SRV, PTR, etc.  */
10411                 rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target = string_search;
10412 
10413                 /* Calculate the text string. Inlcude the one byte label '.' and null '\0'.  */
10414                 rr_ptr -> nx_mdns_rr_rdata_length = (USHORT)(rr_ptr -> nx_mdns_rr_rdata_length + (temp_string_length + 2));
10415 
10416                 /* Update the status.  */
10417                 status = NX_MDNS_SUCCESS;
10418             }
10419         }
10420     }
10421 
10422     /* Return success.  */
10423     return (status);
10424 }
10425 
10426 
10427 #ifdef NX_MDNS_ENABLE_ADDRESS_CHECK
10428 /**************************************************************************/
10429 /*                                                                        */
10430 /*  FUNCTION                                               RELEASE        */
10431 /*                                                                        */
10432 /*    _nx_mdns_packet_address_check                       PORTABLE C      */
10433 /*                                                           6.1.4        */
10434 /*  AUTHOR                                                                */
10435 /*                                                                        */
10436 /*    Yuxin Zhou, Microsoft Corporation                                   */
10437 /*                                                                        */
10438 /*  DESCRIPTION                                                           */
10439 /*                                                                        */
10440 /*    This function checks the IP address and port of received packet.    */
10441 /*                                                                        */
10442 /*  INPUT                                                                 */
10443 /*                                                                        */
10444 /*    packet_ptr                            Pointer to mDNS packet        */
10445 /*                                                                        */
10446 /*  OUTPUT                                                                */
10447 /*                                                                        */
10448 /*    status                                Completion status             */
10449 /*                                                                        */
10450 /*  CALLS                                                                 */
10451 /*                                                                        */
10452 /*    none                                                                */
10453 /*                                                                        */
10454 /*  CALLED BY                                                             */
10455 /*                                                                        */
10456 /*    _nx_mdns_packet_process               Process mDNS packet           */
10457 /*                                                                        */
10458 /*  RELEASE HISTORY                                                       */
10459 /*                                                                        */
10460 /*    DATE              NAME                      DESCRIPTION             */
10461 /*                                                                        */
10462 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10463 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10464 /*                                            resulting in version 6.1    */
10465 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
10466 /*                                            packet length verification, */
10467 /*                                            resulting in version 6.1.4  */
10468 /*                                                                        */
10469 /**************************************************************************/
_nx_mdns_packet_address_check(NX_PACKET * packet_ptr)10470 static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr)
10471 {
10472 
10473 USHORT              mdns_flags;
10474 UINT                src_port;
10475 ULONG              *udp_header;
10476 
10477 #if !defined NX_DISABLE_IPV4 || defined NX_MDNS_ENABLE_IPV6
10478 NXD_ADDRESS         src_address;
10479 NXD_ADDRESS         des_address;
10480 #endif /* !NX_DISABLE_IPV4 || NX_MDNS_ENABLE_IPV6  */
10481 
10482 #ifndef NX_DISABLE_IPV4
10483 NX_IPV4_HEADER     *ipv4_header;
10484 #endif /* NX_DISABLE_IPV4  */
10485 
10486 #ifdef NX_MDNS_ENABLE_IPV6
10487 NX_IPV6_HEADER     *ipv6_header;
10488 #endif /* NX_MDNS_ENABLE_IPV6  */
10489 
10490 
10491     /* 2 bytes ID and 2 bytes flags. */
10492     if (packet_ptr -> nx_packet_length < 4)
10493     {
10494         return(NX_MDNS_ERROR);
10495     }
10496 
10497     /* Extract the message type which should be the first byte.  */
10498     mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET);
10499 
10500 #ifndef NX_DISABLE_IPV4
10501     /* Get the ip address.  */
10502     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10503     {
10504 
10505         /* Set the IPv4 header.  */
10506         ipv4_header = (NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header;
10507 
10508         /* Set the source address.  */
10509         src_address.nxd_ip_version = NX_IP_VERSION_V4;
10510         src_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_source_ip;
10511 
10512         /* Set the destination address.  */
10513         des_address.nxd_ip_version = NX_IP_VERSION_V4;
10514         des_address.nxd_ip_address.v4 = ipv4_header -> nx_ip_header_destination_ip;
10515     }
10516     else
10517 #endif /* NX_DISABLE_IPV4  */
10518 
10519 #ifdef NX_MDNS_ENABLE_IPV6
10520     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10521     {
10522 
10523         /* Set the IPv6 header.  */
10524         ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
10525 
10526         /* Set the source address.  */
10527         src_address.nxd_ip_version = NX_IP_VERSION_V6;
10528         COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_address.nxd_ip_address.v6);
10529 
10530         /* Set the destination address.  */
10531         des_address.nxd_ip_version = NX_IP_VERSION_V6;
10532         COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, des_address.nxd_ip_address.v6);
10533     }
10534     else
10535 #endif /* NX_MDNS_ENABLE_IPV6  */
10536     {
10537 
10538         /* Invalid IP version . */
10539         return(NX_MDNS_ERROR);
10540     }
10541 
10542     /* Pickup the pointer to the head of the UDP packet.  */
10543     udp_header =  (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 8);
10544 
10545     /* Get the source port and destination port.  */
10546     src_port = (UINT) ((*udp_header) >> NX_SHIFT_BY_16);
10547 
10548     /* Check the source UDP port.  RFC6762, Section6, Page15.  */
10549     if (src_port != NX_MDNS_UDP_PORT)
10550     {
10551         return(NX_MDNS_UDP_PORT_ERROR);
10552     }
10553 
10554     /* Check the QR bit. */
10555     if ((mdns_flags & NX_MDNS_RESPONSE_FLAG) == NX_MDNS_RESPONSE_FLAG)
10556     {
10557 
10558         /* Check the response code.  */
10559         if (mdns_flags & NX_MDNS_ERROR_MASK)
10560         {
10561 
10562             /* Release the source packet.  */
10563             return(NX_MDNS_AUTH_ERROR);
10564         }
10565 
10566         /* In response messages for Multicast domains, the AA bit Must be set to one, RFC6762, Page48. */
10567         if ((mdns_flags & NX_MDNS_AA_FLAG) != NX_MDNS_AA_FLAG)
10568         {
10569             return (NX_MDNS_ERROR);
10570         }
10571 
10572 #ifndef NX_DISABLE_IPV4
10573         /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10574         if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10575         {
10576 
10577             /* Local link check, Multicast Address or (I & M) == (P & M).  */
10578             if ((des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS) &&
10579                 (packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address & packet_ptr ->nx_packet_ip_interface -> nx_interface_ip_network_mask) !=
10580                 (src_address.nxd_ip_address.v4 & packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_network_mask))
10581             {
10582                 return (NX_MDNS_NOT_LOCAL_LINK);
10583             }
10584         }
10585         else
10586 #endif /* NX_DISABLE_IPV4  */
10587 
10588 #ifdef NX_MDNS_ENABLE_IPV6
10589         if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10590         {
10591 
10592             /* Destination address is not FF02::FB address or source address not on link, RFC6762, Section 11, Page39. */
10593             /* Not check the source address.  */
10594             if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10595                 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10596                 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10597                 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10598             {
10599                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10600             }
10601         }
10602         else
10603 #endif /* NX_MDNS_ENABLE_IPV6  */
10604         {
10605 
10606             /* Invalid IP version. */
10607             return(NX_MDNS_ERROR);
10608         }
10609     }
10610     else
10611     {
10612 
10613 #ifndef NX_DISABLE_IPV4
10614         /* Check the interface and destination address. RFC6762, Section 11, Page38,39. */
10615         if (des_address.nxd_ip_version == NX_IP_VERSION_V4)
10616         {
10617             if (des_address.nxd_ip_address.v4 != NX_MDNS_IPV4_MULTICAST_ADDRESS)
10618             {
10619                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10620             }
10621         }
10622         else
10623 #endif /* NX_DISABLE_IPV4  */
10624 
10625 #ifdef NX_MDNS_ENABLE_IPV6
10626         if(des_address.nxd_ip_version == NX_IP_VERSION_V6)
10627         {
10628             if ((des_address.nxd_ip_address.v6[0] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[0]) ||
10629                 (des_address.nxd_ip_address.v6[1] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[1]) ||
10630                 (des_address.nxd_ip_address.v6[2] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[2]) ||
10631                 (des_address.nxd_ip_address.v6[3] != NX_MDNS_IPV6_MULTICAST_ADDRESS.nxd_ip_address.v6[3]))
10632             {
10633                 return (NX_MDNS_DEST_ADDRESS_ERROR);
10634             }
10635         }
10636         else
10637 #endif /* NX_MDNS_ENABLE_IPV6  */
10638         {
10639 
10640             /* Invalid IP version . */
10641             return(NX_MDNS_ERROR);
10642         }
10643     }
10644 
10645     return(NX_MDNS_SUCCESS);
10646 }
10647 #endif /* NX_MDNS_ENABLE_ADDRESS_CHECK  */
10648 
10649 
10650 #ifndef NX_MDNS_DISABLE_SERVER
10651 /**************************************************************************/
10652 /*                                                                        */
10653 /*  FUNCTION                                               RELEASE        */
10654 /*                                                                        */
10655 /*    _nx_mdns_address_change_process                     PORTABLE C      */
10656 /*                                                           6.1          */
10657 /*  AUTHOR                                                                */
10658 /*                                                                        */
10659 /*    Yuxin Zhou, Microsoft Corporation                                   */
10660 /*                                                                        */
10661 /*  DESCRIPTION                                                           */
10662 /*                                                                        */
10663 /*    This function process the address change event.                     */
10664 /*                                                                        */
10665 /*  INPUT                                                                 */
10666 /*                                                                        */
10667 /*    mdns_ptr                              Pointer to mDNS instance      */
10668 /*                                                                        */
10669 /*  OUTPUT                                                                */
10670 /*                                                                        */
10671 /*    status                                Completion status             */
10672 /*                                                                        */
10673 /*  CALLS                                                                 */
10674 /*                                                                        */
10675 /*    nx_packet_copy                        Copy the mDNS packet          */
10676 /*    nx_packet_release                     Release the mDNS packet       */
10677 /*    nx_udp_socket_send                    Send the udp packet           */
10678 /*    nxd_udp_socket_send                   Send the udp packet           */
10679 /*                                                                        */
10680 /*  CALLED BY                                                             */
10681 /*                                                                        */
10682 /*    _nx_mdns_thread_entry                 Processing thread for mDNS    */
10683 /*                                                                        */
10684 /*  RELEASE HISTORY                                                       */
10685 /*                                                                        */
10686 /*    DATE              NAME                      DESCRIPTION             */
10687 /*                                                                        */
10688 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10689 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10690 /*                                            resulting in version 6.1    */
10691 /*                                                                        */
10692 /**************************************************************************/
_nx_mdns_address_change_process(NX_MDNS * mdns_ptr)10693 static VOID    _nx_mdns_address_change_process(NX_MDNS *mdns_ptr)
10694 {
10695 
10696 ULONG       *head;
10697 NX_MDNS_RR  *p;
10698 UINT        i;
10699 
10700 
10701     /* Register the host name.  */
10702     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
10703     {
10704 
10705         /* Check if the interface is enabled.  */
10706         if (!mdns_ptr -> nx_mdns_interface_enabled[i])
10707             continue;
10708 
10709         /* Get the local buffer head. */
10710         head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10711 
10712         if (head)
10713         {
10714 
10715             /* Set the pointer.  */
10716             head = (ULONG*)(*head);
10717 
10718             /* Check the resource record.  */
10719             for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10720             {
10721 
10722                 /* Check whether the resource record is valid. */
10723                 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
10724                     continue;
10725 
10726                 /* Check the interface index.  */
10727                 if (p -> nx_mdns_rr_interface_index != i)
10728                     continue;
10729 
10730                 /* If any of a host's IP addresses change, it MUST re-announce those address records. RFC6762, Section8.4, Page31.  */
10731                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10732                     (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10733                 {
10734 
10735                     /* Send the "goodbye " announcement with RR TTL zero. RFC6762, Section8.4, Page31.  */
10736                     p -> nx_mdns_rr_state = NX_MDNS_RR_STATE_GOODBYE;
10737 
10738                     /* Clear the retransmit count.  */
10739                     p -> nx_mdns_rr_retransmit_count = NX_MDNS_GOODBYE_RETRANSMIT_COUNT;
10740 
10741                     /* Set the timer count. 250ms.  */
10742                     p -> nx_mdns_rr_timer_count = NX_MDNS_GOODBYE_TIMER_COUNT;
10743 
10744                     /* Set the delete flag.  */
10745                     p -> nx_mdns_rr_word = (p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_DELETE);
10746 
10747                     /* Set the mDNS timer.  */
10748                     _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count);
10749                 }
10750 
10751 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
10752                 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
10753                     _nx_mdns_cache_delete_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, p);
10754 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
10755             }
10756         }
10757 
10758         /* Second register the host name, the host does not need to repeat the Probing step, Only Announcing the A/AAAA.  */
10759         _nx_mdns_host_name_register(mdns_ptr, NX_FALSE, i);
10760     }
10761 }
10762 
10763 
10764 /**************************************************************************/
10765 /*                                                                        */
10766 /*  FUNCTION                                               RELEASE        */
10767 /*                                                                        */
10768 /*    _nx_mdns_conflict_process                           PORTABLE C      */
10769 /*                                                           6.1          */
10770 /*  AUTHOR                                                                */
10771 /*                                                                        */
10772 /*    Yuxin Zhou, Microsoft Corporation                                   */
10773 /*                                                                        */
10774 /*  DESCRIPTION                                                           */
10775 /*                                                                        */
10776 /*    This function process the mDNS conflict. RFC6762, Section9, Page31  */
10777 /*                                                                        */
10778 /*  INPUT                                                                 */
10779 /*                                                                        */
10780 /*    mdns_ptr                              Pointer to mDNS instance      */
10781 /*    record_rr                             The resource record           */
10782 /*                                                                        */
10783 /*  OUTPUT                                                                */
10784 /*                                                                        */
10785 /*    status                                Completion status             */
10786 /*                                                                        */
10787 /*  CALLS                                                                 */
10788 /*                                                                        */
10789 /*    _nx_mdns_cache_add_string             Add the string                */
10790 /*    _nx_mdns_cache_delete_string          Delete the string             */
10791 /*    _nx_mdns_srv_name_resolve             Reslove the service name      */
10792 /*    nx_mdns_rr_change_notify              Resource record notify        */
10793 /*                                                                        */
10794 /*  CALLED BY                                                             */
10795 /*                                                                        */
10796 /*    _nx_mdns_packet_process               Process mDNS packet           */
10797 /*                                                                        */
10798 /*  RELEASE HISTORY                                                       */
10799 /*                                                                        */
10800 /*    DATE              NAME                      DESCRIPTION             */
10801 /*                                                                        */
10802 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10803 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
10804 /*                                            buffer length verification, */
10805 /*                                            verified memcpy use cases,  */
10806 /*                                            resulting in version 6.1    */
10807 /*                                                                        */
10808 /**************************************************************************/
_nx_mdns_conflict_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_rr)10809 static UINT _nx_mdns_conflict_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr)
10810 {
10811 
10812 UINT        status;
10813 UCHAR       *old_name;
10814 UCHAR       *name;
10815 UCHAR       *type = NX_NULL;
10816 UCHAR       *domain = NX_NULL;
10817 UINT        i;
10818 ULONG       *head;
10819 NX_MDNS_RR  *p;
10820 UCHAR       is_host_type;
10821 UINT        temp_string_length;
10822 UINT        rr_name_length;
10823 
10824 
10825     /* Initialize the value.  */
10826     i = 0;
10827     memset(&temp_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10828     memset(&target_string_buffer[0], 0, NX_MDNS_NAME_MAX + 1);
10829 
10830     /* Get rr type. */
10831     if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10832        (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT))
10833     {
10834         is_host_type = NX_FALSE;
10835 
10836         /* Check string length.  */
10837         if (_nx_utility_string_length_check((CHAR *)(record_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
10838         {
10839             return(NX_MDNS_DATA_SIZE_ERROR);
10840         }
10841 
10842         /* Store the service name.  */
10843         memcpy((CHAR *)&target_string_buffer[0], (const char*)(record_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
10844 
10845         /* Get Name, Type, Domain.  */
10846         _nx_mdns_service_name_resolve(&target_string_buffer[0], &name, &type, &domain);
10847     }
10848     else if((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
10849             (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA))
10850     {
10851         is_host_type = NX_TRUE;
10852         name = mdns_ptr -> nx_mdns_host_name;
10853     }
10854     else
10855     {
10856 
10857         /* This is an unsupported or unknown type. */
10858         return(NX_MDNS_UNSUPPORTED_TYPE);
10859     }
10860 
10861     /* Check the conflict count.  */
10862     if (record_rr -> nx_mdns_rr_conflict_count >= NX_MDNS_CONFLICT_COUNT)
10863     {
10864 
10865         /* Yes, Receive the confilictiong mDNS, Probing failure.  */
10866         if ((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
10867             (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A))
10868         {
10869 
10870             /* Service name has been registered , invoke the notify function.  */
10871             if (mdns_ptr -> nx_mdns_probing_notify)
10872             {
10873                 (mdns_ptr -> nx_mdns_probing_notify)(mdns_ptr, name, NX_MDNS_LOCAL_SERVICE_REGISTERED_FAILURE);
10874             }
10875         }
10876 
10877         /* Return.  */
10878         return (NX_MDNS_ERROR);
10879     }
10880 
10881     /* Record the old name.  */
10882     old_name = record_rr -> nx_mdns_rr_name;
10883 
10884     /* Set the new name and probing it.  */
10885     while ((*name) != '\0')
10886     {
10887         temp_string_buffer[i++] = *name++;
10888     }
10889 
10890     /* The first conflict, only add the " (2)".  */
10891     if (record_rr -> nx_mdns_rr_conflict_count == 0)
10892     {
10893         temp_string_buffer[i++] = ' ';
10894         temp_string_buffer[i++] = '(';
10895         temp_string_buffer[i++] = '2';
10896         temp_string_buffer[i++] = ')';
10897     }
10898 
10899     /* Modify the count, eg: " (2)" change to " (3)".  */
10900     else
10901     {
10902         temp_string_buffer[i-2] = (UCHAR)(temp_string_buffer[i-2] + 1);
10903     }
10904 
10905 
10906     if(is_host_type == NX_TRUE)
10907     {
10908 
10909         /* Check string length.  */
10910         if (_nx_utility_string_length_check((CHAR *)temp_string_buffer, &temp_string_length, NX_MDNS_HOST_NAME_MAX))
10911         {
10912             return(NX_MDNS_DATA_SIZE_ERROR);
10913         }
10914 
10915         /* Construct the target host.  */
10916         memcpy((CHAR *)(mdns_ptr -> nx_mdns_host_name), (CHAR *)(temp_string_buffer), temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_HOST_NAME_MAX is limited in nxd_mdns.h. */
10917 
10918         temp_string_buffer[i++] = '.';
10919 
10920         /* Check string length.  */
10921         if (_nx_utility_string_length_check((CHAR *)mdns_ptr -> nx_mdns_domain_name, &temp_string_length, NX_MDNS_DOMAIN_NAME_MAX))
10922         {
10923             return(NX_MDNS_DATA_SIZE_ERROR);
10924         }
10925 
10926         /* Add the domain.  */
10927         memcpy((CHAR *)(&temp_string_buffer[i]), (CHAR *)mdns_ptr -> nx_mdns_domain_name, temp_string_length); /* Use case of memcpy is verified. The NX_MDNS_DOMAIN_NAME_MAX is limited in nxd_mdns.h. */
10928     }
10929     else
10930     {
10931         temp_string_buffer[i++] = '.';
10932 
10933         /* Set the Type.  */
10934         while ((*type) != '\0')
10935         {
10936             temp_string_buffer[i++] = *type++;
10937         }
10938 
10939         temp_string_buffer[i++] = '.';
10940 
10941         /* Set the Domain.  */
10942         while ((*domain) != '\0')
10943         {
10944             temp_string_buffer[i++] = *domain++;
10945         }
10946     }
10947 
10948     /* Check string length.  */
10949     if (_nx_utility_string_length_check((CHAR *)&temp_string_buffer[0], &temp_string_length, NX_MDNS_NAME_MAX))
10950     {
10951         return(NX_MDNS_DATA_SIZE_ERROR);
10952     }
10953 
10954     /* Add the new resource records. */
10955     status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL,
10956                                        &temp_string_buffer[0], temp_string_length,
10957                                        (VOID **)(&record_rr -> nx_mdns_rr_name), NX_FALSE, NX_TRUE);
10958 
10959     if (status )
10960     {
10961 
10962         /* No, return error status.  */
10963         return(status);
10964     }
10965 
10966     /* Update the state.  */
10967     record_rr -> nx_mdns_rr_state = NX_MDNS_RR_STATE_PROBING;
10968     record_rr -> nx_mdns_rr_timer_count = mdns_ptr -> nx_mdns_first_probing_delay;
10969     record_rr -> nx_mdns_rr_retransmit_count = NX_MDNS_PROBING_RETRANSMIT_COUNT;
10970     record_rr -> nx_mdns_rr_conflict_count ++;
10971 
10972     /* Set the mDNS timer.  */
10973     _nx_mdns_timer_set(mdns_ptr, record_rr, record_rr -> nx_mdns_rr_timer_count);
10974 
10975     /* Update the PTR/SRV data name.  */
10976     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
10977     head = (ULONG*)(*head);
10978 
10979     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
10980     {
10981         if ((((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) && (is_host_type == NX_FALSE)) ||
10982              ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) && (is_host_type == NX_TRUE))) &&
10983             (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == old_name))
10984         {
10985 
10986             /* Add the new resource records. */
10987             status = _nx_mdns_cache_add_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, &temp_string_buffer[0], temp_string_length,
10988                                                (VOID **)(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)), NX_FALSE, NX_TRUE);
10989 
10990             /* Delete the rdata name.  */
10991             _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10992         }
10993     }
10994 
10995     /* Delete the old name.  */
10996     _nx_mdns_cache_delete_string(mdns_ptr, NX_MDNS_CACHE_TYPE_LOCAL, old_name, 0);
10997 
10998     return(NX_MDNS_SUCCESS);
10999 }
11000 #endif /* NX_MDNS_DISABLE_SERVER  */
11001 
11002 
11003 #ifndef NX_MDNS_DISABLE_CLIENT
11004 /**************************************************************************/
11005 /*                                                                        */
11006 /*  FUNCTION                                               RELEASE        */
11007 /*                                                                        */
11008 /*    _nx_mdns_service_change_notify_process              PORTABLE C      */
11009 /*                                                           6.1          */
11010 /*  AUTHOR                                                                */
11011 /*                                                                        */
11012 /*    Yuxin Zhou, Microsoft Corporation                                   */
11013 /*                                                                        */
11014 /*  DESCRIPTION                                                           */
11015 /*                                                                        */
11016 /*    This function processes the mDNS service change operation, when the */
11017 /*    service information change, notify the application.                 */
11018 /*                                                                        */
11019 /*  INPUT                                                                 */
11020 /*                                                                        */
11021 /*    mdns_ptr                              Pointer to mDNS instance      */
11022 /*    record_rr                             The resource record           */
11023 /*    is_present                            The service type              */
11024 /*                                                                        */
11025 /*  OUTPUT                                                                */
11026 /*                                                                        */
11027 /*    status                                Completion status             */
11028 /*                                                                        */
11029 /*  CALLS                                                                 */
11030 /*                                                                        */
11031 /*    tx_mutex_get                          Get the mDNS mutex            */
11032 /*    tx_mutex_put                          Put the mDNS mutex            */
11033 /*                                                                        */
11034 /*  CALLED BY                                                             */
11035 /*                                                                        */
11036 /*    Application Code                                                    */
11037 /*                                                                        */
11038 /*  RELEASE HISTORY                                                       */
11039 /*                                                                        */
11040 /*    DATE              NAME                      DESCRIPTION             */
11041 /*                                                                        */
11042 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11043 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11044 /*                                            verified memcpy use cases,  */
11045 /*                                            resulting in version 6.1    */
11046 /*                                                                        */
11047 /**************************************************************************/
_nx_mdns_service_change_notify_process(NX_MDNS * mdns_ptr,NX_MDNS_RR * new_rr,UCHAR is_present)11048 static VOID _nx_mdns_service_change_notify_process(NX_MDNS *mdns_ptr, NX_MDNS_RR *new_rr, UCHAR is_present)
11049 {
11050 
11051 UINT            notify_status = 0;
11052 ULONG           *head;
11053 NX_MDNS_RR      *p;
11054 NX_MDNS_SERVICE temp_service;
11055 UINT            rr_name_length;
11056 
11057 
11058     /* Initialize the struct.  */
11059     memset(&temp_service, 0, sizeof(NX_MDNS_SERVICE));
11060 
11061     /* Compare the RDATA. */
11062     switch (new_rr -> nx_mdns_rr_type)
11063     {
11064         case NX_MDNS_RR_TYPE_A:
11065         case NX_MDNS_RR_TYPE_AAAA:
11066         {
11067 
11068             /* Get the remote buffer head. */
11069             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11070             head = (ULONG*)(*head);
11071 
11072             /* Check the resource record.  */
11073             for(p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_peer_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
11074             {
11075 
11076                 /* Check whether the resource record is valid. */
11077                 if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11078                     (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11079                     continue;
11080 
11081                 /* Check the interface.  */
11082                 if (p -> nx_mdns_rr_interface_index != new_rr -> nx_mdns_rr_interface_index)
11083                     continue;
11084 
11085                 if (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
11086                 {
11087                     if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == new_rr -> nx_mdns_rr_name)
11088                     {
11089 
11090                         /* Check string length.  */
11091                         if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11092                         {
11093                             break;
11094                         }
11095 
11096                         /* Store the Service name.  */
11097                         memcpy((CHAR *)(&temp_string_buffer[0]), (CHAR *)(p -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11098 
11099                         /* Check if the address is updated.  */
11100                         if (((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0)) ||
11101                             (((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))))
11102                         {
11103                             notify_status = NX_MDNS_PEER_SERVICE_UPDATED;
11104                         }
11105                         break;
11106                     }
11107                 }
11108             }
11109 
11110             break;
11111         }
11112         case NX_MDNS_RR_TYPE_SRV:
11113         {
11114 
11115             /* Check string length.  */
11116             if (_nx_utility_string_length_check((CHAR *)(new_rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11117             {
11118                 break;
11119             }
11120 
11121             /* Store the Service name.  */
11122             memcpy((CHAR *)&temp_string_buffer[0], (CHAR *)(new_rr -> nx_mdns_rr_name), rr_name_length + 1); /* Use case of memcpy is verified. */
11123 
11124             /* Check if the service is new.  */
11125             if ((is_present == NX_FALSE) && (new_rr -> nx_mdns_rr_ttl != 0))
11126             {
11127                 notify_status = NX_MDNS_PEER_SERVICE_RECEIVED;
11128             }
11129             else if ((is_present == NX_TRUE) && (new_rr -> nx_mdns_rr_ttl == 0))
11130             {
11131                 notify_status = NX_MDNS_PEER_SERVICE_DELETED;
11132             }
11133             break;
11134         }
11135         default:
11136         {
11137 
11138             /* This is an unsupported or unknown type. */
11139             return;
11140         }
11141     }
11142 
11143     /* Check if need to call then notify function.  */
11144     if (notify_status == 0)
11145         return;
11146 
11147     /* Store the service name.  */
11148     memcpy((CHAR *)(&temp_service.buffer[0]), (CHAR *)(&temp_string_buffer[0]), rr_name_length); /* Use case of memcpy is verified. */
11149 
11150     /* Reslove the service name.  */
11151     if (_nx_mdns_service_name_resolve(&temp_service.buffer[0], &(temp_service.service_name), &(temp_service.service_type), &(temp_service.service_domain)))
11152         return;
11153 
11154     /* Compare the service change type.  */
11155     if (_nx_mdns_service_mask_match(mdns_ptr, temp_service.service_type, mdns_ptr -> nx_mdns_service_notify_mask))
11156         return;
11157 
11158     /* Get the additional information.  */
11159     _nx_mdns_service_addition_info_get(mdns_ptr, &temp_string_buffer[0], &temp_service, new_rr -> nx_mdns_rr_interface_index);
11160 
11161     /* Call the notify function.  */
11162     (mdns_ptr -> nx_mdns_service_change_notify)(mdns_ptr, &temp_service, notify_status);
11163 }
11164 
11165 
11166 /**************************************************************************/
11167 /*                                                                        */
11168 /*  FUNCTION                                               RELEASE        */
11169 /*                                                                        */
11170 /*    _nx_mdns_service_addition_info_get                  PORTABLE C      */
11171 /*                                                           6.1          */
11172 /*  AUTHOR                                                                */
11173 /*                                                                        */
11174 /*    Yuxin Zhou, Microsoft Corporation                                   */
11175 /*                                                                        */
11176 /*  DESCRIPTION                                                           */
11177 /*                                                                        */
11178 /*    This function adds the mDNS resource record into remote buffer,     */
11179 /*    mDNS thread send the query message using continuous type.           */
11180 /*                                                                        */
11181 /*  INPUT                                                                 */
11182 /*                                                                        */
11183 /*    mdns_ptr                              Pointer to mDNS instance      */
11184 /*    name                                  The service instance          */
11185 /*    type                                  The service type              */
11186 /*    domain                                The domain name               */
11187 /*                                                                        */
11188 /*  OUTPUT                                                                */
11189 /*                                                                        */
11190 /*    status                                Completion status             */
11191 /*                                                                        */
11192 /*  CALLS                                                                 */
11193 /*                                                                        */
11194 /*    tx_mutex_get                          Get the mDNS mutex            */
11195 /*    tx_mutex_put                          Put the mDNS mutex            */
11196 /*    _nx_mdns_query_check                  Check the query RR            */
11197 /*    _nx_mdns_cache_add_string             Add the string into buffer    */
11198 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11199 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
11200 /*                                            into buffer                 */
11201 /*                                                                        */
11202 /*  CALLED BY                                                             */
11203 /*                                                                        */
11204 /*    Application Code                                                    */
11205 /*                                                                        */
11206 /*  RELEASE HISTORY                                                       */
11207 /*                                                                        */
11208 /*    DATE              NAME                      DESCRIPTION             */
11209 /*                                                                        */
11210 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11211 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11212 /*                                            verified memcpy use cases,  */
11213 /*                                            resulting in version 6.1    */
11214 /*                                                                        */
11215 /**************************************************************************/
_nx_mdns_service_addition_info_get(NX_MDNS * mdns_ptr,UCHAR * srv_name,NX_MDNS_SERVICE * service,UINT interface_index)11216 static UINT _nx_mdns_service_addition_info_get(NX_MDNS *mdns_ptr, UCHAR *srv_name, NX_MDNS_SERVICE *service, UINT interface_index)
11217 {
11218 
11219 UINT        index = 0;
11220 ULONG       current_time;
11221 ULONG       *head, *tail;
11222 UCHAR       i;
11223 NX_MDNS_RR  *p;
11224 NX_MDNS_RR  *p1;
11225 UINT        srv_name_length;
11226 UINT        temp_length;
11227 
11228 
11229     /* Check string length.  */
11230     if (_nx_utility_string_length_check((CHAR *)srv_name, &srv_name_length, NX_MDNS_NAME_MAX))
11231     {
11232         return(NX_MDNS_ERROR);
11233     }
11234 
11235     /* Get the current time.  */
11236     current_time = tx_time_get();
11237 
11238     for(i = 0; i < 2; i++)
11239     {
11240 
11241         /* Set the pointer. */
11242         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
11243         {
11244 #ifndef NX_MDNS_DISABLE_SERVER
11245             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
11246 #else
11247             continue;
11248 #endif /* NX_MDNS_DISABLE_SERVER */
11249         }
11250         else
11251         {
11252 #ifndef NX_MDNS_DISABLE_CLIENT
11253             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
11254 #else
11255             continue;
11256 #endif /* NX_MDNS_DISABLE_CLIENT  */
11257         }
11258 
11259         if(head == NX_NULL)
11260             continue;
11261 
11262         /* Set the pointer.  */
11263         tail = (ULONG*)(*head);
11264 
11265         /* Check the resource record.  */
11266         for(p = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p < tail; p++)
11267         {
11268 
11269             /* Check whether the resource record is valid. */
11270             if ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID) ||
11271                 (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
11272                 continue;
11273 
11274             /* Check the interface index.  */
11275             if (p -> nx_mdns_rr_interface_index != interface_index)
11276                 continue;
11277 
11278             /* Check the type and name. */
11279             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
11280                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11281             {
11282 
11283                 /* Update the elasped timer.  */
11284                 p -> nx_mdns_rr_elapsed_time = current_time;
11285 
11286                 /* Set the service priority, weight, port and target. */
11287                 service -> service_priority = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority;
11288                 service -> service_weight = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights;
11289                 service -> service_port = p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port;
11290 
11291                 /* Check string length.  */
11292                 if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target), &temp_length, NX_MDNS_HOST_NAME_MAX))
11293                 {
11294                     return(NX_MDNS_ERROR);
11295                 }
11296 
11297                 /* Store the target host.  */
11298                 memcpy((CHAR *)(service -> service_host), /* Use case of memcpy is verified. */
11299                        (CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target),
11300                        temp_length + 1);
11301 
11302                 /* All address records (type "A" and "AAAA") named in the SRV rdata */
11303                 for (p1 = (NX_MDNS_RR*)((UCHAR*)(head + 1)); (ULONG*)p1 < tail; p1++)
11304                 {
11305 
11306                     /* Update the elasped timer.  */
11307                     p1 -> nx_mdns_rr_elapsed_time = current_time;
11308 
11309                     /* Check the interface index.  */
11310                     if (p1 -> nx_mdns_rr_interface_index != interface_index)
11311                         continue;
11312 
11313                     /* Find the "A" records.  */
11314                     if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) &&
11315                         (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11316                     {
11317 
11318                         /* Set the IPv4 address.  */
11319                         service -> service_ipv4 = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address;
11320                     }
11321 
11322                     /* Find the "AAAA" records.  */
11323                     if ((p1 -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA) &&
11324                         (p1 -> nx_mdns_rr_name == p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11325                     {
11326                         if (index < NX_MDNS_IPV6_ADDRESS_COUNT)
11327                         {
11328 
11329                             /* Set the IPv6 address.  */
11330                             service -> service_ipv6[index][0] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0];
11331                             service -> service_ipv6[index][1] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1];
11332                             service -> service_ipv6[index][2] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[2];
11333                             service -> service_ipv6[index][3] = p1 -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[3];
11334                             index ++;
11335                         }
11336                     }
11337                 }
11338             }
11339 
11340             /* Check the type and name. */
11341             if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) &&
11342                 (!_nx_mdns_name_match(p -> nx_mdns_rr_name, srv_name, srv_name_length)))
11343             {
11344 
11345                 /* Update the elasped timer.  */
11346                 p -> nx_mdns_rr_elapsed_time = current_time;
11347 
11348                 /* Set the text valid flag.  */
11349                 service -> service_text_valid = 1;
11350 
11351                 if (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data)
11352                 {
11353 
11354                     /* Check string length.  */
11355                     if (_nx_utility_string_length_check((CHAR *)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), &temp_length, NX_MDNS_NAME_MAX))
11356                     {
11357                         continue;
11358                     }
11359 
11360                     /* Store the txt.  */
11361                     memcpy((CHAR *)(service -> service_text), (const char*)(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_txt.nx_mdns_rr_txt_data), temp_length + 1); /* Use case of memcpy is verified. */
11362                 }
11363             }
11364         }
11365     }
11366 
11367     /* Set the interface index.  */
11368     service -> interface_index = (UCHAR)interface_index;
11369 
11370     /* Return a error status.  */
11371     return(NX_MDNS_SUCCESS);
11372 }
11373 #endif /* NX_MDNS_DISABLE_CLIENT */
11374 
11375 
11376 /**************************************************************************/
11377 /*                                                                        */
11378 /*  FUNCTION                                               RELEASE        */
11379 /*                                                                        */
11380 /*    _nx_mdns_cache_initialize                         PORTABLE C       */
11381 /*                                                           6.1          */
11382 /*  AUTHOR                                                                */
11383 /*                                                                        */
11384 /*    Yuxin Zhou, Microsoft Corporation                                   */
11385 /*                                                                        */
11386 /*  DESCRIPTION                                                           */
11387 /*                                                                        */
11388 /*    This function initializes the mDNS remote buffer and local buffer.  */
11389 /*                                                                        */
11390 /*  INPUT                                                                 */
11391 /*                                                                        */
11392 /*    mdns_ptr                              Pointer to mDNS instance      */
11393 /*    local_cache_ptr                       Pointer to local cache        */
11394 /*    local_cache_size                      The size of local cache       */
11395 /*    peer_cache_ptr                        Pointer to peer cache         */
11396 /*    peer_cache_size                       The size of peer cache        */
11397 /*                                                                        */
11398 /*  OUTPUT                                                                */
11399 /*                                                                        */
11400 /*    status                                Completion status             */
11401 /*                                                                        */
11402 /*  CALLS                                                                 */
11403 /*                                                                        */
11404 /*    tx_mutex_get                          Get the mDNS mutex            */
11405 /*    tx_mutex_put                          Put the mDNS mutex            */
11406 /*                                                                        */
11407 /*  CALLED BY                                                             */
11408 /*                                                                        */
11409 /*    _nx_mdns_create                       Initialize the mDNS structure */
11410 /*    _nx_mdns_disable                      Disable the mDNS function     */
11411 /*    _nx_mdns_peer_cache_clear             Clear the peer cache          */
11412 /*                                                                        */
11413 /*  RELEASE HISTORY                                                       */
11414 /*                                                                        */
11415 /*    DATE              NAME                      DESCRIPTION             */
11416 /*                                                                        */
11417 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11418 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11419 /*                                            resulting in version 6.1    */
11420 /*                                                                        */
11421 /**************************************************************************/
_nx_mdns_cache_initialize(NX_MDNS * mdns_ptr,VOID * local_cache_ptr,UINT local_cache_size,VOID * peer_cache_ptr,UINT peer_cache_size)11422 UINT _nx_mdns_cache_initialize(NX_MDNS *mdns_ptr, VOID *local_cache_ptr, UINT local_cache_size,
11423                                VOID *peer_cache_ptr, UINT peer_cache_size)
11424 {
11425 
11426 ULONG *head;
11427 ULONG *tail;
11428 
11429 
11430 #ifndef NX_MDNS_DISABLE_SERVER
11431     /* Check the cache.  */
11432     if (local_cache_ptr)
11433     {
11434 
11435         /* Zero out the cache. */
11436         memset(local_cache_ptr, 0, local_cache_size);
11437 
11438         /* Set the head. */
11439         head = (ULONG*)local_cache_ptr;
11440         *head = (ULONG)((ULONG*)local_cache_ptr + 1);
11441 
11442         /* Set the tail. */
11443         tail = (ULONG*)local_cache_ptr + (local_cache_size >> 2) - 1;
11444         *tail = (ULONG)tail;
11445 
11446         /* Record the info.  */
11447         mdns_ptr -> nx_mdns_local_service_cache = (UCHAR*)local_cache_ptr;
11448         mdns_ptr -> nx_mdns_local_service_cache_size = local_cache_size;
11449 
11450         /* Clear the count.  */
11451         mdns_ptr -> nx_mdns_local_rr_count = 0;
11452         mdns_ptr -> nx_mdns_local_string_count = 0;
11453         mdns_ptr -> nx_mdns_local_string_bytes = 0;
11454     }
11455 #else
11456     NX_PARAMETER_NOT_USED(local_cache_ptr);
11457     NX_PARAMETER_NOT_USED(local_cache_size);
11458 #endif /* NX_MDNS_DISABLE_SERVER */
11459 
11460 #ifndef NX_MDNS_DISABLE_CLIENT
11461     /* Check the cache.  */
11462     if (peer_cache_ptr)
11463     {
11464 
11465         /* Zero out the cache. */
11466         memset(peer_cache_ptr, 0, peer_cache_size);
11467 
11468         /* Set the head. */
11469         head = (ULONG*)peer_cache_ptr;
11470         *head = (ULONG)((ULONG*)peer_cache_ptr + 1);
11471 
11472         /* Set the tail. */
11473         tail = (ULONG*)peer_cache_ptr + (peer_cache_size >> 2) - 1;
11474         *tail = (ULONG)tail;
11475 
11476         /* Record the info.  */
11477         mdns_ptr -> nx_mdns_peer_service_cache = (UCHAR*)peer_cache_ptr;
11478         mdns_ptr -> nx_mdns_peer_service_cache_size = peer_cache_size;
11479 
11480         /* Clear the count.  */
11481         mdns_ptr -> nx_mdns_peer_rr_count = 0;
11482         mdns_ptr -> nx_mdns_peer_string_count = 0;
11483         mdns_ptr -> nx_mdns_peer_string_bytes = 0;
11484     }
11485 #else
11486     NX_PARAMETER_NOT_USED(peer_cache_ptr);
11487     NX_PARAMETER_NOT_USED(peer_cache_size);
11488 #endif /* NX_MDNS_DISABLE_CLIENT */
11489 
11490     return(NX_SUCCESS);
11491 }
11492 
11493 
11494 /**************************************************************************/
11495 /*                                                                        */
11496 /*  FUNCTION                                               RELEASE        */
11497 /*                                                                        */
11498 /*    _nx_mdns_cache_add_resource_record                  PORTABLE C      */
11499 /*                                                           6.1          */
11500 /*  AUTHOR                                                                */
11501 /*                                                                        */
11502 /*    Yuxin Zhou, Microsoft Corporation                                   */
11503 /*                                                                        */
11504 /*  DESCRIPTION                                                           */
11505 /*                                                                        */
11506 /*    This function adds the mDNS  resource record into record buffer.    */
11507 /*                                                                        */
11508 /*  INPUT                                                                 */
11509 /*                                                                        */
11510 /*    mdns_ptr                              Pointer to mDNS instance      */
11511 /*    cache_type                            Cache type: local or peer     */
11512 /*    record_ptr                            Pointer to resource record    */
11513 /*    insert_rr                             Pointer to insert resource    */
11514 /*                                            record                      */
11515 /*                                                                        */
11516 /*  OUTPUT                                                                */
11517 /*                                                                        */
11518 /*    status                                Completion status             */
11519 /*                                                                        */
11520 /*  CALLS                                                                 */
11521 /*                                                                        */
11522 /*    _nx_mdns_cache_find_resource_record   Find the resource record      */
11523 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11524 /*                                                                        */
11525 /*  CALLED BY                                                             */
11526 /*                                                                        */
11527 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
11528 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
11529 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
11530 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
11531 /*    _nx_mdns_query                        Send query                    */
11532 /*    _nx_mdns_cache_delete_rr_string       Delete the rr string          */
11533 /*    _nx_mdns_packet_rr_process            Process resource record       */
11534 /*                                                                        */
11535 /*  RELEASE HISTORY                                                       */
11536 /*                                                                        */
11537 /*    DATE              NAME                      DESCRIPTION             */
11538 /*                                                                        */
11539 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11540 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
11541 /*                                            verified memcpy use cases,  */
11542 /*                                            resulting in version 6.1    */
11543 /*                                                                        */
11544 /**************************************************************************/
_nx_mdns_cache_add_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,NX_MDNS_RR ** insert_ptr,UCHAR * is_present)11545 UINT _nx_mdns_cache_add_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, NX_MDNS_RR **insert_ptr, UCHAR *is_present)
11546 {
11547 
11548 UCHAR       *cache_ptr;
11549 UINT        cache_size;
11550 ULONG       *tail;
11551 ULONG       *head;
11552 NX_MDNS_RR  *p;
11553 NX_MDNS_RR  *rr;
11554 UINT        rr_name_length;
11555 
11556 #ifndef NX_MDNS_DISABLE_CLIENT
11557 ULONG       elapsed_time;
11558 ULONG       current_time;
11559 ULONG       min_elapsed_time;
11560 #endif /* NX_MDNS_DISABLE_CLIENT  */
11561 
11562 
11563 #ifndef NX_MDNS_DISABLE_CLIENT
11564     /* Initialize the parameters.  */
11565     min_elapsed_time = 0;
11566     current_time = tx_time_get();
11567 #endif /* NX_MDNS_DISABLE_CLIENT  */
11568 
11569     /* Initialize.  */
11570     if (is_present)
11571         *is_present = NX_FALSE;
11572 
11573     /* Check the RR with same rname, rtype, rclass and rdata.  */
11574     if (_nx_mdns_cache_find_resource_record(mdns_ptr, cache_type, record_ptr, NX_MDNS_RR_MATCH_ALL, &rr) == NX_MDNS_SUCCESS)
11575     {
11576 
11577         /* Check string length.  */
11578         if (_nx_utility_string_length_check((CHAR *)(rr -> nx_mdns_rr_name), &rr_name_length, NX_MDNS_NAME_MAX))
11579         {
11580             return(NX_MDNS_DATA_SIZE_ERROR);
11581         }
11582 
11583         /* Copy other informations of record_ptr into insert_rr resource record.  */
11584         memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11585 
11586         /* Special process for _services._dns-sd._udp.local which pointer to same service type.  */
11587         if ((rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR) &&
11588             (!_nx_mdns_name_match(rr -> nx_mdns_rr_name, (UCHAR *)_nx_mdns_dns_sd, rr_name_length)))
11589         {
11590             rr -> nx_mdns_rr_count ++;
11591         }
11592 
11593         /* Delete the resource record same strings. */
11594         _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, rr);
11595 
11596         /* Set the insert ptr.  */
11597         if(insert_ptr != NX_NULL)
11598             *insert_ptr = rr;
11599 
11600         /* Set the flag.  */
11601         if (is_present)
11602             *is_present = NX_TRUE;
11603 
11604         return(NX_MDNS_SUCCESS);
11605     }
11606 
11607     /* Check the cache type.  */
11608     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11609     {
11610         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11611         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
11612     }
11613     else
11614     {
11615         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11616         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
11617     }
11618 
11619     /* Check cache pointer and cache size.  */
11620     if ((cache_ptr == NX_NULL) || (cache_size == 0))
11621     {
11622         return(NX_MDNS_ERROR);
11623     }
11624 
11625     /* Get head and tail. */
11626     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
11627     tail = (ULONG*)(*tail);
11628     head = (ULONG*)cache_ptr;
11629     head = (ULONG*)(*head);
11630 
11631     /* Set the pointer.  */
11632     rr = NX_NULL;
11633 
11634     /* Find an empty entry before head. */
11635     for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11636     {
11637         if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11638         {
11639             rr = p;
11640             break;
11641         }
11642     }
11643 
11644     if (!rr)
11645     {
11646 
11647         /* Check whether the cache is full. */
11648         if((head + (sizeof(NX_MDNS_RR) >> 2)) > tail)
11649         {
11650             if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11651             {
11652                 return(NX_MDNS_CACHE_ERROR);
11653             }
11654             else
11655             {
11656 
11657 #ifndef NX_MDNS_DISABLE_CLIENT
11658                 /* Find an aging resource reocrd and repalce it.  */
11659                 for(p = (NX_MDNS_RR*)((ULONG*)cache_ptr + 1); p < (NX_MDNS_RR*)head; p++)
11660                 {
11661 
11662                     if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11663                         continue;
11664 
11665                     /* Calculate the elapsed time.  */
11666                     elapsed_time = current_time - p -> nx_mdns_rr_elapsed_time;
11667 
11668                     /* Check the elapsed time to find the aging resource record.  */
11669                     if (elapsed_time >= min_elapsed_time)
11670                     {
11671                         rr = p;
11672                         min_elapsed_time = elapsed_time;
11673                     }
11674                 }
11675 
11676                 if (rr)
11677                 {
11678 
11679                     /* Delete this record.  */
11680                     _nx_mdns_cache_delete_resource_record(mdns_ptr, cache_type, rr);
11681 
11682                     /* Update the head.  */
11683                     head = (ULONG*)cache_ptr;
11684                     head = (ULONG*)(*head);
11685                 }
11686                 else
11687                 {
11688                     return(NX_MDNS_CACHE_ERROR);
11689                 }
11690 #endif /* NX_MDNS_DISABLE_CLIENT */
11691             }
11692         }
11693         else
11694         {
11695             rr = (NX_MDNS_RR*)head;
11696         }
11697     }
11698 
11699     /* Just copy it to cache_ptr. */
11700     memcpy(rr, record_ptr, sizeof(NX_MDNS_RR)); /* Use case of memcpy is verified. */
11701 
11702     /* Check the type.  */
11703     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11704     {
11705 
11706         /* Increase the count.  */
11707         mdns_ptr -> nx_mdns_local_rr_count ++;
11708     }
11709     else
11710     {
11711 
11712         /* Increase the count.  */
11713         mdns_ptr -> nx_mdns_peer_rr_count ++;
11714     }
11715 
11716 #ifndef NX_MDNS_DISABLE_CLIENT
11717     /* Update the peer resource record elapsed time.  */
11718     if (cache_type == NX_MDNS_CACHE_TYPE_PEER)
11719     {
11720 
11721         /* Get the current time to set the elapsed time.  */
11722         rr -> nx_mdns_rr_elapsed_time = current_time;
11723     }
11724 #endif /* NX_MDNS_DISABLE_CLIENT */
11725 
11726     /* Set the insert ptr.  */
11727     if(insert_ptr != NX_NULL)
11728         *insert_ptr = rr;
11729 
11730     if((ULONG*)rr >= head)
11731     {
11732 
11733         /* Update HEAD when new record is added. */
11734         head = (ULONG*)cache_ptr;
11735         *head = (ULONG)(rr + 1);
11736     }
11737 
11738     return(NX_MDNS_SUCCESS);
11739 }
11740 
11741 
11742 /**************************************************************************/
11743 /*                                                                        */
11744 /*  FUNCTION                                               RELEASE        */
11745 /*                                                                        */
11746 /*    _nx_mdns_cache_delete_resource_record               PORTABLE C      */
11747 /*                                                           6.1          */
11748 /*  AUTHOR                                                                */
11749 /*                                                                        */
11750 /*    Yuxin Zhou, Microsoft Corporation                                   */
11751 /*                                                                        */
11752 /*  DESCRIPTION                                                           */
11753 /*                                                                        */
11754 /*    This function deletes the mDNS resource record from record buffer.  */
11755 /*                                                                        */
11756 /*  INPUT                                                                 */
11757 /*                                                                        */
11758 /*    mdns_ptr                              Pointer to mDNS instance.     */
11759 /*    cache_type                            Cache type: local or peer     */
11760 /*    record_ptr                            Pointer to resource record.   */
11761 /*                                                                        */
11762 /*  OUTPUT                                                                */
11763 /*                                                                        */
11764 /*    status                                Completion status             */
11765 /*                                                                        */
11766 /*  CALLS                                                                 */
11767 /*                                                                        */
11768 /*    _nx_mdns_cache_delete_string          Delete the string from buffer */
11769 /*                                                                        */
11770 /*  CALLED BY                                                             */
11771 /*                                                                        */
11772 /*    _nx_mdns_rr_delete                    Delete the resource record    */
11773 /*    _nx_mdns_query                        Send the one-shot query       */
11774 /*    _nx_mdns_timer_event_process          Process the timer event       */
11775 /*    _nx_mdns_packet_process               Process mDNS packet           */
11776 /*    _nx_mdns_cache_delete_rr_string       Delete the rr string          */
11777 /*                                                                        */
11778 /*  RELEASE HISTORY                                                       */
11779 /*                                                                        */
11780 /*    DATE              NAME                      DESCRIPTION             */
11781 /*                                                                        */
11782 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11783 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11784 /*                                            resulting in version 6.1    */
11785 /*                                                                        */
11786 /**************************************************************************/
_nx_mdns_cache_delete_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr)11787 UINT _nx_mdns_cache_delete_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr)
11788 {
11789 
11790 UCHAR       *cache_ptr;
11791 ULONG       *head;
11792 
11793 
11794     /* Delete the resource record strings. */
11795     _nx_mdns_cache_delete_rr_string(mdns_ptr, cache_type, record_ptr);
11796 
11797     /* Zero out the record. */
11798     memset(record_ptr, 0, sizeof(NX_MDNS_RR));
11799 
11800     /* Check the type.  */
11801     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11802     {
11803 
11804         /* Decrease the count.  */
11805         mdns_ptr -> nx_mdns_local_rr_count --;
11806 
11807         /* Set the cache.  */
11808         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11809     }
11810     else
11811     {
11812 
11813         /* Decrease the count.  */
11814         mdns_ptr -> nx_mdns_peer_rr_count --;
11815 
11816         /* Set the cache.  */
11817         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11818     }
11819 
11820     if (cache_ptr == NX_NULL)
11821     {
11822         return(NX_MDNS_CACHE_ERROR);
11823     }
11824 
11825     /* Get head. */
11826     head = (ULONG*)cache_ptr;
11827     head = (ULONG*)(*head);
11828 
11829     /* Move HEAD if the last RR is deleted. */
11830     if(record_ptr == ((NX_MDNS_RR*)head - 1))
11831     {
11832         while(record_ptr -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11833         {
11834             record_ptr--;
11835             if(record_ptr < (NX_MDNS_RR*)cache_ptr)
11836                 break;
11837         }
11838         *((ULONG*)cache_ptr) = (ULONG)(record_ptr + 1);
11839     }
11840 
11841     return(NX_MDNS_SUCCESS);
11842 }
11843 
11844 
11845 /**************************************************************************/
11846 /*                                                                        */
11847 /*  FUNCTION                                               RELEASE        */
11848 /*                                                                        */
11849 /*    _nx_mdns_cache_find_resource_record                 PORTABLE C      */
11850 /*                                                           6.1          */
11851 /*  AUTHOR                                                                */
11852 /*                                                                        */
11853 /*    Yuxin Zhou, Microsoft Corporation                                   */
11854 /*                                                                        */
11855 /*  DESCRIPTION                                                           */
11856 /*                                                                        */
11857 /*    This function finds the mDNS resource record in record buffer.      */
11858 /*                                                                        */
11859 /*  INPUT                                                                 */
11860 /*                                                                        */
11861 /*    mdns_ptr                              Pointer to mDNS instance.     */
11862 /*    cache_type                            Cache type: local or peer     */
11863 /*    record_ptr                            Resource record.              */
11864 /*    match_type                            Match type.                   */
11865 /*    search_rr                             The search resource record.   */
11866 /*                                                                        */
11867 /*  OUTPUT                                                                */
11868 /*                                                                        */
11869 /*    status                                Completion status             */
11870 /*                                                                        */
11871 /*  CALLS                                                                 */
11872 /*                                                                        */
11873 /*    None                                                                */
11874 /*                                                                        */
11875 /*  CALLED BY                                                             */
11876 /*                                                                        */
11877 /*    _nx_mdns_packet_process               Process mDNS packet           */
11878 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
11879 /*                                                                        */
11880 /*  RELEASE HISTORY                                                       */
11881 /*                                                                        */
11882 /*    DATE              NAME                      DESCRIPTION             */
11883 /*                                                                        */
11884 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11885 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11886 /*                                            resulting in version 6.1    */
11887 /*                                                                        */
11888 /**************************************************************************/
_nx_mdns_cache_find_resource_record(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_ptr,UINT match_type,NX_MDNS_RR ** search_rr)11889 UINT _nx_mdns_cache_find_resource_record(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_ptr, UINT match_type, NX_MDNS_RR **search_rr)
11890 {
11891 
11892 UCHAR       *cache_ptr;
11893 ULONG       *head;
11894 NX_MDNS_RR  *p;
11895 UINT        same_rdata;
11896 
11897 
11898     /* Check the cache type.  */
11899     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
11900     {
11901         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
11902     }
11903     else
11904     {
11905         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
11906     }
11907 
11908     /* Get head. */
11909     head = (ULONG*)cache_ptr;
11910     head = (ULONG*)(*head);
11911 
11912     /* Find the same record.  */
11913     for(p = (NX_MDNS_RR*)((UCHAR*)cache_ptr + sizeof(ULONG)); (ULONG*)p < head; p++)
11914     {
11915 
11916         /* Check the interface index.  */
11917         if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
11918             continue;
11919 
11920         /* Check whether the resource record is valid. */
11921         if(p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
11922             continue;
11923 
11924         /* Check whether the same record it is. RFC6762, Section6, Page13. */
11925         /* The rules: rrname must match the question name.
11926                       rrtype must match the question qtype unless the qtype is "ANY" or the rrtype is "CNAME".
11927                       rrclass must match the question qclass unless the qclass is "ANY". */
11928         if (p -> nx_mdns_rr_name != record_ptr -> nx_mdns_rr_name)
11929             continue;
11930 
11931         /* In the probing state, we need not match the type.  */
11932         if (p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_PROBING)
11933         {
11934             if ((p -> nx_mdns_rr_type != record_ptr -> nx_mdns_rr_type) &&
11935                 (record_ptr -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_ALL) &&
11936                 (p -> nx_mdns_rr_type != NX_MDNS_RR_TYPE_CNAME))
11937                 continue;
11938         }
11939 
11940         /* Check the RR class, Ignore the top bit.  */
11941         if ((p -> nx_mdns_rr_class != (record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK)) &&
11942             ((record_ptr -> nx_mdns_rr_class & NX_MDNS_TOP_BIT_MASK) != NX_MDNS_RR_CLASS_ALL))
11943             continue;
11944 
11945         /* Check if just match the basic info.  */
11946         if (match_type == NX_MDNS_RR_MATCH_EXCEPT_RDATA)
11947         {
11948 
11949             /* Find the same record.  */
11950             *search_rr = p;
11951             return(NX_MDNS_SUCCESS);
11952         }
11953         else
11954         {
11955 
11956             /* Yes, match all information of resource record.  */
11957 
11958             /* Check the state.  */
11959             if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY)
11960                 continue;
11961 
11962             /* Reset the value.  */
11963             same_rdata = NX_FALSE;
11964 
11965             /* Compare the RDATA. */
11966             switch (p -> nx_mdns_rr_type)
11967             {
11968                 case NX_MDNS_RR_TYPE_A:
11969                 {
11970                     if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address)
11971                     {
11972                         same_rdata = NX_TRUE;
11973                     }
11974                     break;
11975                 }
11976                 case NX_MDNS_RR_TYPE_SRV:
11977                 {
11978                     if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority) &&
11979                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_weights)   &&
11980                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_port)         &&
11981                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
11982                     {
11983                         same_rdata = NX_TRUE;
11984                     }
11985                     break;
11986                 }
11987                 case NX_MDNS_RR_TYPE_AAAA:
11988                 {
11989                     if(!memcmp(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address, 16))
11990                     {
11991                         same_rdata = NX_TRUE;
11992                     }
11993                     break;
11994                 }
11995                 case NX_MDNS_RR_TYPE_PTR:
11996                 case NX_MDNS_RR_TYPE_TXT:
11997 
11998 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
11999                 case NX_MDNS_RR_TYPE_CNAME:
12000                 case NX_MDNS_RR_TYPE_NS:
12001 #endif
12002                 {
12003 
12004                     /* Check the rdata. */
12005                     if(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name)
12006                     {
12007                         same_rdata = NX_TRUE;
12008                     }
12009                     break;
12010                 }
12011 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12012                 case NX_MDNS_RR_TYPE_MX:
12013                 {
12014                     if((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_name) &&
12015                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference))
12016                     {
12017                         same_rdata = NX_TRUE;
12018                     }
12019                     break;
12020                 }
12021 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
12022 
12023 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12024                 case NX_MDNS_RR_TYPE_NSEC:
12025                 {
12026                     if ((p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain == record_ptr ->nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_next_domain) &&
12027                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_window_block) &&
12028                         (p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length) &&
12029                         (!memcmp(&(p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12030                                  &(record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap[0]),
12031                                  record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_nsec.nx_mdns_rr_nsec_bitmap_length)))
12032                     {
12033                         same_rdata = NX_TRUE;
12034                     }
12035                     break;
12036                 }
12037 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12038                 default:
12039                 {
12040 
12041                     /* This is an unsupported or unknown type. */
12042                     return(NX_MDNS_UNSUPPORTED_TYPE);
12043                 }
12044             }
12045 
12046             /* Check the same RR.  */
12047             if (same_rdata == NX_TRUE)
12048             {
12049 
12050                 /* Find the same record.  */
12051                 *search_rr = p;
12052                 return(NX_MDNS_SUCCESS);
12053             }
12054         }
12055     }
12056 
12057     return(NX_MDNS_ERROR);
12058 }
12059 
12060 
12061 /**************************************************************************/
12062 /*                                                                        */
12063 /*  FUNCTION                                               RELEASE        */
12064 /*                                                                        */
12065 /*    _nx_mdns_cache_add_string                           PORTABLE C      */
12066 /*                                                           6.1          */
12067 /*  AUTHOR                                                                */
12068 /*                                                                        */
12069 /*    Yuxin Zhou, Microsoft Corporation                                   */
12070 /*                                                                        */
12071 /*  DESCRIPTION                                                           */
12072 /*                                                                        */
12073 /*    This function adds or finds the mDNS string in the record buffer.   */
12074 /*                                                                        */
12075 /*  INPUT                                                                 */
12076 /*                                                                        */
12077 /*    mdns_ptr                              Pointer to mDNS instance      */
12078 /*    cache_type                            Cache type: local or peer     */
12079 /*    memory_ptr                            Pointer to the string         */
12080 /*    memory_size                           The size of string.           */
12081 /*    insert_rr                             Pointer to insert string.     */
12082 /*    find_string                           If set, just find the existed */
12083 /*                                            string, otherwise, insert   */
12084 /*                                            this string if it does not  */
12085 /*                                            exist.                      */
12086 /*    add_name                              If set, use name match        */
12087 /*                                            to check the string,        */
12088 /*                                            otherwise, use memcmp.      */
12089 /*                                                                        */
12090 /*  OUTPUT                                                                */
12091 /*                                                                        */
12092 /*    status                                Completion status             */
12093 /*                                                                        */
12094 /*  CALLS                                                                 */
12095 /*                                                                        */
12096 /*    none                                                                */
12097 /*                                                                        */
12098 /*  CALLED BY                                                             */
12099 /*                                                                        */
12100 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
12101 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
12102 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
12103 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
12104 /*    _nx_mdns_query                        Send query                    */
12105 /*    _nx_mdns_conflict_process             Process the conflict          */
12106 /*    _nx_mdns_packet_rr_process            Process resource record       */
12107 /*                                                                        */
12108 /*  RELEASE HISTORY                                                       */
12109 /*                                                                        */
12110 /*    DATE              NAME                      DESCRIPTION             */
12111 /*                                                                        */
12112 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12113 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
12114 /*                                            verified memcpy use cases,  */
12115 /*                                            resulting in version 6.1    */
12116 /*                                                                        */
12117 /**************************************************************************/
_nx_mdns_cache_add_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * memory_ptr,UINT memory_size,VOID ** insert_ptr,UCHAR find_string,UCHAR add_name)12118 UINT _nx_mdns_cache_add_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *memory_ptr, UINT memory_size, VOID **insert_ptr, UCHAR find_string, UCHAR add_name)
12119 {
12120 
12121 UCHAR   *cache_ptr;
12122 UINT    cache_size;
12123 ULONG   *tail;
12124 ULONG   *head;
12125 UINT    memory_len;
12126 UINT    used_cache_size;
12127 USHORT  len, cnt;
12128 USHORT  min_len = 0xFFFF;
12129 UCHAR   *p, *available, *start;
12130 
12131 
12132     /* Check the cache type.  */
12133     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12134     {
12135         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12136         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12137     }
12138     else
12139     {
12140         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12141         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12142     }
12143 
12144     /* Check cache pointer and cache size.  */
12145     if ((cache_ptr == NX_NULL) || (cache_size == 0))
12146     {
12147         return(NX_MDNS_ERROR);
12148     }
12149 
12150     /* Get head and tail. */
12151     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12152     p = (UCHAR*)tail;
12153     tail = (ULONG*)(*tail);
12154     head = (ULONG*)cache_ptr;
12155     head = (ULONG*)(*head);
12156 
12157     /* Calculate the amount of memory needed to store this string, including CNT and LEN fields. */
12158 
12159     /* Make the length 4 bytes align. */
12160     memory_len = memory_size;
12161 
12162     /* Add the length of CNT and LEN fields.  */
12163     memory_len = ((memory_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12164 
12165     available = (UCHAR*)tail;
12166     while(p > (UCHAR*)tail)
12167     {
12168 
12169         /* Get len and cnt. */
12170         len = *((USHORT*)(p - 2));
12171         cnt = *((USHORT*)(p - 4));
12172         start = p - len;
12173 
12174         if((len == memory_len) &&
12175            (((add_name == NX_TRUE) &&
12176              (!_nx_mdns_name_match(start, memory_ptr, memory_size))) ||
12177             ((add_name == NX_FALSE) &&
12178              (!memcmp(start, memory_ptr, memory_size)))))
12179         {
12180 
12181             /* The same string exists in the string table. */
12182             if(insert_ptr)
12183                 *insert_ptr = start;
12184 
12185             if(find_string == NX_FALSE)
12186             {
12187 
12188                 /* Increase the use count CNT. */
12189                 cnt++;
12190                 *((USHORT*)(p - 4)) = cnt;
12191             }
12192 
12193             return(NX_MDNS_SUCCESS);
12194         }
12195 
12196         /* This slot is not being used. The size of the slot is a smaller
12197            fit for this string. */
12198         if((cnt == 0) && (len >= memory_len) && (len < min_len))
12199         {
12200 
12201             /* This place is better to insert. */
12202             available = p;
12203             min_len = len;
12204         }
12205 
12206         /* Move to the next string. */
12207         p = start;
12208     }
12209 
12210     if(find_string == NX_TRUE)
12211         return(NX_MDNS_ERROR);
12212 
12213     /* If we reach this point, the string needs to be added to the string table. */
12214     if(available == (UCHAR*)tail)
12215     {
12216 
12217         /* Make sure the service cache still has room to add this string
12218            (without overwriting the RR area.) */
12219         if(((UCHAR*)tail - memory_len) < (UCHAR*)head )
12220         {
12221 
12222             /* This service cache does not have room for the string table to grow. */
12223             /* Invoke user-installed cache full notify function .*/
12224             if(mdns_ptr -> nx_mdns_cache_full_notify)
12225             {
12226 
12227                 /* Calculate the fragment size, RR size, string size, Head and Tail. */
12228                 if(cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12229                 {
12230                     used_cache_size = mdns_ptr -> nx_mdns_local_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_local_string_bytes + 2 * sizeof(ULONG);
12231                 }
12232                 else
12233                 {
12234                     used_cache_size = mdns_ptr -> nx_mdns_peer_rr_count * sizeof(NX_MDNS_RR) + mdns_ptr -> nx_mdns_peer_string_bytes + 2 * sizeof(ULONG);
12235                 }
12236 
12237                 /* Check the cache.  */
12238                 if ((used_cache_size + memory_len) <= cache_size)
12239                 {
12240                     (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FRAGMENTED, cache_type);
12241                 }
12242                 else
12243                 {
12244                     (mdns_ptr -> nx_mdns_cache_full_notify)(mdns_ptr, NX_MDNS_CACHE_STATE_FULL, cache_type);
12245                 }
12246             }
12247 
12248             /* The buffer is full. */
12249             return(NX_MDNS_CACHE_ERROR);
12250         }
12251 
12252         /* Update TAIL. */
12253         *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)(available - memory_len);
12254 
12255     }
12256     else if(memory_len < min_len)
12257     {
12258 
12259         /* Set the LEN for remaining space. */
12260         *((USHORT*)(available - 2 - memory_len)) = (USHORT)(min_len - memory_len);
12261     }
12262 
12263     /* Set LEN and CNT. */
12264     *((USHORT*)(available - 2)) = (USHORT)memory_len;
12265     *((USHORT*)(available - 4)) = 1;
12266 
12267     /* Clear last 4 bytes. */
12268     *((ULONG*)(available - 8)) = 0;
12269 
12270     /* Insert string to cache. */
12271     memcpy(available - memory_len, memory_ptr, memory_size); /* Use case of memcpy is verified. */
12272 
12273     /* Set end character 0. */
12274     *(available - memory_len + memory_size) = 0;
12275 
12276 
12277     /* Check the type.  */
12278     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12279     {
12280 
12281         /* Increase the count and bytes.  */
12282         mdns_ptr -> nx_mdns_local_string_count ++;
12283         mdns_ptr -> nx_mdns_local_string_bytes += memory_len;
12284     }
12285     else
12286     {
12287 
12288         /* Increase the count and bytes.  */
12289         mdns_ptr -> nx_mdns_peer_string_count ++;
12290         mdns_ptr -> nx_mdns_peer_string_bytes += memory_len;
12291     }
12292 
12293     if(insert_ptr)
12294         *insert_ptr = available - memory_len;
12295 
12296     return(NX_MDNS_SUCCESS);
12297 }
12298 
12299 
12300 /**************************************************************************/
12301 /*                                                                        */
12302 /*  FUNCTION                                               RELEASE        */
12303 /*                                                                        */
12304 /*    _nx_mdns_cache_delete_string                        PORTABLE C      */
12305 /*                                                           6.1          */
12306 /*  AUTHOR                                                                */
12307 /*                                                                        */
12308 /*    Yuxin Zhou, Microsoft Corporation                                   */
12309 /*                                                                        */
12310 /*  DESCRIPTION                                                           */
12311 /*                                                                        */
12312 /*    This function deletes the mDNS string from the record buffer.       */
12313 /*                                                                        */
12314 /*  INPUT                                                                 */
12315 /*                                                                        */
12316 /*    mdns_ptr                              Pointer to mDNS instance      */
12317 /*    cache_type                            Cache type: local or peer     */
12318 /*    string_ptr                            Pointer to the string         */
12319 /*    string_len                            The length of string          */
12320 /*                                                                        */
12321 /*  OUTPUT                                                                */
12322 /*                                                                        */
12323 /*    status                                Completion status             */
12324 /*                                                                        */
12325 /*  CALLS                                                                 */
12326 /*                                                                        */
12327 /*    None                                                                */
12328 /*                                                                        */
12329 /*  CALLED BY                                                             */
12330 /*                                                                        */
12331 /*    _nx_mdns_rr_a_aaaa_add                Add A/AAAA resource record    */
12332 /*    _nx_mdns_rr_ptr_add                   Add PTR resource record       */
12333 /*    _nx_mdns_rr_srv_add                   Add SRV resource record       */
12334 /*    _nx_mdns_rr_txt_add                   Add TXT resource record       */
12335 /*    _nx_mdns_query                        Send query                    */
12336 /*    _nx_mdns_conflict_process             Process the conflict          */
12337 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
12338 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
12339 /*    _nx_mdns_packet_rr_process            Process resource record       */
12340 /*                                                                        */
12341 /*  RELEASE HISTORY                                                       */
12342 /*                                                                        */
12343 /*    DATE              NAME                      DESCRIPTION             */
12344 /*                                                                        */
12345 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12346 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12347 /*                                            resulting in version 6.1    */
12348 /*                                                                        */
12349 /**************************************************************************/
_nx_mdns_cache_delete_string(NX_MDNS * mdns_ptr,UINT cache_type,VOID * string_ptr,UINT string_len)12350 UINT _nx_mdns_cache_delete_string(NX_MDNS *mdns_ptr, UINT cache_type, VOID *string_ptr, UINT string_len)
12351 {
12352 
12353 UCHAR   *cache_ptr;
12354 UINT    cache_size;
12355 ULONG   *tail;
12356 ULONG   *end;
12357 USHORT  cnt;
12358 
12359 
12360     /* Check the cache type.  */
12361     if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12362     {
12363         cache_ptr = mdns_ptr -> nx_mdns_local_service_cache;
12364         cache_size = mdns_ptr -> nx_mdns_local_service_cache_size;
12365     }
12366     else
12367     {
12368         cache_ptr = mdns_ptr -> nx_mdns_peer_service_cache;
12369         cache_size = mdns_ptr -> nx_mdns_peer_service_cache_size;
12370     }
12371 
12372     /* Check cache pointer and cache size.  */
12373     if ((cache_ptr == NX_NULL) || (cache_size == 0))
12374     {
12375         return(NX_MDNS_ERROR);
12376     }
12377 
12378     /* Validate input parameter. */
12379     if(string_ptr == NX_NULL)
12380         return(NX_MDNS_PARAM_ERROR);
12381 
12382     /* Check if input the string length.  */
12383     if (string_len == 0)
12384     {
12385 
12386         /* Check string length.  */
12387         if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12388         {
12389             return(NX_MDNS_DATA_SIZE_ERROR);
12390         }
12391     }
12392 
12393     /* Add the length of CNT and LEN fields.  */
12394     /* Also make the total length 4 bytes align. */
12395     string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12396 
12397     end = (ULONG*)((UCHAR*)string_ptr + string_len);
12398 
12399     /* Get tail. */
12400 
12401     /* Validate the string table. */
12402     tail = (ULONG*)cache_ptr + (cache_size >> 2) - 1;
12403     if(end > tail)
12404     {
12405 
12406         /* The end of string exceeds cache_ptr. */
12407         return(NX_MDNS_CACHE_ERROR);
12408     }
12409     tail = (ULONG*)(*tail);
12410     if((UCHAR*)string_ptr < (UCHAR*)tail)
12411     {
12412 
12413         /* The end of string exceeds cache_ptr. */
12414         return(NX_MDNS_CACHE_ERROR);
12415     }
12416 
12417     /* Decrease the usage counter value. */
12418     cnt = *((USHORT*)((UCHAR*)end - 4));
12419     cnt--;
12420     *((USHORT*)((UCHAR*)end - 4)) = cnt;
12421 
12422     /* Clear the memory if cnt is zero. */
12423     if(cnt == 0)
12424     {
12425         memset(string_ptr, 0, string_len - 2);
12426 
12427         /* Check the type.  */
12428         if (cache_type == NX_MDNS_CACHE_TYPE_LOCAL)
12429         {
12430 
12431             /* Increase the count and bytes.  */
12432             mdns_ptr -> nx_mdns_local_string_count --;
12433             mdns_ptr -> nx_mdns_local_string_bytes -= string_len;
12434         }
12435         else
12436         {
12437 
12438             /* Increase the count and bytes.  */
12439             mdns_ptr -> nx_mdns_peer_string_count --;
12440             mdns_ptr -> nx_mdns_peer_string_bytes -= string_len;
12441         }
12442 
12443         /* Update the tail pointer if the string at the tail is deleted. */
12444         if(string_ptr == tail)
12445         {
12446             tail = end;
12447 
12448             while((end < ((ULONG*)cache_ptr + (cache_size >> 2) - 1)))
12449             {
12450 
12451                 /* Set the string pt and string length.  */
12452                 string_ptr = end;
12453 
12454                 /* Check string length.  */
12455                 if (_nx_utility_string_length_check(string_ptr, &string_len, NX_MDNS_NAME_MAX))
12456                 {
12457                     return(NX_MDNS_DATA_SIZE_ERROR);
12458                 }
12459 
12460                 /* Check the string length.  */
12461                 if(string_len == 0)
12462                 {
12463 
12464                     /* This slot is cleared. */
12465                     while(*((ULONG*)string_ptr) == 0)
12466                         string_ptr = (UCHAR*)string_ptr + 4;
12467 
12468                     end = (ULONG*)string_ptr + 1;
12469                     cnt = *((USHORT*)string_ptr);
12470                 }
12471                 else
12472                 {
12473 
12474                     /* Make the length 4 bytes align and add the length of CNT and LEN fields.  */
12475                     string_len = ((string_len & 0xFFFFFFFC) + 8) & 0xFFFFFFFF;
12476 
12477                     end = (ULONG*)((UCHAR*)string_ptr + string_len);
12478                     cnt = *((USHORT*)((UCHAR*)end - 4));
12479                 }
12480 
12481                 /* Check whether this slot is never referenced. */
12482                 if(cnt == 0)
12483                     tail = end;
12484                 else
12485                     break;
12486             }
12487             *((ULONG*)cache_ptr + (cache_size >> 2) - 1) = (ULONG)tail;
12488         }
12489     }
12490 
12491     return(NX_MDNS_SUCCESS);
12492 }
12493 
12494 
12495 /**************************************************************************/
12496 /*                                                                        */
12497 /*  FUNCTION                                               RELEASE        */
12498 /*                                                                        */
12499 /*    _nx_mdns_cache_delete_rr_string                     PORTABLE C      */
12500 /*                                                           6.1          */
12501 /*  AUTHOR                                                                */
12502 /*                                                                        */
12503 /*    Yuxin Zhou, Microsoft Corporation                                   */
12504 /*                                                                        */
12505 /*  DESCRIPTION                                                           */
12506 /*                                                                        */
12507 /*    This function deletes the mDNS string from the record buffer.       */
12508 /*                                                                        */
12509 /*  INPUT                                                                 */
12510 /*                                                                        */
12511 /*    mdns_ptr                              Pointer to mDNS instance      */
12512 /*    cache_type                            Cache type: local or peer     */
12513 /*    string_ptr                            Pointer to the string         */
12514 /*                                                                        */
12515 /*  OUTPUT                                                                */
12516 /*                                                                        */
12517 /*    None                                                                */
12518 /*                                                                        */
12519 /*  CALLS                                                                 */
12520 /*                                                                        */
12521 /*    _nx_mdns_cache_delete_string          Delete the string from cache  */
12522 /*                                                                        */
12523 /*  CALLED BY                                                             */
12524 /*                                                                        */
12525 /*    _nx_mdns_cache_add_resource_record    Add the resource record       */
12526 /*    _nx_mdns_cache_delete_resource_record Delete the resource record    */
12527 /*                                                                        */
12528 /*  RELEASE HISTORY                                                       */
12529 /*                                                                        */
12530 /*    DATE              NAME                      DESCRIPTION             */
12531 /*                                                                        */
12532 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12533 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12534 /*                                            resulting in version 6.1    */
12535 /*                                                                        */
12536 /**************************************************************************/
_nx_mdns_cache_delete_rr_string(NX_MDNS * mdns_ptr,UINT cache_type,NX_MDNS_RR * record_rr)12537 VOID _nx_mdns_cache_delete_rr_string(NX_MDNS *mdns_ptr, UINT cache_type, NX_MDNS_RR *record_rr)
12538 {
12539 
12540     /* Delete the  name strings. */
12541     _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_name, 0);
12542 
12543     /* Check if need to release the rdata string.  */
12544     if (record_rr -> nx_mdns_rr_state != NX_MDNS_RR_STATE_QUERY)
12545     {
12546 
12547         if (((record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) ||
12548              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12549              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_PTR)
12550 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12551              ||
12552              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)
12553 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12554 #ifdef NX_MDNS_ENABLE_EXTENDED_RR_TYPES
12555              ||
12556              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_CNAME) ||
12557              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NS) ||
12558              (record_rr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_MX)
12559 #endif /* NX_MDNS_ENABLE_EXTENDED_RR_TYPES  */
12560             ) &&
12561             (record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target))
12562         {
12563 
12564             /* Delete the same strings. */
12565             _nx_mdns_cache_delete_string(mdns_ptr, cache_type, record_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, 0);
12566         }
12567     }
12568 }
12569 
12570 
12571 #ifndef NX_MDNS_DISABLE_SERVER
12572 /**************************************************************************/
12573 /*                                                                        */
12574 /*  FUNCTION                                               RELEASE        */
12575 /*                                                                        */
12576 /*    _nx_mdns_additional_resource_record_find            PORTABLE C      */
12577 /*                                                           6.1          */
12578 /*  AUTHOR                                                                */
12579 /*                                                                        */
12580 /*    Yuxin Zhou, Microsoft Corporation                                   */
12581 /*                                                                        */
12582 /*  DESCRIPTION                                                           */
12583 /*                                                                        */
12584 /*    This function find the mDNS additional resource record.             */
12585 /*                                                                        */
12586 /*  INPUT                                                                 */
12587 /*                                                                        */
12588 /*    mdns_ptr                              Pointer to mDNS instance      */
12589 /*    record_ptr                            Pointer to record instance    */
12590 /*                                                                        */
12591 /*  OUTPUT                                                                */
12592 /*                                                                        */
12593 /*    status                                Completion status             */
12594 /*                                                                        */
12595 /*  CALLS                                                                 */
12596 /*                                                                        */
12597 /*    None                                                                */
12598 /*                                                                        */
12599 /*  CALLED BY                                                             */
12600 /*                                                                        */
12601 /*    _nx_mdns_response_send                Send response message         */
12602 /*                                                                        */
12603 /*  RELEASE HISTORY                                                       */
12604 /*                                                                        */
12605 /*    DATE              NAME                      DESCRIPTION             */
12606 /*                                                                        */
12607 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12608 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12609 /*                                            resulting in version 6.1    */
12610 /*                                                                        */
12611 /**************************************************************************/
_nx_mdns_additional_resource_record_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12612 UINT _nx_mdns_additional_resource_record_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12613 {
12614 
12615 ULONG           *head;
12616 NX_MDNS_RR      *p;
12617 
12618     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12619     head = (ULONG*)(*head);
12620 
12621     /* Find the additional resource records according to the type.  */
12622     switch (record_ptr -> nx_mdns_rr_type )
12623     {
12624 
12625         case NX_MDNS_RR_TYPE_A:
12626         case NX_MDNS_RR_TYPE_AAAA:
12627         {
12628 
12629             /* Recommends AAAA records in the additional section when responding
12630                to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51.  */
12631             _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_interface_index);
12632 
12633             break;
12634         }
12635 
12636         case NX_MDNS_RR_TYPE_PTR:
12637         {
12638 
12639             /* Find the additional resource record.  */
12640             for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12641             {
12642 
12643                 /* Check the interface.  */
12644                 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12645                     continue;
12646 
12647                 /* The SRV record(s) named in the PTR rdata.
12648                    The TXT record(s) named in the PTR rdata.
12649                    All address records (type "A" and "AAAA") named in the SRV rdata. RFC6763, Section12.1, Page30.*/
12650 
12651                 /* The SRV records named in the PTR rdata */
12652                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV) &&
12653                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12654                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12655                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12656                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12657                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12658                 {
12659 
12660                     /* Set the flag to add this resource records into additional records.  */
12661                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12662 
12663                     /* All address records (type "A" and "AAAA") named in the SRV rdata */
12664                     _nx_mdns_additional_a_aaaa_find(mdns_ptr, p -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12665                 }
12666 
12667                 /* The TXT records named in the PTR rdata */
12668                 if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_TXT) ||
12669                      (p ->nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC)) &&
12670                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name) &&
12671                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12672                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12673                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12674                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12675                 {
12676 
12677                     /* Set the flag to add this resource records into additional records.  */
12678                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12679                 }
12680             }
12681 
12682             break;
12683         }
12684 
12685         case NX_MDNS_RR_TYPE_SRV:
12686         case NX_MDNS_RR_TYPE_TXT:
12687         {
12688 
12689 #ifdef NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES
12690             /* Find the additional resource record.  */
12691             for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12692             {
12693 
12694                 /* Check the interface.  */
12695                 if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12696                     continue;
12697 
12698                 /* The NSEC records named same as SRV/TXT name.  */
12699                 if ((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC) &&
12700                     (p -> nx_mdns_rr_name == record_ptr -> nx_mdns_rr_name) &&
12701                     ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12702                      (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12703                     (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12704                     (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12705                 {
12706 
12707                     /* Set the flag to add this resource records into additional records.  */
12708                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12709                 }
12710             }
12711 #endif /* NX_MDNS_ENABLE_SERVER_NEGATIVE_RESPONSES  */
12712 
12713             /* All address records (type "A" and "AAAA") named in the SRV rdata */
12714             if (record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_SRV)
12715                 _nx_mdns_additional_a_aaaa_find(mdns_ptr, record_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_target, record_ptr -> nx_mdns_rr_interface_index);
12716             break;
12717         }
12718     }
12719 
12720     return(NX_MDNS_SUCCESS);
12721 }
12722 
12723 
12724 /**************************************************************************/
12725 /*                                                                        */
12726 /*  FUNCTION                                               RELEASE        */
12727 /*                                                                        */
12728 /*    _nx_mdns_additional_a_aaaa_find                     PORTABLE C      */
12729 /*                                                           6.1          */
12730 /*  AUTHOR                                                                */
12731 /*                                                                        */
12732 /*    Yuxin Zhou, Microsoft Corporation                                   */
12733 /*                                                                        */
12734 /*  DESCRIPTION                                                           */
12735 /*                                                                        */
12736 /*    This function find the mDNS additional A/AAAA resource record.      */
12737 /*                                                                        */
12738 /*  INPUT                                                                 */
12739 /*                                                                        */
12740 /*    mdns_ptr                              Pointer to mDNS instance      */
12741 /*    record_ptr                            Pointer to record instance    */
12742 /*                                                                        */
12743 /*  OUTPUT                                                                */
12744 /*                                                                        */
12745 /*    status                                Completion status             */
12746 /*                                                                        */
12747 /*  CALLS                                                                 */
12748 /*                                                                        */
12749 /*    None                                                                */
12750 /*                                                                        */
12751 /*  CALLED BY                                                             */
12752 /*                                                                        */
12753 /*    _nx_mdns_additional_resource_record_find                            */
12754 /*                                          Find additional record        */
12755 /*                                                                        */
12756 /*  RELEASE HISTORY                                                       */
12757 /*                                                                        */
12758 /*    DATE              NAME                      DESCRIPTION             */
12759 /*                                                                        */
12760 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12761 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12762 /*                                            resulting in version 6.1    */
12763 /*                                                                        */
12764 /**************************************************************************/
_nx_mdns_additional_a_aaaa_find(NX_MDNS * mdns_ptr,UCHAR * name,UINT interface_index)12765 static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *name, UINT interface_index)
12766 {
12767 
12768 ULONG           *head;
12769 NX_MDNS_RR      *p;
12770 
12771     head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12772     head = (ULONG*)(*head);
12773 
12774     /* Recommends AAAA records in the additional section when responding
12775        to rrtype "A" queries, and vice versa. RFC6762, Section19, Page51.  */
12776     for (p = (NX_MDNS_RR*)((UCHAR*)mdns_ptr -> nx_mdns_local_service_cache + sizeof(ULONG)); (ULONG*)p < head; p++)
12777     {
12778 
12779         /* Check the interface index.  */
12780         if (p -> nx_mdns_rr_interface_index != interface_index)
12781             continue;
12782 
12783         /* Find the "A" records.  */
12784         if (((p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_A) ||
12785              (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_AAAA ||
12786              (p -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_NSEC))) &&
12787             (p -> nx_mdns_rr_name == name) &&
12788             ((p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_VALID) ||
12789             (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_ANNOUNCING)) &&
12790             (p -> nx_mdns_rr_send_flag == NX_MDNS_RR_SEND_FLAG_CLEAR) &&
12791             (!(p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_ANSWER)))
12792         {
12793 
12794             /* Set the flag to add this resource records into additional records.  */
12795             p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_ADDITIONAL;
12796         }
12797     }
12798 }
12799 #endif /* NX_MDNS_DISABLE_SERVER */
12800 
12801 
12802 #ifndef NX_MDNS_DISABLE_CLIENT
12803 /**************************************************************************/
12804 /*                                                                        */
12805 /*  FUNCTION                                               RELEASE        */
12806 /*                                                                        */
12807 /*    _nx_mdns_known_answer_find                          PORTABLE C      */
12808 /*                                                           6.1          */
12809 /*  AUTHOR                                                                */
12810 /*                                                                        */
12811 /*    Yuxin Zhou, Microsoft Corporation                                   */
12812 /*                                                                        */
12813 /*  DESCRIPTION                                                           */
12814 /*                                                                        */
12815 /*    This function finds the mDNS known answer.                          */
12816 /*                                                                        */
12817 /*  INPUT                                                                 */
12818 /*                                                                        */
12819 /*    mdns_ptr                              Pointer to mDNS instance      */
12820 /*    record_ptr                            Pointer to record instance    */
12821 /*                                                                        */
12822 /*  OUTPUT                                                                */
12823 /*                                                                        */
12824 /*    status                                Completion status             */
12825 /*                                                                        */
12826 /*  CALLS                                                                 */
12827 /*                                                                        */
12828 /*    None                                                                */
12829 /*                                                                        */
12830 /*  CALLED BY                                                             */
12831 /*                                                                        */
12832 /*    _nx_mdns_query_send                   Send query message            */
12833 /*    _nx_mdns_packet_process               Process mDNS packet           */
12834 /*                                                                        */
12835 /*  RELEASE HISTORY                                                       */
12836 /*                                                                        */
12837 /*    DATE              NAME                      DESCRIPTION             */
12838 /*                                                                        */
12839 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12840 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12841 /*                                            resulting in version 6.1    */
12842 /*                                                                        */
12843 /**************************************************************************/
_nx_mdns_known_answer_find(NX_MDNS * mdns_ptr,NX_MDNS_RR * record_ptr)12844 static UINT _nx_mdns_known_answer_find(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_ptr)
12845 {
12846 
12847 UINT            status = NX_MDNS_NO_KNOWN_ANSWER;
12848 ULONG           *head, *tail;
12849 NX_MDNS_RR      *p;
12850 UINT            i;
12851 UINT            name_length;
12852 #ifndef NX_MDNS_DISABLE_SERVER
12853 UINT            cache_count = 2;
12854 #else
12855 UINT            cache_count = 1;
12856 #endif
12857 
12858     /* Check string length.  */
12859     if (_nx_utility_string_length_check((CHAR *)(record_ptr -> nx_mdns_rr_name), &name_length, NX_MDNS_NAME_MAX))
12860     {
12861         return(NX_MDNS_DATA_SIZE_ERROR);
12862     }
12863 
12864     /* Loop to find the known answer in cache.  */
12865     for (i = 0; i < cache_count; i++)
12866     {
12867 
12868         /* Set the pointer. */
12869         if (i == 0)
12870         {
12871             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12872         }
12873 #ifndef NX_MDNS_DISABLE_SERVER
12874         else
12875         {
12876             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12877         }
12878 #endif /* NX_MDNS_DISABLE_SERVER  */
12879         tail = (ULONG*)(*head);
12880 
12881         /* Whether this mDNS message response to query. */
12882         for(p = (NX_MDNS_RR*)(head + 1); (ULONG*)p < tail; p++)
12883         {
12884 
12885             /* Check the state.  */
12886             if(p -> nx_mdns_rr_state != NX_MDNS_RR_STATE_VALID)
12887                 continue;
12888 
12889             /* Check the interface index.  */
12890             if (p -> nx_mdns_rr_interface_index != record_ptr -> nx_mdns_rr_interface_index)
12891                 continue;
12892 
12893             /* Check whether the Known Answer record it is. */
12894             if ((!_nx_mdns_name_match(p -> nx_mdns_rr_name, record_ptr -> nx_mdns_rr_name, name_length)) &&
12895                 (p -> nx_mdns_rr_class == record_ptr -> nx_mdns_rr_class))
12896             {
12897 
12898                 if ((record_ptr -> nx_mdns_rr_type == NX_MDNS_RR_TYPE_ALL) ||
12899                     (p -> nx_mdns_rr_type == record_ptr -> nx_mdns_rr_type))
12900                 {
12901 
12902                     /* Set the additional flag.  */
12903                     p -> nx_mdns_rr_word = p -> nx_mdns_rr_word | NX_MDNS_RR_FLAG_KNOWN_ANSWER;
12904 
12905                     /* Yes, find the known answer.  */
12906                     status = NX_MDNS_SUCCESS;
12907                 }
12908             }
12909         }
12910     }
12911 
12912     return(status);
12913 }
12914 #endif /* NX_MDNS_DISABLE_CLIENT */
12915 
12916 
12917 #ifndef NX_MDNS_DISABLE_CLIENT
12918 /**************************************************************************/
12919 /*                                                                        */
12920 /*  FUNCTION                                               RELEASE        */
12921 /*                                                                        */
12922 /*    _nx_mdns_query_check                                PORTABLE C      */
12923 /*                                                           6.1.11       */
12924 /*  AUTHOR                                                                */
12925 /*                                                                        */
12926 /*    Yuxin Zhou, Microsoft Corporation                                   */
12927 /*                                                                        */
12928 /*  DESCRIPTION                                                           */
12929 /*                                                                        */
12930 /*    This function checks whether mDNS querier already has one Unique    */
12931 /*    record in the local buffer/remote buffer or one same query in the   */
12932 /*    remote buffer.                                                      */
12933 /*                                                                        */
12934 /*  INPUT                                                                 */
12935 /*                                                                        */
12936 /*    mdns_ptr                              Pointer to mDNS instance      */
12937 /*    name                                  The resource record name      */
12938 /*    type                                  The resource record type      */
12939 /*    interface_index                       The interface index           */
12940 /*                                                                        */
12941 /*  OUTPUT                                                                */
12942 /*                                                                        */
12943 /*    status                                Completion status             */
12944 /*                                                                        */
12945 /*  CALLS                                                                 */
12946 /*                                                                        */
12947 /*    None                                                                */
12948 /*                                                                        */
12949 /*  CALLED BY                                                             */
12950 /*                                                                        */
12951 /*    _nx_mdns_query                        Send the query                */
12952 /*                                                                        */
12953 /*  RELEASE HISTORY                                                       */
12954 /*                                                                        */
12955 /*    DATE              NAME                      DESCRIPTION             */
12956 /*                                                                        */
12957 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12958 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12959 /*                                            resulting in version 6.1    */
12960 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
12961 /*                                            corrected the random value, */
12962 /*                                            resulting in version 6.1.11 */
12963 /*                                                                        */
12964 /**************************************************************************/
_nx_mdns_query_check(NX_MDNS * mdns_ptr,UCHAR * name,USHORT type,UINT one_shot,NX_MDNS_RR ** search_rr,UINT interface_index)12965 static UINT _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index)
12966 {
12967 
12968 ULONG       *head;
12969 NX_MDNS_RR  *p;
12970 UCHAR       i;
12971 UCHAR       same_query = NX_FALSE;
12972 NX_MDNS_RR  *rr = NX_NULL;
12973 UCHAR       srv_flag = NX_FALSE;
12974 UCHAR       txt_flag = NX_FALSE;
12975 UINT        name_length;
12976 
12977 
12978     /* Check string length.  */
12979     if (_nx_utility_string_length_check((CHAR *)name, &name_length, NX_MDNS_NAME_MAX))
12980     {
12981         return(NX_MDNS_DATA_SIZE_ERROR);
12982     }
12983 
12984     for(i = 0; i < 2; i++)
12985     {
12986         if(i == NX_MDNS_CACHE_TYPE_LOCAL)
12987             head = (ULONG*)mdns_ptr -> nx_mdns_local_service_cache;
12988         else
12989             head = (ULONG*)mdns_ptr -> nx_mdns_peer_service_cache;
12990 
12991         if(head)
12992         {
12993             for(p = (NX_MDNS_RR*)(head + 1); (ULONG)p < *head; p++)
12994             {
12995 
12996                 /* Check whether the resource record is valid. */
12997                 if (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_INVALID)
12998                     continue;
12999 
13000                 /* Check the interface index.  */
13001                 if (p -> nx_mdns_rr_interface_index != interface_index)
13002                     continue;
13003 
13004                 if (!_nx_mdns_name_match(p -> nx_mdns_rr_name, name, name_length))
13005                 {
13006                     if ((p -> nx_mdns_rr_type == type) && (p -> nx_mdns_rr_state == NX_MDNS_RR_STATE_QUERY))
13007                     {
13008 
13009                         /* Set the query.  */
13010                         same_query = NX_TRUE;
13011 
13012                         /* Record the RR potiner.  */
13013                         rr = p;
13014                     }
13015 
13016                     /* Check the rr type.  */
13017                     if (p -> nx_mdns_rr_type  == NX_MDNS_RR_TYPE_SRV)
13018                         srv_flag = NX_TRUE;
13019                     if (p -> nx_mdns_rr_type  == NX_MDNS_RR_TYPE_TXT)
13020                         txt_flag = NX_TRUE;
13021 
13022                     if ((p -> nx_mdns_rr_type == type) ||
13023                         ((type == NX_MDNS_RR_TYPE_ALL) && (srv_flag == NX_TRUE) && (txt_flag == NX_TRUE)))
13024                     {
13025                         if (search_rr)
13026                             *search_rr = p;
13027 
13028                         /* Check the query type.  */
13029                         if (one_shot == NX_TRUE)
13030                             return(NX_MDNS_EXIST_SHARED_RR);
13031 
13032                         if (p -> nx_mdns_rr_word & NX_MDNS_RR_FLAG_UNIQUE)
13033                             return(NX_MDNS_EXIST_UNIQUE_RR);
13034                     }
13035                 }
13036             }
13037         }
13038     }
13039 
13040     /* Check the same query.  */
13041     if (same_query == NX_TRUE)
13042     {
13043 
13044         /* A multicast DNS querier should also delay the first query of the series by
13045            a randomly chosen amount in the range 20-120ms.  */
13046         rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE));
13047         rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE;
13048 
13049         /* Set the mDNS timer.  */
13050         _nx_mdns_timer_set(mdns_ptr, rr, rr -> nx_mdns_rr_timer_count);
13051 
13052         return (NX_MDNS_EXIST_SAME_QUERY);
13053     }
13054 
13055     /* Return a successful status.  */
13056     return(NX_SUCCESS);
13057 }
13058 
13059 
13060 /**************************************************************************/
13061 /*                                                                        */
13062 /*  FUNCTION                                               RELEASE        */
13063 /*                                                                        */
13064 /*    _nx_mdns_query_cleanup                              PORTABLE C      */
13065 /*                                                           6.1          */
13066 /*  AUTHOR                                                                */
13067 /*                                                                        */
13068 /*    Yuxin Zhou, Microsoft Corporation                                   */
13069 /*                                                                        */
13070 /*  DESCRIPTION                                                           */
13071 /*                                                                        */
13072 /*    This function processes mDNS One-shot query timeout and thread      */
13073 /*    terminate actions that require the mDNS data structures to be       */
13074 /*    cleaned up.                                                         */
13075 /*                                                                        */
13076 /*  INPUT                                                                 */
13077 /*                                                                        */
13078 /*    thread_ptr                            Pointer to suspended thread's */
13079 /*                                            control block               */
13080 /*                                                                        */
13081 /*  OUTPUT                                                                */
13082 /*                                                                        */
13083 /*    None                                                                */
13084 /*                                                                        */
13085 /*  CALLS                                                                 */
13086 /*                                                                        */
13087 /*    _tx_thread_system_resume              Resume thread service         */
13088 /*                                                                        */
13089 /*  CALLED BY                                                             */
13090 /*                                                                        */
13091 /*    _tx_thread_timeout                    Thread timeout processing     */
13092 /*    _tx_thread_terminate                  Thread terminate processing   */
13093 /*                                                                        */
13094 /*  RELEASE HISTORY                                                       */
13095 /*                                                                        */
13096 /*    DATE              NAME                      DESCRIPTION             */
13097 /*                                                                        */
13098 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13099 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13100 /*                                            resulting in version 6.1    */
13101 /*                                                                        */
13102 /**************************************************************************/
_nx_mdns_query_cleanup(TX_THREAD * thread_ptr NX_CLEANUP_PARAMETER)13103 VOID  _nx_mdns_query_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER)
13104 {
13105 
13106 TX_INTERRUPT_SAVE_AREA
13107 
13108 NX_MDNS     *mdns_ptr;
13109 
13110 
13111     NX_CLEANUP_EXTENSION
13112 
13113     /* Setup pointer to UDP socket control block.  */
13114     mdns_ptr =  (NX_MDNS *) thread_ptr -> tx_thread_suspend_control_block;
13115 
13116     /* Disable interrupts to remove the suspended thread from the UDP socket.  */
13117     TX_DISABLE
13118 
13119     /* Determine if the cleanup is still required.  */
13120     if ((thread_ptr -> tx_thread_suspend_cleanup) && (mdns_ptr) &&
13121         (mdns_ptr -> nx_mdns_id == NX_MDNS_ID))
13122     {
13123 
13124         /* Yes, we still have thread suspension!  */
13125 
13126         /* Clear the suspension cleanup flag.  */
13127         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
13128 
13129         /* Remove the suspended thread from the list.  */
13130 
13131         /* See if this is the only suspended thread on the list.  */
13132         if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13133         {
13134 
13135             /* Yes, the only suspended thread.  */
13136 
13137             /* Update the head pointer.  */
13138             mdns_ptr -> nx_mdns_rr_receive_suspension_list =  NX_NULL;
13139         }
13140         else
13141         {
13142 
13143             /* At least one more thread is on the same suspension list.  */
13144 
13145             /* Update the list head pointer.  */
13146             mdns_ptr -> nx_mdns_rr_receive_suspension_list =  thread_ptr -> tx_thread_suspended_next;
13147 
13148             /* Update the links of the adjacent threads.  */
13149             (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13150             (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13151         }
13152 
13153         /* Decrement the suspension count.  */
13154         mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13155 
13156         /* Now we need to determine if this cleanup is from a terminate, timeout,
13157            or from a wait abort.  */
13158         if (thread_ptr -> tx_thread_state == TX_TCP_IP)
13159         {
13160 
13161             /* Thread still suspended on the UDP socket.  Setup return error status and
13162                resume the thread.  */
13163 
13164             /* Setup return status.  */
13165             thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13166 
13167             /* Temporarily disable preemption.  */
13168             _tx_thread_preempt_disable++;
13169 
13170             /* Restore interrupts.  */
13171             TX_RESTORE
13172 
13173             /* Resume the thread!  Check for preemption even though we are executing
13174                from the system timer thread right now which normally executes at the
13175                highest priority.  */
13176             _tx_thread_system_resume(thread_ptr);
13177 
13178             /* Finished, just return.  */
13179             return;
13180         }
13181     }
13182 
13183     /* Restore interrupts.  */
13184     TX_RESTORE
13185 }
13186 
13187 
13188 /**************************************************************************/
13189 /*                                                                        */
13190 /*  FUNCTION                                               RELEASE        */
13191 /*                                                                        */
13192 /*    _nx_mdns_query_thread_suspend                       PORTABLE C      */
13193 /*                                                           6.1          */
13194 /*  AUTHOR                                                                */
13195 /*                                                                        */
13196 /*    Yuxin Zhou, Microsoft Corporation                                   */
13197 /*                                                                        */
13198 /*  DESCRIPTION                                                           */
13199 /*                                                                        */
13200 /*    This function suspends a thread on a mDNS client query service      */
13201 /*                                                                        */
13202 /*  INPUT                                                                 */
13203 /*                                                                        */
13204 /*    suspension_list_head                  Pointer to the suspension list*/
13205 /*    mutex_ptr                             Pointer to mutex to release   */
13206 /*    suspend_cleanup                       Suspension cleanup routine    */
13207 /*    wait_option                           Optional timeout value        */
13208 /*                                                                        */
13209 /*  OUTPUT                                                                */
13210 /*                                                                        */
13211 /*    None                                                                */
13212 /*                                                                        */
13213 /*  CALLS                                                                 */
13214 /*                                                                        */
13215 /*    tx_mutex_put                          Release protection            */
13216 /*    _tx_thread_system_suspend             Suspend thread                */
13217 /*                                                                        */
13218 /*  CALLED BY                                                             */
13219 /*                                                                        */
13220 /*                                                                        */
13221 /*  RELEASE HISTORY                                                       */
13222 /*                                                                        */
13223 /*    DATE              NAME                      DESCRIPTION             */
13224 /*                                                                        */
13225 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13226 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13227 /*                                            resulting in version 6.1    */
13228 /*                                                                        */
13229 /**************************************************************************/
_nx_mdns_query_thread_suspend(TX_THREAD ** suspension_list_head,VOID (* suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),NX_MDNS * mdns_ptr,NX_MDNS_RR ** rr,ULONG wait_option)13230 VOID  _nx_mdns_query_thread_suspend(TX_THREAD **suspension_list_head, VOID (*suspend_cleanup)(TX_THREAD * NX_CLEANUP_PARAMETER),
13231                                     NX_MDNS *mdns_ptr, NX_MDNS_RR **rr, ULONG wait_option)
13232 {
13233 
13234 TX_INTERRUPT_SAVE_AREA
13235 
13236 TX_THREAD *thread_ptr;
13237 
13238 
13239     /* Lockout interrupts.  */
13240     TX_DISABLE
13241 
13242     /* Pickup thread pointer.  */
13243     thread_ptr =  _tx_thread_current_ptr;
13244 
13245     /* Setup suspension list.  */
13246     if (*suspension_list_head)
13247     {
13248 
13249         /* This list is not NULL, add current thread to the end. */
13250         thread_ptr -> tx_thread_suspended_next = *suspension_list_head;
13251         thread_ptr -> tx_thread_suspended_previous = (*suspension_list_head) -> tx_thread_suspended_previous;
13252         ((*suspension_list_head) -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr;
13253         (*suspension_list_head) -> tx_thread_suspended_previous = thread_ptr;
13254     }
13255     else
13256     {
13257 
13258         /* No other threads are suspended.  Setup the head pointer and
13259             just setup this threads pointers to itself.  */
13260         *suspension_list_head = thread_ptr;
13261         thread_ptr -> tx_thread_suspended_next = thread_ptr;
13262         thread_ptr -> tx_thread_suspended_previous = thread_ptr;
13263     }
13264 
13265     /* Setup return status.  */
13266     thread_ptr -> tx_thread_suspend_status = NX_MDNS_NO_RR;
13267 
13268     /* Setup cleanup routine pointer.  */
13269     thread_ptr -> tx_thread_suspend_cleanup = suspend_cleanup;
13270 
13271     /* Setup cleanup information, i.e. this pool control block.  */
13272     thread_ptr -> tx_thread_suspend_control_block = (void *)mdns_ptr;
13273 
13274     /* Save the return RR pointer address as well.  */
13275     thread_ptr -> tx_thread_additional_suspend_info = (void *)rr;
13276 
13277     /* Increment the suspended thread count.  */
13278     mdns_ptr -> nx_mdns_rr_receive_suspended_count++;
13279 
13280     /* Set the state to suspended.  */
13281     thread_ptr -> tx_thread_state = TX_TCP_IP;
13282 
13283     /* Set the suspending flag.  */
13284     thread_ptr -> tx_thread_suspending = TX_TRUE;
13285 
13286     /* Temporarily disable preemption.  */
13287     _tx_thread_preempt_disable++;
13288 
13289     /* Save the timeout value.  */
13290     thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
13291 
13292     /* Restore interrupts.  */
13293     TX_RESTORE
13294 
13295     /* Call actual thread suspension routine.  */
13296     _tx_thread_system_suspend(thread_ptr);
13297 }
13298 
13299 
13300 /**************************************************************************/
13301 /*                                                                        */
13302 /*  FUNCTION                                               RELEASE        */
13303 /*                                                                        */
13304 /*    _nx_mdns_query_thread_resume                        PORTABLE C      */
13305 /*                                                           6.1          */
13306 /*  AUTHOR                                                                */
13307 /*                                                                        */
13308 /*    Yuxin Zhou, Microsoft Corporation                                   */
13309 /*                                                                        */
13310 /*  DESCRIPTION                                                           */
13311 /*                                                                        */
13312 /*    This function resumes a thread suspended on a mDNS Client query     */
13313 /*    service.                                                            */
13314 /*                                                                        */
13315 /*  INPUT                                                                 */
13316 /*                                                                        */
13317 /*    thread_ptr                            Pointer to suspended thread's */
13318 /*                                            control block               */
13319 /*                                                                        */
13320 /*  OUTPUT                                                                */
13321 /*                                                                        */
13322 /*    None                                                                */
13323 /*                                                                        */
13324 /*  CALLS                                                                 */
13325 /*                                                                        */
13326 /*    _tx_thread_system_resume              Resume thread service         */
13327 /*                                                                        */
13328 /*  CALLED BY                                                             */
13329 /*                                                                        */
13330 /*    _tx_thread_timeout                    Thread timeout processing     */
13331 /*    _tx_thread_terminate                  Thread terminate processing   */
13332 /*                                                                        */
13333 /*  RELEASE HISTORY                                                       */
13334 /*                                                                        */
13335 /*    DATE              NAME                      DESCRIPTION             */
13336 /*                                                                        */
13337 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13338 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13339 /*                                            resulting in version 6.1    */
13340 /*                                                                        */
13341 /**************************************************************************/
_nx_mdns_query_thread_resume(TX_THREAD ** suspension_list_head,NX_MDNS * mdns_ptr,NX_MDNS_RR * rr)13342 VOID  _nx_mdns_query_thread_resume(TX_THREAD **suspension_list_head, NX_MDNS *mdns_ptr, NX_MDNS_RR *rr)
13343 {
13344 
13345 TX_INTERRUPT_SAVE_AREA
13346 
13347 TX_THREAD *thread_ptr;
13348 
13349 
13350     /* Disable interrupts.  */
13351     TX_DISABLE
13352 
13353     /* Pickup the thread pointer.  */
13354     thread_ptr =  *suspension_list_head;
13355 
13356     /* Determine if there still is a thread suspended.  */
13357     if (thread_ptr)
13358     {
13359 
13360         /* Remove the suspended thread from the list.  */
13361 
13362         /* See if this is the only suspended thread on the list.  */
13363         if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
13364         {
13365 
13366             /* Yes, the only suspended thread.  */
13367 
13368             /* Update the head pointer.  */
13369             *suspension_list_head = TX_NULL;
13370         }
13371         else
13372         {
13373 
13374             /* At least one more thread is on the same expiration list.  */
13375 
13376             /* Update the list head pointer.  */
13377             *suspension_list_head = thread_ptr -> tx_thread_suspended_next;
13378 
13379             /* Update the links of the adjacent threads.  */
13380             (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous = thread_ptr -> tx_thread_suspended_previous;
13381             (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next = thread_ptr -> tx_thread_suspended_next;
13382         }
13383 
13384         /* Decrement the suspension count.  */
13385         mdns_ptr -> nx_mdns_rr_receive_suspended_count--;
13386 
13387         /* Prepare for resumption of the first thread.  */
13388 
13389         /* Clear cleanup routine to avoid timeout.  */
13390         thread_ptr -> tx_thread_suspend_cleanup =  TX_NULL;
13391 
13392         /* Temporarily disable preemption.  */
13393         _tx_thread_preempt_disable++;
13394 
13395         /* Return this block pointer to the suspended thread waiting for
13396            a block.  */
13397         *((NX_MDNS_RR **) thread_ptr -> tx_thread_additional_suspend_info) =  rr;
13398 
13399         /* Restore interrupts.  */
13400         TX_RESTORE
13401 
13402         /* Put return status into the thread control block.  */
13403         thread_ptr -> tx_thread_suspend_status =  NX_MDNS_SUCCESS;
13404 
13405         /* Resume thread.  */
13406         _tx_thread_system_resume(thread_ptr);
13407     }
13408     else
13409     {
13410 
13411         /* Restore interrupts.  */
13412         TX_RESTORE
13413     }
13414 }
13415 
13416 
13417 /**************************************************************************/
13418 /*                                                                        */
13419 /*  FUNCTION                                               RELEASE        */
13420 /*                                                                        */
13421 /*    _nx_mdns_service_mask_match                         PORTABLE C      */
13422 /*                                                           6.1          */
13423 /*  AUTHOR                                                                */
13424 /*                                                                        */
13425 /*    Yuxin Zhou, Microsoft Corporation                                   */
13426 /*                                                                        */
13427 /*  DESCRIPTION                                                           */
13428 /*                                                                        */
13429 /*    This function matchs the mDNS service mask to listen the service    */
13430 /*    and notify the application, or ignore the service.                  */
13431 /*                                                                        */
13432 /*  INPUT                                                                 */
13433 /*                                                                        */
13434 /*    mdns_ptr                              Pointer to mDNS instance      */
13435 /*    service_type                          Pointer to Service type       */
13436 /*    service_mask                          The Service mask              */
13437 /*                                                                        */
13438 /*  OUTPUT                                                                */
13439 /*                                                                        */
13440 /*    status                                Completion status             */
13441 /*                                                                        */
13442 /*  CALLS                                                                 */
13443 /*                                                                        */
13444 /*    tx_mutex_get                          Get the mDNS mutex            */
13445 /*    tx_mutex_put                          Put the mDNS mutex            */
13446 /*                                                                        */
13447 /*  CALLED BY                                                             */
13448 /*                                                                        */
13449 /*    Application Code                                                    */
13450 /*                                                                        */
13451 /*  RELEASE HISTORY                                                       */
13452 /*                                                                        */
13453 /*    DATE              NAME                      DESCRIPTION             */
13454 /*                                                                        */
13455 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13456 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13457 /*                                            resulting in version 6.1    */
13458 /*                                                                        */
13459 /**************************************************************************/
_nx_mdns_service_mask_match(NX_MDNS * mdns_ptr,UCHAR * service_type,ULONG service_mask)13460 static UINT _nx_mdns_service_mask_match(NX_MDNS *mdns_ptr, UCHAR *service_type, ULONG service_mask)
13461 {
13462 
13463 UINT        i;
13464 UINT        found;
13465 ULONG       mask;
13466 UINT        type_length;
13467 
13468 
13469     NX_PARAMETER_NOT_USED(mdns_ptr);
13470 
13471     /* Initialize the parameters.  */
13472     i = 0;
13473     found = 0;
13474     mask = 0x00000001;
13475 
13476     /* Compare the service type.  */
13477     while (nx_mdns_service_types[i])
13478     {
13479 
13480         /* Check string length.  */
13481         if (_nx_utility_string_length_check((CHAR *)nx_mdns_service_types[i], &type_length, NX_MDNS_TYPE_MAX))
13482         {
13483             return(NX_MDNS_DATA_SIZE_ERROR);
13484         }
13485 
13486         /* Find the same service type.  */
13487         if (!_nx_mdns_name_match(service_type, (UCHAR *)(nx_mdns_service_types[i]), type_length))
13488         {
13489             found = 1;
13490             break;
13491         }
13492         i ++;
13493     }
13494 
13495     /* Check the result.  */
13496     if (found)
13497     {
13498 
13499         /* Check service mask.  */
13500         if (service_mask & (mask << i))
13501         {
13502               return(NX_MDNS_SUCCESS);
13503         }
13504     }
13505 
13506     /* Return status.  */
13507     return(NX_MDNS_SERVICE_TYPE_MISMATCH);
13508 }
13509 #endif /* NX_MDNS_DISABLE_CLIENT */
13510 
13511 
13512 /**************************************************************************/
13513 /*                                                                        */
13514 /*  FUNCTION                                               RELEASE        */
13515 /*                                                                        */
13516 /*    _nx_mdns_name_match                                 PORTABLE C      */
13517 /*                                                           6.1          */
13518 /*  AUTHOR                                                                */
13519 /*                                                                        */
13520 /*    Yuxin Zhou, Microsoft Corporation                                   */
13521 /*                                                                        */
13522 /*  DESCRIPTION                                                           */
13523 /*                                                                        */
13524 /*    This function name string match, the lowercase letters "a" to "z"   */
13525 /*    match their uppercase equivalents "A" to "Z".                       */
13526 /*                                                                        */
13527 /*  INPUT                                                                 */
13528 /*                                                                        */
13529 /*    ptr                                   Pointer to destination        */
13530 /*    name                                  Source name string            */
13531 /*                                                                        */
13532 /*  OUTPUT                                                                */
13533 /*                                                                        */
13534 /*    status                                Completion status             */
13535 /*                                                                        */
13536 /*  CALLS                                                                 */
13537 /*                                                                        */
13538 /*    None                                                                */
13539 /*                                                                        */
13540 /*  CALLED BY                                                             */
13541 /*                                                                        */
13542 /*    _nx_mdns_packet_rr_add                Add the RR into packet        */
13543 /*                                                                        */
13544 /*  RELEASE HISTORY                                                       */
13545 /*                                                                        */
13546 /*    DATE              NAME                      DESCRIPTION             */
13547 /*                                                                        */
13548 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13549 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13550 /*                                            resulting in version 6.1    */
13551 /*                                                                        */
13552 /**************************************************************************/
_nx_mdns_name_match(UCHAR * src,UCHAR * dst,UINT length)13553 static UINT  _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length)
13554 {
13555 
13556 UINT    index = 0;
13557 
13558 
13559     /* Check the name.  */
13560     while (*dst != '\0')
13561     {
13562         if((*src) != (*dst))
13563         {
13564             if((((*src) | 0x20) >= 'a') && (((*src) | 0x20) <= 'z'))
13565             {
13566                 /* Match the characters, case in-sensitive. */
13567                 if(((*src) | 0x20) != ((*dst) | 0x20))
13568                     return(NX_MDNS_NAME_MISMATCH);
13569             }
13570             else
13571             {
13572                 return(NX_MDNS_NAME_MISMATCH);
13573             }
13574         }
13575         src ++;
13576         dst ++;
13577         index ++;
13578     }
13579 
13580     /* Check the scan length.  */
13581     if (index != length)
13582     {
13583         return (NX_MDNS_NAME_MISMATCH);
13584     }
13585 
13586     /* Return success.  */
13587     return(NX_MDNS_SUCCESS);
13588 }
13589 
13590 
13591 /**************************************************************************/
13592 /*                                                                        */
13593 /*  FUNCTION                                               RELEASE        */
13594 /*                                                                        */
13595 /*    _nx_mdns_txt_string_encode                          PORTABLE C      */
13596 /*                                                           6.1          */
13597 /*  AUTHOR                                                                */
13598 /*                                                                        */
13599 /*    Yuxin Zhou, Microsoft Corporation                                   */
13600 /*                                                                        */
13601 /*  DESCRIPTION                                                           */
13602 /*                                                                        */
13603 /*    This function encodes the txt string and adds the txt string into   */
13604 /*    packet.the TXT records are formatted in a "key=value" notation      */
13605 /*    with ";" acting as separator when more then one key is available.   */
13606 /*                                                                        */
13607 /*  INPUT                                                                 */
13608 /*                                                                        */
13609 /*    ptr                                   Pointer to destination        */
13610 /*    name                                  Source name string            */
13611 /*                                                                        */
13612 /*  OUTPUT                                                                */
13613 /*                                                                        */
13614 /*    status                                Completion status             */
13615 /*                                                                        */
13616 /*  CALLS                                                                 */
13617 /*                                                                        */
13618 /*    None                                                                */
13619 /*                                                                        */
13620 /*  CALLED BY                                                             */
13621 /*                                                                        */
13622 /*    _nx_mdns_packet_rr_add                Add the RR into packet        */
13623 /*                                                                        */
13624 /*  RELEASE HISTORY                                                       */
13625 /*                                                                        */
13626 /*    DATE              NAME                      DESCRIPTION             */
13627 /*                                                                        */
13628 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13629 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13630 /*                                            resulting in version 6.1    */
13631 /*                                                                        */
13632 /**************************************************************************/
_nx_mdns_txt_string_encode(UCHAR * ptr,UCHAR * txt)13633 static UINT  _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *txt)
13634 {
13635 
13636 UCHAR   *length;
13637 UINT    count =  1;
13638 
13639 
13640     /* Point to the first character position in the buffer.  This will point
13641        to the length of the following name.  */
13642     length =  ptr++;
13643 
13644     /* Default the length to zero.  */
13645     *length =  0;
13646 
13647     /* Move through string, copying bytes and updating length.
13648        Whenever a "." is found, start a new string by updating the
13649        pointer to the length and setting the length to zero.  */
13650     while (*txt)
13651     {
13652 
13653         /* Is a dot been found?  */
13654         if (*txt == ';')
13655         {
13656 
13657 
13658             /* Yes, setup a new length pointer. */
13659             length =  ptr++;
13660 
13661             /* Default the length to zero. */
13662             *length =  0;
13663             txt++;
13664         }
13665         else
13666         {
13667 
13668             /* Copy a character to the destination.  */
13669             *ptr++ =  *txt++;
13670 
13671             /* Adjust the length of the current segment.  */
13672             (*length)++;
13673         }
13674 
13675         /* Increment the total count here.  */
13676         count++;
13677     }
13678 
13679     /* Return the count.  */
13680     return(count);
13681 }
13682 
13683 
13684 /**************************************************************************/
13685 /*                                                                        */
13686 /*  FUNCTION                                               RELEASE        */
13687 /*                                                                        */
13688 /*    _nx_mdns_txt_string_decode                          PORTABLE C      */
13689 /*                                                           6.1.3        */
13690 /*  AUTHOR                                                                */
13691 /*                                                                        */
13692 /*    Yuxin Zhou, Microsoft Corporation                                   */
13693 /*                                                                        */
13694 /*  DESCRIPTION                                                           */
13695 /*                                                                        */
13696 /*    This function decode the txt string and adds the txt string into    */
13697 /*    buffer.the TXT records are formatted in a "key=value"  notation     */
13698 /*    with ";" acting as separator when more then one key is available.   */
13699 /*                                                                        */
13700 /*  INPUT                                                                 */
13701 /*                                                                        */
13702 /*    data                                  Pointer to buffer to decode   */
13703 /*    data_length                           The length of data            */
13704 /*    buffer                                Pointer to decoded data       */
13705 /*    size                                  Size of data buffer to decode */
13706 /*                                                                        */
13707 /*  OUTPUT                                                                */
13708 /*                                                                        */
13709 /*    status                                Completion status             */
13710 /*                                                                        */
13711 /*  CALLS                                                                 */
13712 /*                                                                        */
13713 /*    None                                                                */
13714 /*                                                                        */
13715 /*  CALLED BY                                                             */
13716 /*                                                                        */
13717 /*    _nx_mdns_packet_process               Process mDNS packet           */
13718 /*    _nx_mdns_packet_rr_process            Process resource record       */
13719 /*                                                                        */
13720 /*  RELEASE HISTORY                                                       */
13721 /*                                                                        */
13722 /*    DATE              NAME                      DESCRIPTION             */
13723 /*                                                                        */
13724 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13725 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13726 /*                                            resulting in version 6.1    */
13727 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
13728 /*                                            buffer length verification, */
13729 /*                                            resulting in version 6.1.3  */
13730 /*                                                                        */
13731 /**************************************************************************/
_nx_mdns_txt_string_decode(UCHAR * data,UINT data_length,UCHAR * buffer,UINT size)13732 static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size)
13733 {
13734 
13735 
13736     /* Check the buffer size.  */
13737     if (data_length >= size)
13738     {
13739         return (NX_MDNS_CACHE_ERROR);
13740     }
13741 
13742     /* decode  the data.   */
13743     while (data_length)
13744     {
13745 
13746     UINT  labelSize =  *data++;
13747 
13748         /* Is this a compression pointer or a count.  */
13749         if (labelSize <= NX_MDNS_LABEL_MAX)
13750         {
13751 
13752             /* Simple count, check for space and copy the label.  */
13753             while ((labelSize > 0) && (data_length > 1))
13754             {
13755 
13756                 *buffer++ =  *data++;
13757                 labelSize--;
13758                 data_length--;
13759             }
13760 
13761             /* Now add the ';' */
13762             *buffer++ =  ';';
13763             data_length--;
13764         }
13765         else
13766         {
13767             return(NX_MDNS_EXCEED_MAX_LABEL);
13768         }
13769     }
13770 
13771     /* Done copying the data, set the last . to a trailing null */
13772     if (*(buffer - 1) == ';')
13773     {
13774 
13775         buffer--;
13776     }
13777 
13778     /* Null terminate name.  */
13779     *buffer =  '\0';
13780 
13781     /* Return name size.  */
13782     return(NX_MDNS_SUCCESS);
13783 }
13784 
13785 
13786 /**************************************************************************/
13787 /*                                                                        */
13788 /*  FUNCTION                                               RELEASE        */
13789 /*                                                                        */
13790 /*    _nx_mdns_name_size_calculate                        PORTABLE C      */
13791 /*                                                           6.1.4        */
13792 /*  AUTHOR                                                                */
13793 /*                                                                        */
13794 /*    Yuxin Zhou, Microsoft Corporation                                   */
13795 /*                                                                        */
13796 /*  DESCRIPTION                                                           */
13797 /*                                                                        */
13798 /*    This function calculates the size of the name.                      */
13799 /*                                                                        */
13800 /*  INPUT                                                                 */
13801 /*                                                                        */
13802 /*    name                                  Pointer to the name           */
13803 /*    packet_ptr                            Pointer to received packet    */
13804 /*                                                                        */
13805 /*  OUTPUT                                                                */
13806 /*                                                                        */
13807 /*    UINT                                  Size of name                  */
13808 /*                                                                        */
13809 /*  CALLS                                                                 */
13810 /*                                                                        */
13811 /*    None                                                                */
13812 /*                                                                        */
13813 /*  CALLED BY                                                             */
13814 /*                                                                        */
13815 /*                                                                        */
13816 /*  RELEASE HISTORY                                                       */
13817 /*                                                                        */
13818 /*    DATE              NAME                      DESCRIPTION             */
13819 /*                                                                        */
13820 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13821 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13822 /*                                            resulting in version 6.1    */
13823 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
13824 /*                                            packet length verification, */
13825 /*                                            resulting in version 6.1.4  */
13826 /*                                                                        */
13827 /**************************************************************************/
_nx_mdns_name_size_calculate(UCHAR * name,NX_PACKET * packet_ptr)13828 static UINT  _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr)
13829 {
13830 
13831 UINT size =  0;
13832 
13833 
13834     /* As long as we haven't found a zero length terminating label */
13835     while (*name != '\0')
13836     {
13837 
13838         UINT  labelSize =  *name++;
13839 
13840         /* Is this a compression pointer or a count.  */
13841         if (labelSize <= NX_MDNS_LABEL_MAX)
13842         {
13843 
13844             if (name + labelSize >= packet_ptr -> nx_packet_append_ptr)
13845             {
13846 
13847                 /* If name buffer is OOB, just fail. */
13848                 return(0);
13849             }
13850 
13851             /* Simple count, adjust size and skip the label.  */
13852             size +=  labelSize + 1;
13853             name +=  labelSize;
13854         }
13855         else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
13856         {
13857 
13858             /* This is a pointer size is 2 bytes and this is the end of this name */
13859             return(size + 2);
13860         }
13861         else
13862         {
13863 
13864             /* Not defined, just fail */
13865             return(0);
13866         }
13867     }
13868 
13869     /* Adjust size for the final NULL.  */
13870     return(size + 1);
13871 }
13872 
13873 
13874 /**************************************************************************/
13875 /*                                                                        */
13876 /*  FUNCTION                                               RELEASE        */
13877 /*                                                                        */
13878 /*    _nx_mdns_name_string_encode                         PORTABLE C      */
13879 /*                                                           6.1          */
13880 /*  AUTHOR                                                                */
13881 /*                                                                        */
13882 /*    Yuxin Zhou, Microsoft Corporation                                   */
13883 /*                                                                        */
13884 /*  DESCRIPTION                                                           */
13885 /*                                                                        */
13886 /*    This function converts a string containing the name as a list of    */
13887 /*    labels separated by dots to the encoded list of labels specified    */
13888 /*    in RFC1035 for DNS servers. This conversion doesn't handle          */
13889 /*    compression and doesn't check on the lengths of the labels or the   */
13890 /*    entire name.                                                        */
13891 /*                                                                        */
13892 /*  INPUT                                                                 */
13893 /*                                                                        */
13894 /*    ptr                                   Pointer to destination        */
13895 /*    name                                  Source name string            */
13896 /*                                                                        */
13897 /*  OUTPUT                                                                */
13898 /*                                                                        */
13899 /*    count                                 Count of characters encoded   */
13900 /*                                                                        */
13901 /*  CALLS                                                                 */
13902 /*                                                                        */
13903 /*    None                                                                */
13904 /*                                                                        */
13905 /*  CALLED BY                                                             */
13906 /*                                                                        */
13907 /*                                                                        */
13908 /*  RELEASE HISTORY                                                       */
13909 /*                                                                        */
13910 /*    DATE              NAME                      DESCRIPTION             */
13911 /*                                                                        */
13912 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13913 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13914 /*                                            resulting in version 6.1    */
13915 /*                                                                        */
13916 /**************************************************************************/
_nx_mdns_name_string_encode(UCHAR * ptr,UCHAR * name)13917 static UINT  _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name)
13918 {
13919 
13920 UCHAR   *length;
13921 UINT    count =  1;
13922 
13923 
13924     /* Point to the first character position in the buffer.  This will point
13925        to the length of the following name.  */
13926     length =  ptr++;
13927 
13928     /* Default the length to zero.  */
13929     *length =  0;
13930 
13931     /* Move through string, copying bytes and updating length.
13932        Whenever a "." is found, start a new string by updating the
13933        pointer to the length and setting the length to zero.  */
13934     while (*name)
13935     {
13936 
13937         /* Is a dot been found?  */
13938         if (*name == '.')
13939         {
13940 
13941             /* Yes, setup a new length pointer. */
13942             length =  ptr++;
13943 
13944             /* Default the length to zero. */
13945             *length =  0;
13946             name++;
13947         }
13948         else
13949         {
13950 
13951             /* Copy a character to the destination.  */
13952             *ptr++ =  *name++;
13953 
13954             /* Adjust the length of the current segment.  */
13955             (*length)++;
13956         }
13957 
13958         /* Increment the total count here.  */
13959         count++;
13960     }
13961 
13962     /* Add the final zero length, like a NULL terminator.  */
13963     *ptr =  0;
13964 
13965     /* Increment the total count.  */
13966     count++;
13967 
13968     /* Return the count.  */
13969     return(count);
13970 }
13971 
13972 
13973 /**************************************************************************/
13974 /*                                                                        */
13975 /*  FUNCTION                                               RELEASE        */
13976 /*                                                                        */
13977 /*    _nx_mdns_name_string_decode                       PORTABLE C        */
13978 /*                                                           6.1.4        */
13979 /*  AUTHOR                                                                */
13980 /*                                                                        */
13981 /*    Yuxin Zhou, Microsoft Corporation                                   */
13982 /*                                                                        */
13983 /*  DESCRIPTION                                                           */
13984 /*                                                                        */
13985 /*    This function converts from the encoded list of labels as specified */
13986 /*    in RFC 1035 to a string containing the name as a list of labels     */
13987 /*    separated by dots.                                                  */
13988 /*                                                                        */
13989 /*  INPUT                                                                 */
13990 /*                                                                        */
13991 /*    data                                  Pointer to buffer to decode   */
13992 /*    start                                 Location of start of data     */
13993 /*    data_length                           Length of data buffer         */
13994 /*    buffer                                Pointer to decoded data       */
13995 /*    size                                  Size of data buffer to decode */
13996 /*                                                                        */
13997 /*  OUTPUT                                                                */
13998 /*                                                                        */
13999 /*    Size of decoded data                                                */
14000 /*                                                                        */
14001 /*  CALLS                                                                 */
14002 /*                                                                        */
14003 /*    None                                                                */
14004 /*                                                                        */
14005 /*  CALLED BY                                                             */
14006 /*                                                                        */
14007 /*                                                                        */
14008 /*  RELEASE HISTORY                                                       */
14009 /*                                                                        */
14010 /*    DATE              NAME                      DESCRIPTION             */
14011 /*                                                                        */
14012 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14013 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14014 /*                                            resulting in version 6.1    */
14015 /*  12-31-2020     Yuxin Zhou               Modified comment(s), improved */
14016 /*                                            buffer length verification, */
14017 /*                                            prevented infinite loop in  */
14018 /*                                            name compression,           */
14019 /*                                            resulting in version 6.1.3  */
14020 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
14021 /*                                            packet length verification, */
14022 /*                                            resulting in version 6.1.4  */
14023 /*                                                                        */
14024 /**************************************************************************/
_nx_mdns_name_string_decode(UCHAR * data,UINT start,UINT data_length,UCHAR * buffer,UINT size)14025 static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size)
14026 {
14027 
14028 UCHAR   *character =  data + start;
14029 UINT    length = 0;
14030 UINT    offset;
14031 UINT    pointer_count = 0;
14032 UINT    labelSize;
14033 
14034 
14035     /* As long as there is space in the buffer and we haven't
14036        found a zero terminating label */
14037     while (1)
14038     {
14039 
14040         if (character >= data + data_length)
14041         {
14042             return(0);
14043         }
14044 
14045         if ((size <= length) || (*character == '\0'))
14046         {
14047             break;
14048         }
14049 
14050         labelSize =  *character++;
14051 
14052         /* Is this a compression pointer or a count.  */
14053         if (labelSize <= NX_MDNS_LABEL_MAX)
14054         {
14055 
14056             /* Simple count, check for space and copy the label.  */
14057             while ((size > length) && (labelSize > 0))
14058             {
14059                 if (character >= data + data_length)
14060                 {
14061                     return(0);
14062                 }
14063 
14064                 *buffer++ =  *character++;
14065                 length++;
14066                 labelSize--;
14067             }
14068 
14069             /* Now add the '.' */
14070             *buffer++ =  '.';
14071             length++;
14072         }
14073         else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE)
14074         {
14075 
14076             if (character >= data + data_length)
14077             {
14078                 return(0);
14079             }
14080 
14081             /* This is a pointer, just adjust the source.  */
14082             offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character;
14083 
14084             /* Make sure offset is in the buffer.  */
14085             if (offset >= data_length)
14086             {
14087                 return(0);
14088             }
14089 
14090             /* Pointer must not point back to itself. */
14091             if ((data + offset == character) || (data + offset == character - 1))
14092             {
14093                 return(0);
14094             }
14095 
14096             /* Prevent infinite loop with compression pointers. */
14097             pointer_count++;
14098             if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS)
14099             {
14100                 return(0);
14101             }
14102 
14103             character =  data + offset;
14104         }
14105         else
14106         {
14107 
14108             /* Not defined, just fail */
14109             return(0);
14110         }
14111     }
14112 
14113     /* Done copying the data, set the last . to a trailing null */
14114     if ((length > 0) && (*(buffer - 1) == '.'))
14115     {
14116 
14117         buffer--;
14118         length --;
14119     }
14120 
14121     /* Null terminate name.  */
14122     *buffer =  '\0';
14123 
14124     /* Return name size.  */
14125     return(length);
14126 }
14127 
14128 
14129 /**************************************************************************/
14130 /*                                                                        */
14131 /*  FUNCTION                                               RELEASE        */
14132 /*                                                                        */
14133 /*    _nx_mdns_rr_size_get                                PORTABLE C      */
14134 /*                                                           6.1.4        */
14135 /*  AUTHOR                                                                */
14136 /*                                                                        */
14137 /*    Yuxin Zhou, Microsoft Corporation                                   */
14138 /*                                                                        */
14139 /*  DESCRIPTION                                                           */
14140 /*                                                                        */
14141 /*    This function gets the size of resource record.                     */
14142 /*                                                                        */
14143 /*  INPUT                                                                 */
14144 /*                                                                        */
14145 /*    resource                              Pointer to the resource       */
14146 /*    packet_ptr                            Pointer to received packet    */
14147 /*                                                                        */
14148 /*  OUTPUT                                                                */
14149 /*                                                                        */
14150 /*    size of data                                                        */
14151 /*                                                                        */
14152 /*  CALLS                                                                 */
14153 /*                                                                        */
14154 /*                                                                        */
14155 /*  CALLED BY                                                             */
14156 /*                                                                        */
14157 /*                                                                        */
14158 /*  RELEASE HISTORY                                                       */
14159 /*                                                                        */
14160 /*    DATE              NAME                      DESCRIPTION             */
14161 /*                                                                        */
14162 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14163 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14164 /*                                            resulting in version 6.1    */
14165 /*  02-02-2021     Yuxin Zhou               Modified comment(s), improved */
14166 /*                                            packet length verification, */
14167 /*                                            resulting in version 6.1.4  */
14168 /*                                                                        */
14169 /**************************************************************************/
_nx_mdns_rr_size_get(UCHAR * resource,NX_PACKET * packet_ptr)14170 static UINT  _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr)
14171 {
14172 
14173 UINT    name_size;
14174 UINT    data_size;
14175 
14176     /* Resource size is
14177         name size + data size + 2 bytes for type, 2 for class, 4 for time to live and 2 for data length
14178         i.e. name size + data size + 10 bytes overhead.
14179     */
14180     name_size = _nx_mdns_name_size_calculate(resource, packet_ptr);
14181 
14182     if (resource + name_size + 8 + 2 > packet_ptr -> nx_packet_append_ptr)
14183     {
14184         return(0);
14185     }
14186     data_size = NX_MDNS_GET_USHORT_DATA(resource + name_size + 8);
14187 
14188     /* Return resource size.  */
14189     return(name_size + data_size + 10);
14190 }
14191 
14192 
14193 /**************************************************************************/
14194 /*                                                                        */
14195 /*  FUNCTION                                               RELEASE        */
14196 /*                                                                        */
14197 /*    _nx_mdns_short_to_network_convert                   PORTABLE C      */
14198 /*                                                           6.1          */
14199 /*  AUTHOR                                                                */
14200 /*                                                                        */
14201 /*    Yuxin Zhou, Microsoft Corporation                                   */
14202 /*                                                                        */
14203 /*  DESCRIPTION                                                           */
14204 /*                                                                        */
14205 /*    This function converts an unsigned short to network byte order,     */
14206 /*    which is big endian.                                                */
14207 /*                                                                        */
14208 /*  INPUT                                                                 */
14209 /*                                                                        */
14210 /*    ptr                                   Pointer to the destination    */
14211 /*    value                                 Source value                  */
14212 /*                                                                        */
14213 /*  OUTPUT                                                                */
14214 /*                                                                        */
14215 /*    None                                                                */
14216 /*                                                                        */
14217 /*  CALLS                                                                 */
14218 /*                                                                        */
14219 /*    None                                                                */
14220 /*                                                                        */
14221 /*  CALLED BY                                                             */
14222 /*                                                                        */
14223 /*    DNS component                                                       */
14224 /*                                                                        */
14225 /*  RELEASE HISTORY                                                       */
14226 /*                                                                        */
14227 /*    DATE              NAME                      DESCRIPTION             */
14228 /*                                                                        */
14229 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14230 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14231 /*                                            resulting in version 6.1    */
14232 /*                                                                        */
14233 /**************************************************************************/
_nx_mdns_short_to_network_convert(UCHAR * ptr,USHORT value)14234 static void  _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value)
14235 {
14236 
14237     *ptr++ =  (UCHAR)(value >> 8);
14238     *ptr   =  (UCHAR)value;
14239 }
14240 
14241 
14242 /**************************************************************************/
14243 /*                                                                        */
14244 /*  FUNCTION                                               RELEASE        */
14245 /*                                                                        */
14246 /*    _nx_mdns_long_to_network_convert                    PORTABLE C      */
14247 /*                                                           6.1          */
14248 /*  AUTHOR                                                                */
14249 /*                                                                        */
14250 /*    Yuxin Zhou, Microsoft Corporation                                   */
14251 /*                                                                        */
14252 /*  DESCRIPTION                                                           */
14253 /*                                                                        */
14254 /*    This function converts an unsigned long to network format, which    */
14255 /*    big endian.                                                         */
14256 /*                                                                        */
14257 /*  INPUT                                                                 */
14258 /*                                                                        */
14259 /*    ptr                                   Pointer to the destination    */
14260 /*    value                                 Source value                  */
14261 /*                                                                        */
14262 /*  OUTPUT                                                                */
14263 /*                                                                        */
14264 /*    None                                                                */
14265 /*                                                                        */
14266 /*  CALLS                                                                 */
14267 /*                                                                        */
14268 /*    None                                                                */
14269 /*                                                                        */
14270 /*  CALLED BY                                                             */
14271 /*                                                                        */
14272 /*    DNS component                                                       */
14273 /*                                                                        */
14274 /*  RELEASE HISTORY                                                       */
14275 /*                                                                        */
14276 /*    DATE              NAME                      DESCRIPTION             */
14277 /*                                                                        */
14278 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14279 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14280 /*                                            resulting in version 6.1    */
14281 /*                                                                        */
14282 /**************************************************************************/
_nx_mdns_long_to_network_convert(UCHAR * ptr,ULONG value)14283 static void _nx_mdns_long_to_network_convert(UCHAR *ptr, ULONG value)
14284 {
14285 
14286     *ptr++ =  (UCHAR)(value >> 24);
14287     *ptr++ =  (UCHAR)(value >> 16);
14288     *ptr++ =  (UCHAR)(value >> 8);
14289     *ptr   =  (UCHAR)value;
14290 }
14291