1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** NetX SNTP Client Component                                            */
15 /**                                                                       */
16 /**   Simple Network Time Protocol (SNTP)                                 */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 /**************************************************************************/
22 /*                                                                        */
23 /*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
24 /*                                                                        */
25 /*    nxd_sntp_client.c                                   PORTABLE C      */
26 /*                                                           6.1          */
27 /*  AUTHOR                                                                */
28 /*                                                                        */
29 /*    Yuxin Zhou, Microsoft Corporation                                   */
30 /*                                                                        */
31 /*  DESCRIPTION                                                           */
32 /*                                                                        */
33 /*    This file defines the NetX Simple Network Time Protocol (SNTP)      */
34 /*    Client component, including all data types and external references. */
35 /*    It is assumed that tx_api.h, tx_port.h, nx_api.h, and nx_port.h,    */
36 /*    have already been included.                                         */
37 /*                                                                        */
38 /*  RELEASE HISTORY                                                       */
39 /*                                                                        */
40 /*    DATE              NAME                      DESCRIPTION             */
41 /*                                                                        */
42 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
43 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
44 /*                                            resulting in version 6.1    */
45 /*                                                                        */
46 /**************************************************************************/
47 
48 #define NX_SNTP_SOURCE_CODE
49 
50 /* Force error checking to be disabled in this module */
51 
52 #ifndef NX_DISABLE_ERROR_CHECKING
53 #define NX_DISABLE_ERROR_CHECKING
54 #endif
55 
56 #include "nx_api.h"
57 #include "nx_udp.h"
58 
59 #include "nx_ipv4.h"
60 #include "nxd_sntp_client.h"
61 #ifdef FEATURE_NX_IPV6
62 #include "nx_ipv6.h"
63 #endif
64 
65 
66 #include <ctype.h>
67 
68 extern  TX_THREAD           *_tx_thread_current_ptr;
69 extern  TX_THREAD           _tx_timer_thread;
70 extern  volatile ULONG      _tx_thread_system_state;
71 
72 TX_EVENT_FLAGS_GROUP        nx_sntp_client_events;
73 
74 /* Define internal time variables for offsets between
75    receipt of SNTP packet and application to
76    SNTP Client local time. */
77 static ULONG send_timerticks = 0;
78 static ULONG receive_timerticks = 0;
79 static ULONG process_timerticks = 0;
80 
81 
82 /**************************************************************************/
83 /*                                                                        */
84 /*  FUNCTION                                               RELEASE        */
85 /*                                                                        */
86 /*    _nxe_sntp_client_create                             PORTABLE C      */
87 /*                                                           6.2.1        */
88 /*  AUTHOR                                                                */
89 /*                                                                        */
90 /*    Yuxin Zhou, Microsoft Corporation                                   */
91 /*                                                                        */
92 /*  DESCRIPTION                                                           */
93 /*                                                                        */
94 /*    This function performs error checking on the SNTP client create     */
95 /*    service.                                                            */
96 /*                                                                        */
97 /*  INPUT                                                                 */
98 /*                                                                        */
99 /*    client_ptr                        Pointer to client struct          */
100 /*    ip_ptr                            Pointer to client IP instance     */
101 /*    iface_index                       Index of SNTP network interface   */
102 /*    packet_pool_ptr                   Pointer to client packet pool     */
103 /*    socket_ptr                        Pointer to client UDP socket      */
104 /*    leap_second_handler               Pointer to leap second handler    */
105 /*    random_number_generator           Random number generator callback  */
106 /*                                                                        */
107 /*  OUTPUT                                                                */
108 /*                                                                        */
109 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
110 /*    NX_INVALID_INTERFACE               Invalid network interface        */
111 /*    status                             Actual completion status         */
112 /*                                                                        */
113 /*  CALLS                                                                 */
114 /*                                                                        */
115 /*    _nx_sntp_client_create            Actual SNTP client create service */
116 /*                                                                        */
117 /*  CALLED BY                                                             */
118 /*                                                                        */
119 /*    Application Code                                                    */
120 /*                                                                        */
121 /*  RELEASE HISTORY                                                       */
122 /*                                                                        */
123 /*    DATE              NAME                      DESCRIPTION             */
124 /*                                                                        */
125 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
126 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
127 /*                                            resulting in version 6.1    */
128 /*  03-08-2023     Wenhui Xie               Modified comment(s),          */
129 /*                                            checked the client ID,      */
130 /*                                            resulting in version 6.2.1  */
131 /*                                                                        */
132 /**************************************************************************/
_nxe_sntp_client_create(NX_SNTP_CLIENT * client_ptr,NX_IP * ip_ptr,UINT iface_index,NX_PACKET_POOL * packet_pool_ptr,UINT (* leap_second_handler)(NX_SNTP_CLIENT * client_ptr,UINT indicator),UINT (* kiss_of_death_handler)(NX_SNTP_CLIENT * client_ptr,UINT code),VOID (random_number_generator)(struct NX_SNTP_CLIENT_STRUCT * client_ptr,ULONG * rand))133 UINT  _nxe_sntp_client_create(NX_SNTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT iface_index, NX_PACKET_POOL *packet_pool_ptr,
134                                 UINT (*leap_second_handler)(NX_SNTP_CLIENT *client_ptr, UINT indicator),
135                                 UINT (*kiss_of_death_handler)(NX_SNTP_CLIENT *client_ptr, UINT code),
136                                 VOID (random_number_generator)(struct NX_SNTP_CLIENT_STRUCT *client_ptr, ULONG *rand))
137 {
138 
139 UINT status;
140 
141 
142     /* Check for invalid input pointers.  */
143     if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) || (client_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL))
144     {
145 
146         /* Return error status.  */
147        return(NX_PTR_ERROR);
148     }
149 
150     /* Check for the client ID.  */
151     if ((client_ptr == NX_NULL) || (client_ptr -> nx_sntp_client_id == NXD_SNTP_ID))
152     {
153 
154         /* Return error status.  */
155         return(NX_PTR_ERROR);
156     }
157 
158     /* Check for invalid network interface input. */
159     if (iface_index >= NX_MAX_PHYSICAL_INTERFACES)
160     {
161 
162         return NX_INVALID_INTERFACE;
163     }
164 
165     /* Call the actual client create service.  */
166     status = _nx_sntp_client_create(client_ptr, ip_ptr, iface_index, packet_pool_ptr,
167                                     leap_second_handler,  kiss_of_death_handler,  random_number_generator);
168 
169     /* Return completion status.  */
170     return(status);
171 }
172 
173 
174 /**************************************************************************/
175 /*                                                                        */
176 /*  FUNCTION                                               RELEASE        */
177 /*                                                                        */
178 /*    _nx_sntp_client_create                              PORTABLE C      */
179 /*                                                           6.1          */
180 /*  AUTHOR                                                                */
181 /*                                                                        */
182 /*    Yuxin Zhou, Microsoft Corporation                                   */
183 /*                                                                        */
184 /*  DESCRIPTION                                                           */
185 /*                                                                        */
186 /*    This function creates a SNTP client with the input NetX and SNTP    */
187 /*    parameters. Note the host application must initialize and start the */
188 /*    SNTP client using the nx_sntp_broadcast/unicast_initialize and      */
189 /*    nx_sntp_run_broadcast/unicast services to receive SNTP time updates.*/
190 /*                                                                        */
191 /*   INPUT                                                                */
192 /*                                                                        */
193 /*    client_ptr                        Pointer to client struct          */
194 /*    ip_ptr                            Pointer to client IP instance     */
195 /*    iface_index                       Index of SNTP network interface   */
196 /*    packet_pool_ptr                   Pointer to client packet pool     */
197 /*    socket_ptr                        Pointer to client UDP socket      */
198 /*    leap_second_handler               Pointer to leap second handler    */
199 /*    random_number_generator           Random number generator callback  */
200 /*                                                                        */
201 /*  OUTPUT                                                                */
202 /*                                                                        */
203 /*    status                            Actual completion status          */
204 /*    NX_SUCCESS                        Successful completion status      */
205 /*    NX_SNTP_INSUFFICIENT_PACKET_PAYLOAD                                 */
206 /*                                      Invalid packet pool payload       */
207 /*                                                                        */
208 /*  CALLED BY                                                             */
209 /*                                                                        */
210 /*    Application Code                                                    */
211 /*                                                                        */
212 /*  CALLS                                                                 */
213 /*                                                                        */
214 /*    tx_timer_create                  Create ThreadX timer service       */
215 /*    tx_timer_delete                  Delete ThreadX timer service       */
216 /*    tx_mutex_create                  Create ThreadX mutex service       */
217 /*    tx_mutex_delete                  Delete ThreadX mutex service       */
218 /*    nx_udp_socket_create             Create the SNTP Client socket      */
219 /*    nx_udp_socket_delete             Delete the SNTP Client socket      */
220 /*    nx_udp_socket_bind               Bind the SNTP Client to SNTP port  */
221 /*                                                                        */
222 /*  RELEASE HISTORY                                                       */
223 /*                                                                        */
224 /*    DATE              NAME                      DESCRIPTION             */
225 /*                                                                        */
226 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
227 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
228 /*                                            resulting in version 6.1    */
229 /*                                                                        */
230 /**************************************************************************/
_nx_sntp_client_create(NX_SNTP_CLIENT * client_ptr,NX_IP * ip_ptr,UINT iface_index,NX_PACKET_POOL * packet_pool_ptr,UINT (* leap_second_handler)(NX_SNTP_CLIENT * client_ptr,UINT indicator),UINT (* kiss_of_death_handler)(NX_SNTP_CLIENT * client_ptr,UINT code),VOID (random_number_generator)(struct NX_SNTP_CLIENT_STRUCT * client_ptr,ULONG * rand))231 UINT  _nx_sntp_client_create(NX_SNTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT iface_index, NX_PACKET_POOL *packet_pool_ptr,
232                                 UINT (*leap_second_handler)(NX_SNTP_CLIENT *client_ptr, UINT indicator),
233                                 UINT (*kiss_of_death_handler)(NX_SNTP_CLIENT *client_ptr, UINT code),
234                                 VOID (random_number_generator)(struct NX_SNTP_CLIENT_STRUCT *client_ptr, ULONG *rand))
235 {
236 
237 UINT status;
238 
239 
240     /* Null the members of NX_SNTP_CLIENT.  */
241     memset(client_ptr, 0, sizeof(NX_SNTP_CLIENT));
242 
243     /* Set the Client ID to indicate the SNTP client thread is ready.  */
244     client_ptr -> nx_sntp_client_id = NXD_SNTP_ID;
245 
246     /* Set the IP instance.  */
247     client_ptr -> nx_sntp_client_ip_ptr   =  ip_ptr;
248 
249     /* Set the SNTP network interface. */
250     client_ptr -> nx_sntp_client_interface_index = iface_index;
251 
252     /* Check for minimal packet size requirement. */
253 #ifndef NX_DISABLE_IPV4
254     if  (packet_pool_ptr -> nx_packet_pool_payload_size <
255             (sizeof(NX_IPV4_HEADER) + sizeof(NX_UDP_HEADER) + NX_SNTP_CLIENT_PACKET_DATA_SIZE))
256     {
257 
258         return NX_SNTP_INSUFFICIENT_PACKET_PAYLOAD;
259     }
260 #endif /* NX_DISABLE_IPV4 */
261 
262 
263     /* This only assures IPv4 packets will work. We do not know yet if the Client expects to receive
264        SNTP packets over ipv6 networks. When sending packets, the SNTP Client will have set its
265        SNTP server from which the IP type will be determined.  However, for receiving packets,
266        it is up to the host to ensure its packet payload will be large enough for IPv6 packets:
267 
268              sizeof(NX_IPV6_HEADER) + sizeof(NX_UDP_HEADER) + NX_SNTP_CLIENT_PACKET_DATA_SIZE)
269                   40 bytes                   8 bytes                    48 bytes
270     */
271 
272     client_ptr -> nx_sntp_client_packet_pool_ptr =  packet_pool_ptr;
273 
274     /* Create a udp socket to receive SNTP time data. */
275     status =  nx_udp_socket_create(client_ptr -> nx_sntp_client_ip_ptr, &(client_ptr -> nx_sntp_client_udp_socket),
276                                    NX_SNTP_CLIENT_UDP_SOCKET_NAME, NX_IP_NORMAL,
277                                    NX_FRAGMENT_OKAY, NX_SNTP_CLIENT_TIME_TO_LIVE,
278                                    NX_SNTP_CLIENT_MAX_QUEUE_DEPTH);
279 
280     /* Check for error. */
281     if (status != NX_SUCCESS)
282     {
283 
284         return status;
285     }
286 
287     /* Register a receive notify callback.  */
288     status = nx_udp_socket_receive_notify(&(client_ptr -> nx_sntp_client_udp_socket), _nx_sntp_client_receive_notify);
289 
290     /* Check for errors.  */
291     if (status != NX_SUCCESS)
292     {
293 
294         nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
295 
296         return status;
297     }
298 
299     /* Set callback for leap second handler (optional).  */
300     client_ptr -> leap_second_handler = leap_second_handler;
301 
302     /* Set callback for kiss of death server packet handler (optional).  */
303     client_ptr -> kiss_of_death_handler = kiss_of_death_handler;
304 
305     /* Set callback for random number generator (Only applicable for unicast clients
306        configured for random wait on startup).  */
307     client_ptr -> random_number_generator = random_number_generator;
308 
309     /* Create the SNTP update timeout timer.  */
310     status =  tx_timer_create(&client_ptr -> nx_sntp_update_timer, "SNTP Client Update Timer",
311               _nx_sntp_client_update_timeout_entry, (ULONG)client_ptr,
312               (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL),
313               (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL), TX_NO_ACTIVATE);
314 
315     /* Check for error.  */
316     if (status != TX_SUCCESS)
317     {
318 
319         /* Delete the UDP socket.  */
320         nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
321 
322         /* Return error status.  */
323         return(status);
324     }
325 
326     /* Create the SNTP mutex.  */
327     status =  tx_mutex_create(&(client_ptr -> nx_sntp_client_mutex), "NetX SNTP Client Mutex", TX_NO_INHERIT);
328 
329     /* Determine if the semaphore creation was successful.  */
330     if (status != NX_SUCCESS)
331     {
332 
333         /* Delete the UDP socket.  */
334         nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
335 
336         /* Delete the timer.  */
337         tx_timer_delete(&(client_ptr -> nx_sntp_update_timer));
338 
339         /* No, return error status.  */
340         return(status);
341     }
342 
343         /* Create the SNTP event flag group.   */
344     status =  tx_event_flags_create(&nx_sntp_client_events, "NetX SNTP Client Events");
345 
346     /* Check the return status.  */
347     if (status != NX_SUCCESS)
348     {
349 
350         /* Delete the UDP socket.  */
351         nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
352 
353         /* Delete the timer.  */
354         tx_timer_delete(&(client_ptr -> nx_sntp_update_timer));
355 
356         /* Delete the Client mutex. */
357         tx_mutex_delete(&client_ptr -> nx_sntp_client_mutex);
358 
359         /* Error present, return error code.  */
360         return(status);
361     }
362 
363     /* Create the SNTP Client processing thread.  */
364     status =  tx_thread_create(&(client_ptr -> nx_sntp_client_thread), "NetX SNTP Client", _nx_sntp_client_thread_entry, (ULONG)client_ptr,
365                         client_ptr -> nx_sntp_client_thread_stack, NX_SNTP_CLIENT_THREAD_STACK_SIZE,
366                         NX_SNTP_CLIENT_THREAD_PRIORITY, NX_SNTP_CLIENT_PREEMPTION_THRESHOLD, 1, TX_DONT_START);
367 
368     /* Determine if the thread creation was successful.  */
369     if (status != NX_SUCCESS)
370     {
371 
372         /* Delete the mutex.  */
373         tx_mutex_delete(&(client_ptr -> nx_sntp_client_mutex));
374 
375         /* Delete the UDP socket.  */
376         nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
377 
378         /* Delete the timer.  */
379         tx_timer_delete(&(client_ptr -> nx_sntp_update_timer));
380 
381         /* Delete the event flag group.  */
382         tx_event_flags_delete(&nx_sntp_client_events);
383 
384         /* No, return error status.  */
385         return(status);
386     }
387 
388     return(NX_SUCCESS);
389 }
390 
391 
392 /**************************************************************************/
393 /*                                                                        */
394 /*  FUNCTION                                               RELEASE        */
395 /*                                                                        */
396 /*    _nxe_sntp_client_delete                             PORTABLE C      */
397 /*                                                           6.1          */
398 /*  AUTHOR                                                                */
399 /*                                                                        */
400 /*    Yuxin Zhou, Microsoft Corporation                                   */
401 /*                                                                        */
402 /*  DESCRIPTION                                                           */
403 /*                                                                        */
404 /*    This function checks for errors on the client delete service.       */
405 /*                                                                        */
406 /*   INPUT                                                                */
407 /*                                                                        */
408 /*    client_ptr                         Pointer to SNTP Client           */
409 /*                                                                        */
410 /*  OUTPUT                                                                */
411 /*                                                                        */
412 /*    NX_PTR_ERROR                       Invalid pointer parameter        */
413 /*    status                             Actual completion status         */
414 /*                                                                        */
415 /*  CALLS                                                                 */
416 /*                                                                        */
417 /*    _nx_sntp_client_delete             Actual SNTP client delete service*/
418 /*                                                                        */
419 /*  CALLED BY                                                             */
420 /*                                                                        */
421 /*    Application Code                                                    */
422 /*                                                                        */
423 /*  RELEASE HISTORY                                                       */
424 /*                                                                        */
425 /*    DATE              NAME                      DESCRIPTION             */
426 /*                                                                        */
427 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
428 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
429 /*                                            resulting in version 6.1    */
430 /*                                                                        */
431 /**************************************************************************/
_nxe_sntp_client_delete(NX_SNTP_CLIENT * client_ptr)432 UINT  _nxe_sntp_client_delete(NX_SNTP_CLIENT *client_ptr)
433 {
434 
435 UINT status;
436 
437 
438     /* Check for the validity of input parameter.  */
439     if ((client_ptr == NX_NULL) || (client_ptr -> nx_sntp_client_id != NXD_SNTP_ID))
440     {
441 
442         /* Return error status.  */
443         return(NX_PTR_ERROR);
444     }
445 
446     /* Check if this function is called from the appropriate thread.  */
447     NX_THREADS_ONLY_CALLER_CHECKING
448 
449     /* Call the actual client create service.  */
450     status =  _nx_sntp_client_delete(client_ptr);
451 
452     /* Return completion status.  */
453     return(status);
454 }
455 
456 
457 /**************************************************************************/
458 /*                                                                        */
459 /*  FUNCTION                                               RELEASE        */
460 /*                                                                        */
461 /*    _nx_sntp_client_delete                              PORTABLE C      */
462 /*                                                           6.2.1        */
463 /*  AUTHOR                                                                */
464 /*                                                                        */
465 /*    Yuxin Zhou, Microsoft Corporation                                   */
466 /*                                                                        */
467 /*  DESCRIPTION                                                           */
468 /*                                                                        */
469 /*    This function deletes a previously created SNTP Client and releases */
470 /*    ThreadX and NetX resources held by the Client.                      */
471 /*                                                                        */
472 /*    Note that it is the application's responsibility to delete/release  */
473 /*    the Client packet pool.                                             */
474 /*                                                                        */
475 /*   INPUT                                                                */
476 /*                                                                        */
477 /*    client_ptr                        Pointer to Client struct          */
478 /*                                                                        */
479 /*  OUTPUT                                                                */
480 /*                                                                        */
481 /*    NX_SUCCESS                        Successful completion status      */
482 /*                                                                        */
483 /*  CALLS                                                                 */
484 /*                                                                        */
485 /*    tx_timer_delete                  Delete ThreadX timer service       */
486 /*    tx_mutex_delete                  Delete ThreadX mutex service       */
487 /*    tx_timer_deactivate              Deschedule ThreadX timer           */
488 /*    nx_udp_socket_unbind             Release NetX UDP socket port       */
489 /*    nx_udp_socket_delete             Delete NetX UDP socket             */
490 /*                                                                        */
491 /*  CALLED BY                                                             */
492 /*                                                                        */
493 /*    Application Code                                                    */
494 /*                                                                        */
495 /*  RELEASE HISTORY                                                       */
496 /*                                                                        */
497 /*    DATE              NAME                      DESCRIPTION             */
498 /*                                                                        */
499 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
500 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
501 /*                                            resulting in version 6.1    */
502 /*  03-08-2023     Wenhui Xie               Modified comment(s),          */
503 /*                                            cleared the client ID,      */
504 /*                                            resulting in version 6.2.1  */
505 /*                                                                        */
506 /**************************************************************************/
_nx_sntp_client_delete(NX_SNTP_CLIENT * client_ptr)507 UINT  _nx_sntp_client_delete(NX_SNTP_CLIENT *client_ptr)
508 {
509 
510     /* Clear the client ID.  */
511     client_ptr -> nx_sntp_client_id = 0;
512 
513     /* Suspend the SNTP Client thread.  */
514     tx_thread_suspend(&client_ptr -> nx_sntp_client_thread);
515 
516     /* Terminate SNTP Client thread. */
517     tx_thread_terminate(&client_ptr -> nx_sntp_client_thread);
518 
519     /* Delete SNTP Client thread.  */
520     tx_thread_delete(&client_ptr -> nx_sntp_client_thread);
521 
522     /* Delete the Client mutex. */
523     tx_mutex_delete(&client_ptr -> nx_sntp_client_mutex);
524 
525     /* Deactivate SNTP update timer.  */
526     tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
527 
528     /* Delete the update timer.  */
529     tx_timer_delete(&(client_ptr -> nx_sntp_update_timer));
530 
531     /* Make sure the socket is in an unbound state.  */
532     nx_udp_socket_unbind(&(client_ptr -> nx_sntp_client_udp_socket));
533 
534     /* Ok to delete the UDP socket.  */
535     nx_udp_socket_delete(&(client_ptr -> nx_sntp_client_udp_socket));
536 
537     /* Delete the Client event flags group. */
538     tx_event_flags_delete(&nx_sntp_client_events);
539 
540     /* Return success status.  */
541     return(NX_SUCCESS);
542 }
543 
544 
545 /**************************************************************************/
546 /*                                                                        */
547 /*  FUNCTION                                               RELEASE        */
548 /*                                                                        */
549 /*    _nx_sntp_client_update_timeout_entry                PORTABLE C      */
550 /*                                                           6.1          */
551 /*  AUTHOR                                                                */
552 /*                                                                        */
553 /*    Yuxin Zhou, Microsoft Corporation                                   */
554 /*                                                                        */
555 /*  DESCRIPTION                                                           */
556 /*                                                                        */
557 /*    This function decrements the Client's time remaining since it last  */
558 /*    received a time update.                                             */
559 /*                                                                        */
560 /*   INPUT                                                                */
561 /*                                                                        */
562 /*    client_ptr                           Pointer to Client              */
563 /*                                                                        */
564 /*  OUTPUT                                                                */
565 /*                                                                        */
566 /*    None                                                                */
567 /*                                                                        */
568 /*  CALLS                                                                 */
569 /*                                                                        */
570 /*    None                                                                */
571 /*                                                                        */
572 /*  CALLED BY                                                             */
573 /*                                                                        */
574 /*    ThreadX                               ThreadX timer callback        */
575 /*                                                                        */
576 /*  RELEASE HISTORY                                                       */
577 /*                                                                        */
578 /*    DATE              NAME                      DESCRIPTION             */
579 /*                                                                        */
580 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
581 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
582 /*                                            resulting in version 6.1    */
583 /*                                                                        */
584 /**************************************************************************/
_nx_sntp_client_update_timeout_entry(ULONG info)585 VOID  _nx_sntp_client_update_timeout_entry(ULONG info)
586 {
587 
588 NX_SNTP_CLIENT *client_ptr;
589 
590 
591     client_ptr = (NX_SNTP_CLIENT *)info;
592 
593     /* Is the Client's time remaining large enough to decrement by the timeout interval?  */
594     if (client_ptr -> nx_sntp_update_time_remaining >= (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL))
595     {
596 
597         /* Yes; ok to decrement time remaining.  */
598         client_ptr -> nx_sntp_update_time_remaining -= (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL);
599     }
600     else
601     {
602         /* No, set the time remaining to NULL.  */
603         client_ptr -> nx_sntp_update_time_remaining = 0;
604     }
605 
606     /* Update time elapsed. */
607     client_ptr -> nx_sntp_client_local_ntp_time_elapsed += NX_SNTP_UPDATE_TIMEOUT_INTERVAL;
608 
609     /* Is the client operating in unicast? */
610     if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
611     {
612 
613         /* Yes; Update the time remaining till it is time to poll the SNTP server. */
614         if (client_ptr -> nx_sntp_client_unicast_poll_interval >= (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL))
615         {
616             client_ptr -> nx_sntp_client_unicast_poll_interval -= (NX_IP_PERIODIC_RATE * NX_SNTP_UPDATE_TIMEOUT_INTERVAL);
617         }
618         else
619         {
620 
621             /* Time is up. Client should send out another update request. */
622             client_ptr -> nx_sntp_client_unicast_poll_interval = 0;
623         }
624     }
625     return;
626 }
627 
628 
629 /**************************************************************************/
630 /*                                                                        */
631 /*  FUNCTION                                               RELEASE        */
632 /*                                                                        */
633 /*    _nx_sntp_client_create_time_request_packet          PORTABLE C      */
634 /*                                                           6.1          */
635 /*  AUTHOR                                                                */
636 /*                                                                        */
637 /*    Yuxin Zhou, Microsoft Corporation                                   */
638 /*                                                                        */
639 /*  DESCRIPTION                                                           */
640 /*                                                                        */
641 /*    This function converts NTP time data from the input buffer into a   */
642 /*    unicast time data and copies into the supplied packet buffer.       */
643 /*                                                                        */
644 /*   INPUT                                                                */
645 /*                                                                        */
646 /*    client_ptr                           Pointer to Client              */
647 /*    packet_ptr                           Pointer to time update packet  */
648 /*    time_message_ptr                     Pointer to time request        */
649 /*                                                                        */
650 /*  OUTPUT                                                                */
651 /*                                                                        */
652 /*    NX_SUCCESS                           Successful completion status   */
653 /*                                                                        */
654 /*  CALLS                                                                 */
655 /*                                                                        */
656 /*    None                                                                */
657 /*                                                                        */
658 /*  CALLED BY                                                             */
659 /*                                                                        */
660 /*    _nx_sntp_client_send_unicast_request Send unicast request to server */
661 /*                                                                        */
662 /*  RELEASE HISTORY                                                       */
663 /*                                                                        */
664 /*    DATE              NAME                      DESCRIPTION             */
665 /*                                                                        */
666 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
667 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
668 /*                                            resulting in version 6.1    */
669 /*                                                                        */
670 /**************************************************************************/
_nx_sntp_client_create_time_request_packet(NX_SNTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_SNTP_TIME_MESSAGE * time_message_ptr)671 UINT  _nx_sntp_client_create_time_request_packet(NX_SNTP_CLIENT *client_ptr, NX_PACKET *packet_ptr,
672                                                  NX_SNTP_TIME_MESSAGE *time_message_ptr)
673 {
674     NX_PARAMETER_NOT_USED(client_ptr);
675 
676     if (40u > ((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(packet_ptr -> nx_packet_append_ptr)))
677     {
678         return(NX_SIZE_ERROR);
679     }
680 
681     /* Clear packet data. */
682     memset(packet_ptr -> nx_packet_append_ptr, 0, 40);
683 
684     *(packet_ptr -> nx_packet_append_ptr) = (UCHAR)(time_message_ptr -> flags);
685 
686     /* Skip to transmit time; all other fields are not used for a client unicast request.  */
687     packet_ptr -> nx_packet_append_ptr += 40;
688     packet_ptr -> nx_packet_length += 40;
689 
690     /* Copy the transmit time stamp from time request into the packet buffer.  */
691     time_message_ptr -> transmit_time.seconds = time_message_ptr -> transmit_time_stamp[0];
692     time_message_ptr -> transmit_time.fraction = time_message_ptr -> transmit_time_stamp[1];
693 
694     /* Now copy the data to the buffer. */
695     *((ULONG*)(packet_ptr -> nx_packet_append_ptr)) = (ULONG)(time_message_ptr -> transmit_time.seconds);
696     *((ULONG*)(packet_ptr -> nx_packet_append_ptr + 4)) = (ULONG)(time_message_ptr -> transmit_time.fraction);
697 
698     /* Change endian to network order. */
699     NX_CHANGE_ULONG_ENDIAN(*((ULONG*)(packet_ptr -> nx_packet_append_ptr)));
700     NX_CHANGE_ULONG_ENDIAN(*((ULONG*)(packet_ptr -> nx_packet_append_ptr + 4)));
701 
702     packet_ptr -> nx_packet_append_ptr += 8;
703     packet_ptr -> nx_packet_length += 8;
704 
705     /* Return completion status.  */
706     return NX_SUCCESS;
707 }
708 
709 
710 /**************************************************************************/
711 /*                                                                        */
712 /*  FUNCTION                                               RELEASE        */
713 /*                                                                        */
714 /*    _nxde_sntp_client_initialize_unicast                PORTABLE C      */
715 /*                                                           6.1          */
716 /*  AUTHOR                                                                */
717 /*                                                                        */
718 /*    Yuxin Zhou, Microsoft Corporation                                   */
719 /*                                                                        */
720 /*  DESCRIPTION                                                           */
721 /*                                                                        */
722 /*    This function performs error checking for the service that          */
723 /*    initializes the Client for unicast service.                         */
724 /*                                                                        */
725 /*   INPUT                                                                */
726 /*                                                                        */
727 /*    client_ptr                       Pointer to Client struct           */
728 /*    unicast_time_server              Pointer to unicast server          */
729 /*                                                                        */
730 /*  OUTPUT                                                                */
731 /*                                                                        */
732 /*    NX_PTR_ERROR                      Invalid pointer input             */
733 /*    status                            Actual completion status          */
734 /*                                                                        */
735 /*  CALLS                                                                 */
736 /*                                                                        */
737 /*     None                                                               */
738 /*                                                                        */
739 /*  CALLED BY                                                             */
740 /*                                                                        */
741 /*    Application Code                                                    */
742 /*                                                                        */
743 /*  RELEASE HISTORY                                                       */
744 /*                                                                        */
745 /*    DATE              NAME                      DESCRIPTION             */
746 /*                                                                        */
747 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
748 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
749 /*                                            resulting in version 6.1    */
750 /*                                                                        */
751 /**************************************************************************/
_nxde_sntp_client_initialize_unicast(NX_SNTP_CLIENT * client_ptr,NXD_ADDRESS * unicast_time_server)752 UINT  _nxde_sntp_client_initialize_unicast(NX_SNTP_CLIENT *client_ptr, NXD_ADDRESS *unicast_time_server)
753 {
754 
755 UINT  status;
756 
757 
758     /* Check pointer input.  */
759     if ((client_ptr == NX_NULL) || (unicast_time_server == NX_NULL))
760     {
761 
762         /* Return error status.  */
763         return NX_PTR_ERROR;
764     }
765 
766     /* Check if this function is called from the appropriate thread.  */
767     NX_THREADS_ONLY_CALLER_CHECKING
768 
769     /* Call the actual Client for initialize unicast service.  */
770     status = _nxd_sntp_client_initialize_unicast(client_ptr, unicast_time_server);
771 
772     /* Return completion status.  */
773     return status;
774 }
775 
776 
777 /**************************************************************************/
778 /*                                                                        */
779 /*  FUNCTION                                               RELEASE        */
780 /*                                                                        */
781 /*    _nxd_sntp_client_initialize_unicast                 PORTABLE C      */
782 /*                                                           6.1          */
783 /*  AUTHOR                                                                */
784 /*                                                                        */
785 /*    Yuxin Zhou, Microsoft Corporation                                   */
786 /*                                                                        */
787 /*  DESCRIPTION                                                           */
788 /*                                                                        */
789 /*    This function sets up the Client to operate in unicast mode with the*/
790 /*    supplied IPv4 or IPv6 SNTP server as the primary (current) server.  */
791 /*                                                                        */
792 /*    For adding IPv4 and IPv6 SNTP servers to the unicast server list,   */
793 /*    use the nxd_sntp_client_duo_add_unicast_server_to_list service.     */
794 /*                                                                        */
795 /*   INPUT                                                                */
796 /*                                                                        */
797 /*    client_ptr                       Pointer to Client struct           */
798 /*    unicast_poll_interval            Interval between update requests   */
799 /*    unicast_time_server              Pointer to unicast server          */
800 /*                                                                        */
801 /*  OUTPUT                                                                */
802 /*                                                                        */
803 /*    NX_SUCCESS                        Successful completion status      */
804 /*    NX_SNTP_PARAM_ERROR               Invalid server list input         */
805 /*                                                                        */
806 /*  CALLS                                                                 */
807 /*                                                                        */
808 /*     memset                           Copy data to area of memory       */
809 /*                                                                        */
810 /*  CALLED BY                                                             */
811 /*                                                                        */
812 /*    Application Code                                                    */
813 /*                                                                        */
814 /*  RELEASE HISTORY                                                       */
815 /*                                                                        */
816 /*    DATE              NAME                      DESCRIPTION             */
817 /*                                                                        */
818 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
819 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
820 /*                                            resulting in version 6.1    */
821 /*                                                                        */
822 /**************************************************************************/
_nxd_sntp_client_initialize_unicast(NX_SNTP_CLIENT * client_ptr,NXD_ADDRESS * unicast_time_server)823 UINT  _nxd_sntp_client_initialize_unicast(NX_SNTP_CLIENT *client_ptr, NXD_ADDRESS *unicast_time_server)
824 {
825 
826 
827     /* Set the Client polling interval.  */
828     client_ptr -> nx_sntp_client_unicast_poll_interval = (NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL  * NX_IP_PERIODIC_RATE);
829 
830     /* Initialize the number of times we've increased the backoff rate to zero. */
831     client_ptr -> nx_sntp_client_backoff_count = 0;
832 
833     /* Clear the Client's current server IP.  */
834     memset(&client_ptr -> nx_sntp_server_ip_address, 0, sizeof(NXD_ADDRESS));
835 
836 #ifdef FEATURE_NX_IPV6
837     /* Set as the Client's unicast server.  */
838     COPY_NXD_ADDRESS(unicast_time_server, &client_ptr -> nx_sntp_unicast_time_server);
839 
840     /* Set as the Client's current SNTP server.  */
841     COPY_NXD_ADDRESS(unicast_time_server, &client_ptr -> nx_sntp_server_ip_address);
842 #else
843     /* Set as the Client's unicast server.  */
844     client_ptr -> nx_sntp_unicast_time_server.nxd_ip_version = NX_IP_VERSION_V4;
845     client_ptr -> nx_sntp_unicast_time_server.nxd_ip_address.v4 = unicast_time_server -> nxd_ip_address.v4;
846 
847     /* Set as the Client's current SNTP server.  */
848     client_ptr -> nx_sntp_server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
849     client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4 = unicast_time_server -> nxd_ip_address.v4;
850 
851 #endif /* FEATURE_NX_IPV6 */
852 
853 
854     /* Set the Client operational mode to unicast mode.  */
855     client_ptr -> nx_sntp_client_protocol_mode = UNICAST_MODE;
856 
857     /* Indicate the Client task is ready to run! */
858     client_ptr -> nx_sntp_client_unicast_initialized = NX_TRUE;
859 
860     /* Initialize the server status as good (receiving updates). */
861     client_ptr -> nx_sntp_valid_server_status = NX_TRUE;
862 
863     return NX_SUCCESS;
864 }
865 
866 
867 /**************************************************************************/
868 /*                                                                        */
869 /*  FUNCTION                                               RELEASE        */
870 /*                                                                        */
871 /*    _nxe_sntp_client_initialize_unicast                 PORTABLE C      */
872 /*                                                           6.1          */
873 /*  AUTHOR                                                                */
874 /*                                                                        */
875 /*    Yuxin Zhou, Microsoft Corporation                                   */
876 /*                                                                        */
877 /*  DESCRIPTION                                                           */
878 /*                                                                        */
879 /*    This function checks for errors on the initialize Client for unicast*/
880 /*    service.                                                            */
881 /*                                                                        */
882 /*   INPUT                                                                */
883 /*                                                                        */
884 /*    client_ptr                       Pointer to Client struct           */
885 /*    unicast_time_server              SNTP unicast server to use         */
886 /*                                                                        */
887 /*  OUTPUT                                                                */
888 /*                                                                        */
889 /*    NX_PTR_ERROR                     Invalid pointer input              */
890 /*    NX_INVALID_PARAMETERS            Invalid non pointer input          */
891 /*    status                           Actual completion status           */
892 /*                                                                        */
893 /*  CALLS                                                                 */
894 /*                                                                        */
895 /*    None                                                                */
896 /*                                                                        */
897 /*  CALLED BY                                                             */
898 /*                                                                        */
899 /*    Application Code                                                    */
900 /*                                                                        */
901 /*  RELEASE HISTORY                                                       */
902 /*                                                                        */
903 /*    DATE              NAME                      DESCRIPTION             */
904 /*                                                                        */
905 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
906 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
907 /*                                            resulting in version 6.1    */
908 /*                                                                        */
909 /**************************************************************************/
_nxe_sntp_client_initialize_unicast(NX_SNTP_CLIENT * client_ptr,ULONG unicast_time_server)910 UINT  _nxe_sntp_client_initialize_unicast(NX_SNTP_CLIENT *client_ptr, ULONG unicast_time_server)
911 {
912 
913 #ifndef NX_DISABLE_IPV4
914 UINT status;
915 
916     /* Check input parameters.  */
917     if (client_ptr == NX_NULL)
918     {
919 
920         /* Return error status.  */
921         return NX_PTR_ERROR;
922     }
923 
924     if (unicast_time_server == 0x0)
925     {
926         return NX_INVALID_PARAMETERS;
927     }
928 
929     /* Check if this function is called from the appropriate thread.  */
930     NX_THREADS_ONLY_CALLER_CHECKING
931 
932 
933     /* Call the actual Client for initialize unicast service.  */
934     status = _nx_sntp_client_initialize_unicast(client_ptr, unicast_time_server);
935 
936     /* Return completion status.  */
937     return status;
938 #else
939     NX_PARAMETER_NOT_USED(client_ptr);
940     NX_PARAMETER_NOT_USED(unicast_time_server);
941 
942     return(NX_NOT_SUPPORTED);
943 #endif /* NX_DISABLE_IPV4 */
944 }
945 
946 
947 /**************************************************************************/
948 /*                                                                        */
949 /*  FUNCTION                                               RELEASE        */
950 /*                                                                        */
951 /*    _nx_sntp_client_initialize_unicast                  PORTABLE C      */
952 /*                                                           6.1          */
953 /*  AUTHOR                                                                */
954 /*                                                                        */
955 /*    Yuxin Zhou, Microsoft Corporation                                   */
956 /*                                                                        */
957 /*  DESCRIPTION                                                           */
958 /*                                                                        */
959 /*    This function converts the input address to the NetX Duo address    */
960 /*    format and calls the 'duo' equivalent service, nxd_sntp_client_     */
961 /*    _initialize_unicast.                                                */
962 /*                                                                        */
963 /*   INPUT                                                                */
964 /*                                                                        */
965 /*    client_ptr                       Pointer to Client struct           */
966 /*    unicast_time_server              SNTP unicast server to use         */
967 /*                                                                        */
968 /*  OUTPUT                                                                */
969 /*                                                                        */
970 /*    status                            Actual completion status          */
971 /*                                                                        */
972 /*  CALLS                                                                 */
973 /*     _nxd_sntp_client_initialize_unicast                                */
974 /*                                      Duo initialize unicast service    */
975 /*                                                                        */
976 /*  CALLED BY                                                             */
977 /*                                                                        */
978 /*    Application Code                                                    */
979 /*                                                                        */
980 /*  RELEASE HISTORY                                                       */
981 /*                                                                        */
982 /*    DATE              NAME                      DESCRIPTION             */
983 /*                                                                        */
984 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
985 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
986 /*                                            resulting in version 6.1    */
987 /*                                                                        */
988 /**************************************************************************/
_nx_sntp_client_initialize_unicast(NX_SNTP_CLIENT * client_ptr,ULONG unicast_time_server)989 UINT  _nx_sntp_client_initialize_unicast(NX_SNTP_CLIENT *client_ptr, ULONG unicast_time_server)
990 {
991 
992 #ifndef NX_DISABLE_IPV4
993 UINT  status;
994 NXD_ADDRESS duo_unicast_time_server;
995 
996 
997 
998     duo_unicast_time_server.nxd_ip_address.v4 = unicast_time_server;
999     duo_unicast_time_server.nxd_ip_version = NX_IP_VERSION_V4;
1000 
1001     status = _nxd_sntp_client_initialize_unicast(client_ptr, &duo_unicast_time_server);
1002 
1003     return status;
1004 #else
1005     NX_PARAMETER_NOT_USED(client_ptr);
1006     NX_PARAMETER_NOT_USED(unicast_time_server);
1007 
1008     return(NX_NOT_SUPPORTED);
1009 #endif /* NX_DISABLE_IPV4 */
1010 }
1011 
1012 
1013 /**************************************************************************/
1014 /*                                                                        */
1015 /*  FUNCTION                                               RELEASE        */
1016 /*                                                                        */
1017 /*    _nxe_sntp_client_run_unicast                        PORTABLE C      */
1018 /*                                                           6.1          */
1019 /*  AUTHOR                                                                */
1020 /*                                                                        */
1021 /*    Yuxin Zhou, Microsoft Corporation                                   */
1022 /*                                                                        */
1023 /*  DESCRIPTION                                                           */
1024 /*                                                                        */
1025 /*    This function performs error checking on the run unicast service.   */
1026 /*                                                                        */
1027 /*   INPUT                                                                */
1028 /*                                                                        */
1029 /*    client_ptr                       Pointer to Client                  */
1030 /*                                                                        */
1031 /*  OUTPUT                                                                */
1032 /*                                                                        */
1033 /*    NX_PTR_ERROR                     Invalid pointer input              */
1034 /*    status                           Actual completion status           */
1035 /*                                                                        */
1036 /*  CALLS                                                                 */
1037 /*    _nx_sntp_client_run_unicast      Actual run unicast service         */
1038 /*                                                                        */
1039 /*  CALLED BY                                                             */
1040 /*                                                                        */
1041 /*    Application Code                                                    */
1042 /*                                                                        */
1043 /*  RELEASE HISTORY                                                       */
1044 /*                                                                        */
1045 /*    DATE              NAME                      DESCRIPTION             */
1046 /*                                                                        */
1047 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1048 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1049 /*                                            resulting in version 6.1    */
1050 /*                                                                        */
1051 /**************************************************************************/
_nxe_sntp_client_run_unicast(NX_SNTP_CLIENT * client_ptr)1052 UINT  _nxe_sntp_client_run_unicast(NX_SNTP_CLIENT *client_ptr)
1053 {
1054 
1055 UINT status;
1056 
1057     /* Check for invalid pointer input.  */
1058     if (client_ptr == NX_NULL)
1059     {
1060 
1061         /* Return pointer error.  */
1062         return NX_PTR_ERROR;
1063     }
1064 
1065     /* Check if this function is called from the appropriate thread.  */
1066     NX_THREADS_ONLY_CALLER_CHECKING
1067 
1068     /* Call the actual run unicast service.  */
1069     status = _nx_sntp_client_run_unicast(client_ptr);
1070 
1071     /* Return actual completion status.  */
1072     return status;
1073 }
1074 
1075 
1076 /**************************************************************************/
1077 /*                                                                        */
1078 /*  FUNCTION                                               RELEASE        */
1079 /*                                                                        */
1080 /*    _nx_sntp_client_run_unicast                         PORTABLE C      */
1081 /*                                                           6.1          */
1082 /*  AUTHOR                                                                */
1083 /*                                                                        */
1084 /*    Yuxin Zhou, Microsoft Corporation                                   */
1085 /*                                                                        */
1086 /*  DESCRIPTION                                                           */
1087 /*                                                                        */
1088 /*    This function starts the SNTP Client for unicast SNTP processing    */
1089 /*    by activating the SNTP timer and main processing thread. The Client */
1090 /*    is checked for being initialized for unicast SNTP and if it is      */
1091 /*    not, the function returns an error status.                          */
1092 /*                                                                        */
1093 /*   INPUT                                                                */
1094 /*                                                                        */
1095 /*    client_ptr                       Pointer to Client                  */
1096 /*                                                                        */
1097 /*  OUTPUT                                                                */
1098 /*                                                                        */
1099 /*    NX_SNTP_CLIENT_NOT_INITIALIZED   Client initialized flag not set    */
1100 /*    NX_SNTP_CLIENT_ALREADY_STARTED   Client already started             */
1101 /*    status                           Actual completion status           */
1102 /*                                                                        */
1103 /*  CALLS                                                                 */
1104 /*                                                                        */
1105 /*    tx_timer_activate                Start the ThreadX timer            */
1106 /*    tx_thread_resume                 Resume the specified thread        */
1107 /*                                                                        */
1108 /*  CALLED BY                                                             */
1109 /*                                                                        */
1110 /*    Application Code                                                    */
1111 /*                                                                        */
1112 /*  RELEASE HISTORY                                                       */
1113 /*                                                                        */
1114 /*    DATE              NAME                      DESCRIPTION             */
1115 /*                                                                        */
1116 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1117 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1118 /*                                            resulting in version 6.1    */
1119 /*                                                                        */
1120 /**************************************************************************/
_nx_sntp_client_run_unicast(NX_SNTP_CLIENT * client_ptr)1121 UINT  _nx_sntp_client_run_unicast(NX_SNTP_CLIENT *client_ptr)
1122 {
1123 
1124 UINT    status;
1125 ULONG   startup_ticks;
1126 
1127 
1128     status = tx_mutex_get(&client_ptr -> nx_sntp_client_mutex, TX_WAIT_FOREVER);
1129 
1130     /* Check for error. */
1131     if (status != NX_SUCCESS)
1132     {
1133 
1134         return status;
1135     }
1136 
1137     /* Determine if SNTP has already been started.  */
1138     if (client_ptr -> nx_sntp_client_started)
1139     {
1140 
1141         /* Error SNTP has already been started.  */
1142 
1143         /* Release the SNTP mutex.  */
1144         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1145 
1146         /* Return completion status.  */
1147         return(NX_SNTP_CLIENT_ALREADY_STARTED);
1148     }
1149 
1150     /* Verify the client is ready to start receiving time data.  */
1151     if (client_ptr -> nx_sntp_client_unicast_initialized == NX_FALSE)
1152     {
1153 
1154         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1155 
1156         /* Return the error condition.  */
1157         return NX_SNTP_CLIENT_NOT_INITIALIZED;
1158     }
1159 
1160     /* Should the first time request sleep for a random timeout?  */
1161     if ((NX_SNTP_CLIENT_RANDOMIZE_ON_STARTUP == NX_TRUE) && (client_ptr -> random_number_generator))
1162     {
1163 
1164         /* Yes, generate a random number of ticks to sleep.*/
1165        (client_ptr -> random_number_generator)(client_ptr, &startup_ticks);
1166 
1167        /* Sleep for the random length.  */
1168        tx_thread_sleep(startup_ticks);
1169     }
1170 
1171     /* Set status that the first update is expected. */
1172     client_ptr -> nx_sntp_client_first_update_pending = NX_TRUE;
1173 
1174     /* Initialize missed broadcasts and bad time updates from server.  */
1175     client_ptr -> nx_sntp_client_invalid_time_updates = 0;
1176 
1177 
1178     /* Set the maximum timeout to the full count.  */
1179     client_ptr -> nx_sntp_update_time_remaining = (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE);
1180 
1181     /* Activate SNTP update timer.  */
1182     status = tx_timer_activate(&(client_ptr -> nx_sntp_update_timer));
1183 
1184     /* Check for error. Ignore timer is already active error.  */
1185     if (status != TX_SUCCESS && status != TX_ACTIVATE_ERROR)
1186     {
1187 
1188         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1189 
1190         /* Return the error condition.  */
1191         return status;
1192     }
1193 
1194     /* Bind the UDP socket to the IP port.  */
1195     status =  nx_udp_socket_bind(&(client_ptr -> nx_sntp_client_udp_socket), NX_SNTP_CLIENT_UDP_PORT, NX_WAIT_FOREVER);
1196 
1197     /* Check for error. */
1198     if (status != NX_SUCCESS)
1199     {
1200 
1201         /* Deactivate SNTP update timer.  */
1202         tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
1203 
1204         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1205 
1206         return status;
1207     }
1208 
1209     status = tx_thread_resume(&(client_ptr -> nx_sntp_client_thread));
1210 
1211     /* Start the SNTP Client thread. */
1212     if (status != NX_SUCCESS)
1213     {
1214 
1215         /* Release the socket port. */
1216         nx_udp_socket_unbind(&(client_ptr -> nx_sntp_client_udp_socket));
1217 
1218         /* Deactivate SNTP update timer.  */
1219         tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
1220 
1221         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1222 
1223         return status;
1224     }
1225 
1226     /* The client thread is successfully started, so set the started flag to true. */
1227     client_ptr -> nx_sntp_client_started = NX_TRUE;
1228 
1229     /* Clear the sleep flag.  */
1230     client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
1231 
1232     /* Set poll interval to 0 to send request immediately. */
1233     client_ptr -> nx_sntp_client_unicast_poll_interval = 0;
1234 
1235     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1236 
1237     return NX_SUCCESS;
1238 }
1239 
1240 
1241 /**************************************************************************/
1242 /*                                                                        */
1243 /*  FUNCTION                                               RELEASE        */
1244 /*                                                                        */
1245 /*    _nx_sntp_client_run_unicast                         PORTABLE C      */
1246 /*                                                           6.1          */
1247 /*  AUTHOR                                                                */
1248 /*                                                                        */
1249 /*    Yuxin Zhou, Microsoft Corporation                                   */
1250 /*                                                                        */
1251 /*  DESCRIPTION                                                           */
1252 /*                                                                        */
1253 /*   This function checks if the SNTP client has received a packet, and if*/
1254 /*   so processes it for valid SNTP data and resets the timeouts          */
1255 /*   for sending (polling) and receiving updates. If no packet received it*/
1256 /*   checks if the timeout to receive an update has expired.  If so, it   */
1257 /*   sends out another SNTP request.                                      */
1258 /*                                                                        */
1259 /*   When a timeout expires, the poll interval is increased as per        */
1260 /*   RFC guidelines until it exceeds the maximum time without an update.  */
1261 /*   An error flag is set, and it is up to the host application to        */
1262 /*   change its unicast SNTP server.                                      */
1263 /*                                                                        */
1264 /*   INPUT                                                                */
1265 /*                                                                        */
1266 /*    client_ptr                       Pointer to Client                  */
1267 /*                                                                        */
1268 /*  OUTPUT                                                                */
1269 /*                                                                        */
1270 /*    None                                                                */
1271 /*                                                                        */
1272 /*  CALLS                                                                 */
1273 /*                                                                        */
1274 /*    _nx_sntp_client_reset_current_time_message                          */
1275 /*                                    Save time update before next update */
1276 /*    _nx_sntp_client_receive_time_update                                 */
1277 /*                                    Receive server update packets       */
1278 /*    _nx_sntp_client_process_time_data                                   */
1279 /*                                    Process time data in server update  */
1280 /*                                                                        */
1281 /*  CALLED BY                                                             */
1282 /*                                                                        */
1283 /*    Application Code                                                    */
1284 /*                                                                        */
1285 /*  RELEASE HISTORY                                                       */
1286 /*                                                                        */
1287 /*    DATE              NAME                      DESCRIPTION             */
1288 /*                                                                        */
1289 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1290 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1291 /*                                            resulting in version 6.1    */
1292 /*                                                                        */
1293 /**************************************************************************/
_nx_sntp_client_process_unicast(NX_SNTP_CLIENT * client_ptr)1294 VOID  _nx_sntp_client_process_unicast(NX_SNTP_CLIENT *client_ptr)
1295 {
1296 
1297 UINT    status;
1298 ULONG   sntp_events;
1299 
1300 
1301     /* Check for a receive event. */
1302     status = tx_event_flags_get(&nx_sntp_client_events, NX_SNTP_CLIENT_RECEIVE_EVENT, TX_OR_CLEAR, &sntp_events, TX_NO_WAIT);
1303 
1304     if (status == NX_SUCCESS)
1305     {
1306 
1307         /* Listen for a server update packet.  */
1308         status = _nx_sntp_client_receive_time_update(client_ptr, TX_NO_WAIT);
1309 
1310         if (status == NX_SUCCESS)
1311         {
1312 
1313             /* Process the server update packet and apply to local time if valid.  */
1314             status =  _nx_sntp_client_process_update_packet(client_ptr);
1315 
1316             /* Check for error. */
1317             if (status != NX_SUCCESS)
1318             {
1319                  return;
1320             }
1321 
1322              /* Reset the Client poll timeout to the original poll interval.  */
1323              client_ptr -> nx_sntp_client_unicast_poll_interval = (NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL  * NX_IP_PERIODIC_RATE);
1324 
1325              /* Reset the Client timeout for maximum time lapse without a valid update. */
1326              client_ptr -> nx_sntp_update_time_remaining = (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE);
1327 
1328              /* Indicate the client has received at least one valid time update with the current server. */
1329              client_ptr -> nx_sntp_client_first_update_pending = NX_FALSE;
1330 
1331              client_ptr -> nx_sntp_client_backoff_count = 0;
1332              /* Set the server status as good (receiving updates). */
1333              client_ptr -> nx_sntp_valid_server_status = NX_TRUE;
1334 
1335              return;
1336         }
1337     }
1338 
1339     /* Has the timeout expired on the maximum lapse without a valid update?  */
1340     if (client_ptr -> nx_sntp_update_time_remaining == 0)
1341     {
1342 
1343         /* Yes, it has. Set the server status as no longer valid. */
1344         client_ptr -> nx_sntp_valid_server_status = NX_FALSE;
1345     }
1346 
1347     /* Is it time to send another SNTP request? */
1348     if (client_ptr -> nx_sntp_client_unicast_poll_interval == 0)
1349     {
1350 
1351 
1352         /* Save the last server message before the next update.  We need this for comparing time data. */
1353         _nx_sntp_client_reset_current_time_message(client_ptr);
1354 
1355         /* Create and send a unicast request .  */
1356         _nx_sntp_client_send_unicast_request(client_ptr);
1357 
1358 
1359         /* Check if we have received an update since the previous unicast poll. */
1360         if ((NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE - client_ptr -> nx_sntp_update_time_remaining) >
1361             (NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL  * NX_IP_PERIODIC_RATE))
1362         {
1363 
1364             /* No we have not. Increase the count of times we've increased the back off rate. */
1365             client_ptr -> nx_sntp_client_backoff_count++;
1366 
1367             client_ptr -> nx_sntp_client_unicast_poll_interval =
1368                 NX_IP_PERIODIC_RATE * NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL * NX_SNTP_CLIENT_EXP_BACKOFF_RATE * client_ptr -> nx_sntp_client_backoff_count;
1369         }
1370         else
1371         {
1372 
1373             /* Reset the polling interval to it's normal value. */
1374             client_ptr -> nx_sntp_client_unicast_poll_interval = NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL  * NX_IP_PERIODIC_RATE;
1375         }
1376 
1377         /* Check that the poll interval does not exceed the maximum lapse without a valid update. */
1378         if (client_ptr -> nx_sntp_client_unicast_poll_interval > (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE))
1379         {
1380 
1381             /* Set the poll interval equal to that lapse. */
1382             client_ptr -> nx_sntp_client_unicast_poll_interval = (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE);
1383         }
1384     }
1385 
1386     /* Nothing to do but wait...*/
1387 }
1388 
1389 
1390 /**************************************************************************/
1391 /*                                                                        */
1392 /*  FUNCTION                                               RELEASE        */
1393 /*                                                                        */
1394 /*    _nxde_sntp_client_initialize_broadcast              PORTABLE C      */
1395 /*                                                           6.1          */
1396 /*  AUTHOR                                                                */
1397 /*                                                                        */
1398 /*    Yuxin Zhou, Microsoft Corporation                                   */
1399 /*                                                                        */
1400 /*  DESCRIPTION                                                           */
1401 /*                                                                        */
1402 /*    This function performs error checking on the initialize Client for  */
1403 /*    IPv4 broadcast time updates service.                                */
1404 /*                                                                        */
1405 /*   INPUT                                                                */
1406 /*                                                                        */
1407 /*    client_ptr                       Pointer to Client                  */
1408 /*    multicast_server_address         Multicast server address           */
1409 /*    broadcast_time_server            Broadcast server address           */
1410 /*                                                                        */
1411 /*  OUTPUT                                                                */
1412 /*                                                                        */
1413 /*    NX_PTR_ERROR                     Invalid pointer input              */
1414 /*    NX_SNTP_PARAM_ERROR              Invalid non pointer input          */
1415 /*    status                           Actual completion status           */
1416 /*                                                                        */
1417 /*  CALLS                                                                 */
1418 /*     _nxd_sntp_client_initialize_duo_broadcast                          */
1419 /*                                     Initialize broadcast Client service*/
1420 /*  CALLED BY                                                             */
1421 /*                                                                        */
1422 /*    Application Code                                                    */
1423 /*                                                                        */
1424 /*  RELEASE HISTORY                                                       */
1425 /*                                                                        */
1426 /*    DATE              NAME                      DESCRIPTION             */
1427 /*                                                                        */
1428 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1429 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1430 /*                                            resulting in version 6.1    */
1431 /*                                                                        */
1432 /**************************************************************************/
_nxde_sntp_client_initialize_broadcast(NX_SNTP_CLIENT * client_ptr,NXD_ADDRESS * multicast_server_address,NXD_ADDRESS * broadcast_server_address)1433 UINT  _nxde_sntp_client_initialize_broadcast(NX_SNTP_CLIENT *client_ptr, NXD_ADDRESS *multicast_server_address, NXD_ADDRESS *broadcast_server_address)
1434 {
1435 
1436 UINT status;
1437 
1438 
1439     /* Check for invalid pointer input.  */
1440     if (client_ptr == NX_NULL)
1441     {
1442 
1443         /* Return pointer error.  */
1444         return NX_PTR_ERROR;
1445     }
1446 
1447     /* Check for missing broadcast server input. */
1448     if ((multicast_server_address == NX_NULL) && (broadcast_server_address == NX_NULL))
1449     {
1450 
1451         /* Return pointer error.  */
1452         return NX_PTR_ERROR;
1453     }
1454 
1455     /* Check for illegal broadcast address in IPv6. */
1456     if ((broadcast_server_address != NX_NULL) && (broadcast_server_address -> nxd_ip_version == NX_IP_VERSION_V6))
1457     {
1458 
1459         return NX_SNTP_PARAM_ERROR;
1460     }
1461 
1462     /* Check if this function is called from the appropriate thread.  */
1463     NX_THREADS_ONLY_CALLER_CHECKING
1464 
1465     /* Call the actual initialize client for broadcast time update service.  */
1466     status = _nxd_sntp_client_initialize_broadcast(client_ptr, multicast_server_address, broadcast_server_address);
1467 
1468     /* Return completion status.  */
1469     return status;
1470 }
1471 
1472 /**************************************************************************/
1473 /*                                                                        */
1474 /*  FUNCTION                                               RELEASE        */
1475 /*                                                                        */
1476 /*    _nxd_sntp_client_initialize_broadcast               PORTABLE C      */
1477 /*                                                           6.1          */
1478 /*  AUTHOR                                                                */
1479 /*                                                                        */
1480 /*    Yuxin Zhou, Microsoft Corporation                                   */
1481 /*                                                                        */
1482 /*  DESCRIPTION                                                           */
1483 /*                                                                        */
1484 /*    This function sets up the Client to operate in broadcast mode with  */
1485 /*    either an IPv6 or an IPv4 broadcast server.                         */
1486 /*                                                                        */
1487 /*   INPUT                                                                */
1488 /*                                                                        */
1489 /*    client_ptr                       Pointer to Client                  */
1490 /*    multicast_server_address         Multicast server address           */
1491 /*    broadcast_time_server            Broadcast server address           */
1492 /*                                                                        */
1493 /*  OUTPUT                                                                */
1494 /*                                                                        */
1495 /*    NX_SUCCESS                        Successful completion status      */
1496 /*                                                                        */
1497 /*  CALLS                                                                 */
1498 /*                                                                        */
1499 /*                                                                        */
1500 /*  CALLED BY                                                             */
1501 /*                                                                        */
1502 /*    Application Code                                                    */
1503 /*                                                                        */
1504 /*  RELEASE HISTORY                                                       */
1505 /*                                                                        */
1506 /*    DATE              NAME                      DESCRIPTION             */
1507 /*                                                                        */
1508 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1509 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1510 /*                                            resulting in version 6.1    */
1511 /*                                                                        */
1512 /**************************************************************************/
_nxd_sntp_client_initialize_broadcast(NX_SNTP_CLIENT * client_ptr,NXD_ADDRESS * multicast_server_address,NXD_ADDRESS * broadcast_server_address)1513 UINT  _nxd_sntp_client_initialize_broadcast(NX_SNTP_CLIENT *client_ptr, NXD_ADDRESS *multicast_server_address, NXD_ADDRESS *broadcast_server_address)
1514 {
1515 
1516 
1517     /* Clear Client's current server IP.  */
1518     memset(&client_ptr -> nx_sntp_server_ip_address, 0, sizeof(NXD_ADDRESS));
1519 
1520     /* Was a multicast IP was supplied?  */
1521     if (multicast_server_address != NX_NULL)
1522     {
1523 
1524 #ifdef FEATURE_NX_IPV6
1525         /* Set the Client multicast server.  */
1526         COPY_NXD_ADDRESS(multicast_server_address, &client_ptr -> nx_sntp_multicast_server_address);
1527 
1528         /* Set this as the Client's current SNTP server. */
1529         COPY_NXD_ADDRESS(multicast_server_address, &client_ptr -> nx_sntp_server_ip_address);
1530 #else
1531         /* Set the Client multicast server.  */
1532         client_ptr -> nx_sntp_multicast_server_address.nxd_ip_version = NX_IP_VERSION_V4;
1533         client_ptr -> nx_sntp_multicast_server_address.nxd_ip_address.v4 = multicast_server_address -> nxd_ip_address.v4;
1534 
1535         /* Set this as the Client's current SNTP server. */
1536         client_ptr -> nx_sntp_server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
1537         client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4 = multicast_server_address -> nxd_ip_address.v4;
1538 
1539 #endif /* FEATURE_NX_IPV6 */
1540     }
1541 
1542     /* No multicast address supplied, so was a broadcast address specified?  This must be an IPv4 address
1543        since IPv6 does not support broadcast. */
1544     else if ((broadcast_server_address != NX_NULL) && (broadcast_server_address -> nxd_ip_version == NX_IP_VERSION_V4))
1545     {
1546 
1547 
1548 #ifdef FEATURE_NX_IPV6
1549         /* Set the Client broadcast server.  */
1550         COPY_NXD_ADDRESS(broadcast_server_address, &client_ptr -> nx_sntp_broadcast_time_server);
1551 
1552         /* Set this as the Client's current SNTP server. */
1553         COPY_NXD_ADDRESS(broadcast_server_address, &client_ptr -> nx_sntp_server_ip_address);
1554 #else
1555         /* Set the Client broadcast server.  */
1556         client_ptr -> nx_sntp_broadcast_time_server.nxd_ip_version = NX_IP_VERSION_V4;
1557         client_ptr -> nx_sntp_broadcast_time_server.nxd_ip_address.v4 = broadcast_server_address -> nxd_ip_address.v4;
1558 
1559         /* Set this as the Client's current SNTP server. */
1560         client_ptr -> nx_sntp_server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
1561         client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4 = broadcast_server_address -> nxd_ip_address.v4;
1562 
1563 #endif /* FEATURE_NX_IPV6 */
1564     }
1565 
1566     /* Set client to work in broadcast (non unicast) mode.  */
1567     client_ptr -> nx_sntp_client_protocol_mode = BROADCAST_MODE;
1568 
1569     /* Indicate the client task is ready to run! */
1570     client_ptr -> nx_sntp_client_broadcast_initialized = NX_TRUE;
1571 
1572     /* Initialize the server status as good (receiving updates) even though it has
1573        not received one with the current server. */
1574     client_ptr -> nx_sntp_valid_server_status = NX_TRUE;
1575 
1576     return NX_SUCCESS;
1577 }
1578 
1579 
1580 /**************************************************************************/
1581 /*                                                                        */
1582 /*  FUNCTION                                               RELEASE        */
1583 /*                                                                        */
1584 /*    _nxe_sntp_client_initialize_broadcast               PORTABLE C      */
1585 /*                                                           6.1          */
1586 /*  AUTHOR                                                                */
1587 /*                                                                        */
1588 /*    Yuxin Zhou, Microsoft Corporation                                   */
1589 /*                                                                        */
1590 /*  DESCRIPTION                                                           */
1591 /*                                                                        */
1592 /*    This function performs error checking on the initialize Client for  */
1593 /*    broadcast time updates service. Note that broadcast and multicast   */
1594 /*    services are only available for IPv4 SNTP communcations.  For       */
1595 /*    multicast service, the host IP instance must be enabled for IGMP.   */
1596 /*                                                                        */
1597 /*   INPUT                                                                */
1598 /*                                                                        */
1599 /*    client_ptr                       Pointer to Client                  */
1600 /*    multicast_server_address         Server multicast address           */
1601 /*    broadcast_server_aaddres         Broadcast server address           */
1602 /*                                                                        */
1603 /*  OUTPUT                                                                */
1604 /*                                                                        */
1605 /*    NX_PTR_ERROR                     Invalid pointer input              */
1606 /*    NX_INVALID_PARAMETERS            Invalid non pointer input          */
1607 /*    status                           Actual completion status           */
1608 /*                                                                        */
1609 /*  CALLS                                                                 */
1610 /*     _nx_sntp_client_initialize_broadcast                               */
1611 /*                                     Actual initialize broadcast service*/
1612 /*  CALLED BY                                                             */
1613 /*                                                                        */
1614 /*    Application Code                                                    */
1615 /*                                                                        */
1616 /*  RELEASE HISTORY                                                       */
1617 /*                                                                        */
1618 /*    DATE              NAME                      DESCRIPTION             */
1619 /*                                                                        */
1620 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1621 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1622 /*                                            resulting in version 6.1    */
1623 /*                                                                        */
1624 /**************************************************************************/
_nxe_sntp_client_initialize_broadcast(NX_SNTP_CLIENT * client_ptr,ULONG multicast_server_address,ULONG broadcast_server_address)1625 UINT  _nxe_sntp_client_initialize_broadcast(NX_SNTP_CLIENT *client_ptr, ULONG multicast_server_address, ULONG broadcast_server_address)
1626 {
1627 
1628 #ifndef NX_DISABLE_IPV4
1629 UINT status;
1630 
1631 
1632     /* Check for invalid pointer input.  */
1633     if (client_ptr == NX_NULL)
1634     {
1635 
1636         /* Return pointer error.  */
1637         return NX_PTR_ERROR;
1638     }
1639 
1640     if ((multicast_server_address == 0x0) && (broadcast_server_address == 0x0))
1641     {
1642 
1643         return NX_INVALID_PARAMETERS;
1644     }
1645 
1646     /* Check if this function is called from the appropriate thread.  */
1647     NX_THREADS_ONLY_CALLER_CHECKING
1648 
1649     /* Call the actual initialize client for broadcast time update service.  */
1650     status = _nx_sntp_client_initialize_broadcast(client_ptr, multicast_server_address, broadcast_server_address);
1651 
1652     /* Return completion status.  */
1653     return status;
1654 #else
1655     NX_PARAMETER_NOT_USED(client_ptr);
1656     NX_PARAMETER_NOT_USED(multicast_server_address);
1657     NX_PARAMETER_NOT_USED(broadcast_server_address);
1658 
1659     return(NX_NOT_SUPPORTED);
1660 #endif /* NX_DISABLE_IPV4 */
1661 }
1662 
1663 
1664 /**************************************************************************/
1665 /*                                                                        */
1666 /*  FUNCTION                                               RELEASE        */
1667 /*                                                                        */
1668 /*    _nx_sntp_client_initialize_broadcast                PORTABLE C      */
1669 /*                                                           6.1          */
1670 /*  AUTHOR                                                                */
1671 /*                                                                        */
1672 /*    Yuxin Zhou, Microsoft Corporation                                   */
1673 /*                                                                        */
1674 /*  DESCRIPTION                                                           */
1675 /*                                                                        */
1676 /*    This function converts the IPv4 addresses to the NetX Duo address   */
1677 /*    format and calls the 'duo' equivalent service, nxd_sntp_client_     */
1678 /*    _initialize_broadcast.                                              */
1679 /*                                                                        */
1680 /*   INPUT                                                                */
1681 /*                                                                        */
1682 /*    client_ptr                       Pointer to Client                  */
1683 /*    multicast_server_address         Server multicast address           */
1684 /*    broadcast_server_address         Broadcast server address           */
1685 /*                                                                        */
1686 /*  OUTPUT                                                                */
1687 /*                                                                        */
1688 /*    status                            Actual completion status          */
1689 /*                                                                        */
1690 /*  CALLS                                                                 */
1691 /*                                                                        */
1692 /*     _nxd_sntp_client_initialize_broadcast                              */
1693 /*                                      Duo initialize broadcast service  */
1694 /*                                                                        */
1695 /*  CALLED BY                                                             */
1696 /*                                                                        */
1697 /*    Application Code                                                    */
1698 /*                                                                        */
1699 /*  RELEASE HISTORY                                                       */
1700 /*                                                                        */
1701 /*    DATE              NAME                      DESCRIPTION             */
1702 /*                                                                        */
1703 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1704 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1705 /*                                            resulting in version 6.1    */
1706 /*                                                                        */
1707 /**************************************************************************/
_nx_sntp_client_initialize_broadcast(NX_SNTP_CLIENT * client_ptr,ULONG multicast_server_address,ULONG broadcast_server_address)1708 UINT  _nx_sntp_client_initialize_broadcast(NX_SNTP_CLIENT *client_ptr, ULONG multicast_server_address, ULONG broadcast_server_address)
1709 {
1710 
1711 #ifndef NX_DISABLE_IPV4
1712 UINT        status;
1713 NXD_ADDRESS server_address;
1714 
1715 
1716     /* Was a multicast IP was supplied?  */
1717     if (multicast_server_address != 0x0)
1718     {
1719 
1720         server_address.nxd_ip_address.v4 = multicast_server_address;
1721         server_address.nxd_ip_version = NX_IP_VERSION_V4;
1722         status =  _nxd_sntp_client_initialize_broadcast(client_ptr, &server_address, NX_NULL);
1723     }
1724 
1725     /* Was a broadcast SNTP server specified?  */
1726     else if (broadcast_server_address != 0x0)
1727     {
1728 
1729         server_address.nxd_ip_address.v4 = broadcast_server_address;
1730         server_address.nxd_ip_version = NX_IP_VERSION_V4;
1731         status =  _nxd_sntp_client_initialize_broadcast(client_ptr, NX_NULL, &server_address);
1732     }
1733     else
1734         return NX_INVALID_PARAMETERS;
1735 
1736     return status;
1737 #else
1738     NX_PARAMETER_NOT_USED(client_ptr);
1739     NX_PARAMETER_NOT_USED(multicast_server_address);
1740     NX_PARAMETER_NOT_USED(broadcast_server_address);
1741 
1742     return(NX_NOT_SUPPORTED);
1743 #endif /* NX_DISABLE_IPV4 */
1744 }
1745 
1746 
1747 /**************************************************************************/
1748 /*                                                                        */
1749 /*  FUNCTION                                               RELEASE        */
1750 /*                                                                        */
1751 /*    _nxe_sntp_client_stop                               PORTABLE C      */
1752 /*                                                           6.1          */
1753 /*  AUTHOR                                                                */
1754 /*                                                                        */
1755 /*    Yuxin Zhou, Microsoft Corporation                                   */
1756 /*                                                                        */
1757 /*  DESCRIPTION                                                           */
1758 /*                                                                        */
1759 /*    This function performs error checking on the SNTP client thread stop*/
1760 /*    service.                                                            */
1761 /*                                                                        */
1762 /*  INPUT                                                                 */
1763 /*                                                                        */
1764 /*    client_ptr                           Pointer to SNTP Client instance*/
1765 /*                                                                        */
1766 /*  OUTPUT                                                                */
1767 /*                                                                        */
1768 /*    status                                Completion status             */
1769 /*                                                                        */
1770 /*  CALLS                                                                 */
1771 /*                                                                        */
1772 /*    nx_sntp_client_sto                    Actual stop SNTP service      */
1773 /*                                                                        */
1774 /*  CALLED BY                                                             */
1775 /*                                                                        */
1776 /*    Application Code                                                    */
1777 /*                                                                        */
1778 /*  RELEASE HISTORY                                                       */
1779 /*                                                                        */
1780 /*    DATE              NAME                      DESCRIPTION             */
1781 /*                                                                        */
1782 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1783 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1784 /*                                            resulting in version 6.1    */
1785 /*                                                                        */
1786 /**************************************************************************/
_nxe_sntp_client_stop(NX_SNTP_CLIENT * client_ptr)1787 UINT  _nxe_sntp_client_stop(NX_SNTP_CLIENT *client_ptr)
1788 {
1789 
1790 UINT status;
1791 
1792 
1793     /* Check for invalid pointer input.  */
1794     if (client_ptr == NX_NULL)
1795     {
1796 
1797         /* Return pointer error.  */
1798         return NX_PTR_ERROR;
1799     }
1800 
1801     status = _nx_sntp_client_stop(client_ptr);
1802 
1803     return status;
1804 }
1805 
1806 
1807 /**************************************************************************/
1808 /*                                                                        */
1809 /*  FUNCTION                                               RELEASE        */
1810 /*                                                                        */
1811 /*    _nx_sntp_client_stop                                PORTABLE C      */
1812 /*                                                           6.1          */
1813 /*  AUTHOR                                                                */
1814 /*                                                                        */
1815 /*    Yuxin Zhou, Microsoft Corporation                                   */
1816 /*                                                                        */
1817 /*  DESCRIPTION                                                           */
1818 /*                                                                        */
1819 /*    This function halts the SNTP Client thread and returns the SNTP     */
1820 /*    Client to an initial state.                                         */
1821 /*                                                                        */
1822 /*  INPUT                                                                 */
1823 /*                                                                        */
1824 /*    client_ptr                           Pointer to SNTP Client instance*/
1825 /*                                                                        */
1826 /*  OUTPUT                                                                */
1827 /*                                                                        */
1828 /*    status                                Completion status             */
1829 /*                                                                        */
1830 /*  CALLS                                                                 */
1831 /*                                                                        */
1832 /*    nx_udp_socket_unbind                  Unbind the SNTP UDP socket    */
1833 /*    tx_thread_preemption_change           Change the thread preemption  */
1834 /*    tx_thread_suspend                     Suspend SNTP processing       */
1835 /*    tx_thread_wait_abort                  Remove any thread suspension  */
1836 /*    tx_mutex_get                          Get the SNTP mutex            */
1837 /*    tx_mutex_put                          Release the SNTP mutex        */
1838 /*                                                                        */
1839 /*  CALLED BY                                                             */
1840 /*                                                                        */
1841 /*    Application Code                                                    */
1842 /*                                                                        */
1843 /*  RELEASE HISTORY                                                       */
1844 /*                                                                        */
1845 /*    DATE              NAME                      DESCRIPTION             */
1846 /*                                                                        */
1847 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1848 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1849 /*                                            resulting in version 6.1    */
1850 /*                                                                        */
1851 /**************************************************************************/
_nx_sntp_client_stop(NX_SNTP_CLIENT * client_ptr)1852 UINT  _nx_sntp_client_stop(NX_SNTP_CLIENT *client_ptr)
1853 {
1854 
1855 UINT    current_preemption;
1856 
1857 
1858     /* Get the SNTP mutex.  */
1859     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
1860 
1861     /* Determine if the SNTP client is started.  */
1862     if (client_ptr -> nx_sntp_client_started == NX_FALSE)
1863     {
1864 
1865         /* Release the SNTP mutex.  */
1866         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1867 
1868         /* SNTP client is not started so it can't be stopped.  */
1869         return(NX_SNTP_CLIENT_NOT_STARTED);
1870     }
1871 
1872     /* Clear the started flag here to ensure other threads can't issue a stop while
1873        this stop is in progress.  */
1874     client_ptr -> nx_sntp_client_started =  NX_FALSE;
1875 
1876     /* Indicate the client needs to be re-initialized to run again. */
1877     client_ptr -> nx_sntp_client_unicast_initialized = NX_FALSE;
1878     client_ptr -> nx_sntp_client_broadcast_initialized = NX_FALSE;
1879 
1880     /* Disable preemption for critical section.  */
1881     tx_thread_preemption_change(tx_thread_identify(), 0, &current_preemption);
1882 
1883     /* Loop to wait for the SNTP Client thread to be in a position to be stopped.  */
1884     while (client_ptr -> nx_sntp_client_sleep_flag != NX_TRUE)
1885     {
1886 
1887         /* Release the SNTP mutex.  */
1888         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1889 
1890         /* Sleep temporarily. */
1891         tx_thread_sleep(1);
1892 
1893         /* Get the SNTP mutex.  */
1894         tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
1895     }
1896 
1897     /* Clear the sleep flag.  */
1898     client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
1899 
1900     /* Get rid of any previous server message.  */
1901     memset(&(client_ptr -> nx_sntp_previous_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
1902 
1903     /* Get rid of the current server message if there is one.  */
1904     memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
1905 
1906     /* Deactivate SNTP update timer.  */
1907     tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
1908 
1909     /* Suspend the SNTP Client thread.  */
1910     tx_thread_suspend(&(client_ptr -> nx_sntp_client_thread));
1911 
1912     /* Abort the wait on the SNTP Client thread.  */
1913     tx_thread_wait_abort(&(client_ptr -> nx_sntp_client_thread));
1914 
1915     /* Unbind the port.  */
1916     nx_udp_socket_unbind(&(client_ptr -> nx_sntp_client_udp_socket));
1917 
1918     /* Restore preemption.  */
1919     tx_thread_preemption_change(tx_thread_identify(), current_preemption, &current_preemption);
1920 
1921     /* Release the SNTP mutex.  */
1922     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
1923 
1924     /* Return completion status.  */
1925     return(NX_SUCCESS);
1926 }
1927 
1928 
1929 /**************************************************************************/
1930 /*                                                                        */
1931 /*  FUNCTION                                               RELEASE        */
1932 /*                                                                        */
1933 /*    _nxe_sntp_client_run_broadcast                      PORTABLE C      */
1934 /*                                                           6.1          */
1935 /*  AUTHOR                                                                */
1936 /*                                                                        */
1937 /*    Yuxin Zhou, Microsoft Corporation                                   */
1938 /*                                                                        */
1939 /*  DESCRIPTION                                                           */
1940 /*                                                                        */
1941 /*    This function performs error checking on the run broadcast service. */
1942 /*                                                                        */
1943 /*   INPUT                                                                */
1944 /*                                                                        */
1945 /*    client_ptr                          Pointer to Client               */
1946 /*                                                                        */
1947 /*  OUTPUT                                                                */
1948 /*                                                                        */
1949 /*    status                              Actual completion status        */
1950 /*    NX_PTR_ERROR                        Invalid pointer input           */
1951 /*                                                                        */
1952 /*  CALLS                                                                 */
1953 /*                                                                        */
1954 /*    _nx_sntp_client_run_broadcast       Actual run broadcast service    */
1955 /*                                                                        */
1956 /*  CALLED BY                                                             */
1957 /*                                                                        */
1958 /*    Application Code                                                    */
1959 /*                                                                        */
1960 /*  RELEASE HISTORY                                                       */
1961 /*                                                                        */
1962 /*    DATE              NAME                      DESCRIPTION             */
1963 /*                                                                        */
1964 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1965 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1966 /*                                            resulting in version 6.1    */
1967 /*                                                                        */
1968 /**************************************************************************/
_nxe_sntp_client_run_broadcast(NX_SNTP_CLIENT * client_ptr)1969 UINT  _nxe_sntp_client_run_broadcast(NX_SNTP_CLIENT *client_ptr)
1970 {
1971 
1972 UINT status;
1973 
1974 
1975     /* Check for pointer error.  */
1976     if (client_ptr == NX_NULL)
1977     {
1978 
1979         /* Return error status.  */
1980         return NX_PTR_ERROR;
1981     }
1982 
1983     /* Verify this is called from thread context only.  */
1984     NX_THREADS_ONLY_CALLER_CHECKING
1985 
1986     /* Call the actual run broadcast service.  */
1987     status = _nx_sntp_client_run_broadcast(client_ptr);
1988 
1989     /* Return completion status.  */
1990     return status;
1991 }
1992 
1993 
1994 /**************************************************************************/
1995 /*                                                                        */
1996 /*  FUNCTION                                               RELEASE        */
1997 /*                                                                        */
1998 /*    _nx_sntp_client_run_broadcast                       PORTABLE C      */
1999 /*                                                           6.1          */
2000 /*  AUTHOR                                                                */
2001 /*                                                                        */
2002 /*    Yuxin Zhou, Microsoft Corporation                                   */
2003 /*                                                                        */
2004 /*  DESCRIPTION                                                           */
2005 /*                                                                        */
2006 /*    This function starts the SNTP Client for broadcast SNTP processing  */
2007 /*    by activating the SNTP timer and main processing thread. The Client */
2008 /*    is checked for being initialized for broadcast SNTP and if it is    */
2009 /*    not, the function returns an error status.                          */
2010 /*                                                                        */
2011 /*   INPUT                                                                */
2012 /*                                                                        */
2013 /*    client_ptr                       Pointer to Client                  */
2014 /*                                                                        */
2015 /*  OUTPUT                                                                */
2016 /*                                                                        */
2017 /*    NX_SNTP_CLIENT_NOT_INITIALIZED   Client initialized flag not set    */
2018 /*    NX_SNTP_CLIENT_ALREADY_STARTED   Client already started             */
2019 /*    status                           Actual completion status           */
2020 /*                                                                        */
2021 /*  CALLS                                                                 */
2022 /*                                                                        */
2023 /*    tx_timer_activate                Start the ThreadX timer            */
2024 /*    tx_thread_resume                 Resume the specified thread        */
2025 /*                                                                        */
2026 /*  CALLED BY                                                             */
2027 /*                                                                        */
2028 /*    Application Code                                                    */
2029 /*                                                                        */
2030 /*  RELEASE HISTORY                                                       */
2031 /*                                                                        */
2032 /*    DATE              NAME                      DESCRIPTION             */
2033 /*                                                                        */
2034 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2035 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2036 /*                                            resulting in version 6.1    */
2037 /*                                                                        */
2038 /**************************************************************************/
_nx_sntp_client_run_broadcast(NX_SNTP_CLIENT * client_ptr)2039 UINT  _nx_sntp_client_run_broadcast(NX_SNTP_CLIENT *client_ptr)
2040 {
2041 
2042 UINT    status;
2043 
2044 
2045     /* Get the SNTP mutex.  */
2046     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
2047 
2048     /* Determine if SNTP has already been started.  */
2049     if (client_ptr -> nx_sntp_client_started)
2050     {
2051 
2052         /* Error SNTP has already been started.  */
2053 
2054         /* Release the SNTP mutex.  */
2055         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
2056 
2057         /* Return completion status.  */
2058         return(NX_SNTP_CLIENT_ALREADY_STARTED);
2059     }
2060 
2061     /* Verify the client is ready to start receiving time data.  */
2062     if (client_ptr -> nx_sntp_client_broadcast_initialized == NX_FALSE)
2063     {
2064 
2065         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2066 
2067         /* Return error condition.  */
2068         return NX_SNTP_CLIENT_NOT_INITIALIZED;
2069     }
2070 
2071 
2072     /* Set the maximum timeout to the full count.  */
2073     client_ptr -> nx_sntp_update_time_remaining = (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE);
2074 
2075     /* Activate the SNTP update timer.  */
2076     status = tx_timer_activate(&(client_ptr -> nx_sntp_update_timer));
2077 
2078     /* Check for error. Ignore timer is already active error.  */
2079     if (status != TX_SUCCESS && status != TX_ACTIVATE_ERROR)
2080     {
2081 
2082         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2083 
2084         /* Return the error condition.  */
2085         return status;
2086     }
2087 
2088     /* Bind the UDP socket to the IP port.  */
2089     status =  nx_udp_socket_bind(&(client_ptr -> nx_sntp_client_udp_socket), NX_SNTP_CLIENT_UDP_PORT, NX_WAIT_FOREVER);
2090 
2091     /* Check for error. */
2092     if (status != NX_SUCCESS)
2093     {
2094 
2095         /* Deactivate SNTP update timer.  */
2096         tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
2097 
2098         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
2099 
2100         return status;
2101     }
2102 
2103     /* Set status that the first update is expected. */
2104     client_ptr -> nx_sntp_client_first_update_pending = NX_TRUE;
2105 
2106     status = tx_thread_resume(&(client_ptr -> nx_sntp_client_thread));
2107 
2108     if (status != NX_SUCCESS)
2109     {
2110 
2111         /* Release the socket port. */
2112         nx_udp_socket_unbind(&(client_ptr -> nx_sntp_client_udp_socket));
2113 
2114         /* Deactivate SNTP update timer.  */
2115         tx_timer_deactivate(&(client_ptr -> nx_sntp_update_timer));
2116 
2117         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2118 
2119         return status;
2120     }
2121 
2122     /* Clear the sleep flag.  */
2123     client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
2124 
2125     client_ptr -> nx_sntp_client_started = NX_TRUE;
2126 
2127     tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2128 
2129     return NX_SUCCESS;
2130 }
2131 
2132 
2133 /**************************************************************************/
2134 /*                                                                        */
2135 /*  FUNCTION                                               RELEASE        */
2136 /*                                                                        */
2137 /*    _nx_sntp_client_process_broadcast                   PORTABLE C      */
2138 /*                                                           6.1          */
2139 /*  AUTHOR                                                                */
2140 /*                                                                        */
2141 /*    Yuxin Zhou, Microsoft Corporation                                   */
2142 /*                                                                        */
2143 /*  DESCRIPTION                                                           */
2144 /*                                                                        */
2145 /*   This function checks if the SNTP client has received a packet, and if*/
2146 /*   so processes it for valid SNTP data and resets the timeouts          */
2147 /*   for receiving the next update.                                       */
2148 /*                                                                        */
2149 /*   If the invalid packet update count exceeds the maximum allowed       */
2150 /*   updates, or no valid packet is received within the maximum interval, */
2151 /*   an error flag is set, and it is up to the host application to change */
2152 /*   its broadcast SNTP server.                                           */
2153 /*                                                                        */
2154 /*   INPUT                                                                */
2155 /*                                                                        */
2156 /*    client_ptr                       Pointer to Client                  */
2157 /*                                                                        */
2158 /*  OUTPUT                                                                */
2159 /*                                                                        */
2160 /*    None                                                                */
2161 /*                                                                        */
2162 /*  CALLS                                                                 */
2163 /*                                                                        */
2164 /*    _nx_sntp_client_reset_current_time_message                          */
2165 /*                                    Save time update before next update */
2166 /*    _nx_sntp_client_receive_time_update                                 */
2167 /*                                    Receive server update packets       */
2168 /*    _nx_sntp_client_process_time_data                                   */
2169 /*                                    Process time data in server update  */
2170 /*                                                                        */
2171 /*  CALLED BY                                                             */
2172 /*                                                                        */
2173 /*    Application Code                                                    */
2174 /*                                                                        */
2175 /*  RELEASE HISTORY                                                       */
2176 /*                                                                        */
2177 /*    DATE              NAME                      DESCRIPTION             */
2178 /*                                                                        */
2179 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2180 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2181 /*                                            resulting in version 6.1    */
2182 /*                                                                        */
2183 /**************************************************************************/
_nx_sntp_client_process_broadcast(NX_SNTP_CLIENT * client_ptr)2184 VOID _nx_sntp_client_process_broadcast(NX_SNTP_CLIENT *client_ptr)
2185 {
2186 
2187 UINT  status;
2188 ULONG sntp_events;
2189 
2190 
2191     /* Check for a receive event. */
2192     status = tx_event_flags_get(&nx_sntp_client_events, NX_SNTP_CLIENT_RECEIVE_EVENT, TX_OR_CLEAR, &sntp_events, TX_NO_WAIT);
2193 
2194     if (status == NX_SUCCESS)
2195     {
2196 
2197         /* Save this server time update before receiving the next server time update.  */
2198         _nx_sntp_client_reset_current_time_message(client_ptr);
2199 
2200         /* Listen for a server update packet.  */
2201         status = _nx_sntp_client_receive_time_update(client_ptr,  TX_NO_WAIT);
2202 
2203         if (status == NX_SUCCESS)
2204         {
2205 
2206             /* Process the server update packet and apply to local time if valid.  */
2207             status =  _nx_sntp_client_process_update_packet(client_ptr);
2208 
2209             /* Check for error. */
2210             if (status != NX_SUCCESS)
2211             {
2212 
2213                 /* Have we exceeded the max number of invalid or missed updates from this server? */
2214                 if (client_ptr -> nx_sntp_client_invalid_time_updates > NX_SNTP_CLIENT_INVALID_UPDATE_LIMIT)
2215                 {
2216 
2217                         /* Yes, set the server status as no longer valid. */
2218                         client_ptr -> nx_sntp_valid_server_status = NX_FALSE;
2219                 }
2220 
2221                 return;
2222             }
2223 
2224             /* Reset the Client timeout for receiving broadcast updates, zero out invalid update count.  */
2225             client_ptr -> nx_sntp_update_time_remaining = (NX_SNTP_CLIENT_MAX_TIME_LAPSE * NX_IP_PERIODIC_RATE);
2226 
2227             client_ptr -> nx_sntp_client_invalid_time_updates = 0;
2228 
2229             /* Set the server status as good (receiving updates). */
2230             client_ptr -> nx_sntp_valid_server_status = NX_TRUE;
2231 
2232             /* Indicate the client has received at least one valid time update with the current server. */
2233             client_ptr -> nx_sntp_client_first_update_pending = NX_FALSE;
2234 
2235             return;
2236         }
2237     }
2238 
2239     /* Has the timeout for receiving the next time update expired? */
2240     if (client_ptr -> nx_sntp_update_time_remaining == 0)
2241     {
2242 
2243         /* Yes, set the server status as no longer valid. */
2244         client_ptr -> nx_sntp_valid_server_status = NX_FALSE;
2245     }
2246 
2247     /* Nothing to do but wait...*/
2248     return;
2249 }
2250 
2251 
2252 /**************************************************************************/
2253 /*                                                                        */
2254 /*  FUNCTION                                               RELEASE        */
2255 /*                                                                        */
2256 /*    _nx_sntp_client_send_unicast_request                PORTABLE C      */
2257 /*                                                           6.1          */
2258 /*  AUTHOR                                                                */
2259 /*                                                                        */
2260 /*    Yuxin Zhou, Microsoft Corporation                                   */
2261 /*                                                                        */
2262 /*  DESCRIPTION                                                           */
2263 /*                                                                        */
2264 /*    This function allocates a packet from the Client packet pool,creates*/
2265 /*    a time request time message, transfers the request message into the */
2266 /*    packet buffer, and sends the packet via the Client UDP socket.  It  */
2267 /*    then releases the packet back to the packet pool.                   */
2268 /*                                                                        */
2269 /*   INPUT                                                                */
2270 /*                                                                        */
2271 /*    client_ptr                       Pointer to Client                  */
2272 /*                                                                        */
2273 /*  OUTPUT                                                                */
2274 /*                                                                        */
2275 /*    status                           Actual completion status           */
2276 /*                                                                        */
2277 /*  CALLS                                                                 */
2278 /*                                                                        */
2279 /*    memset                          Clear specified area of memory      */
2280 /*    nx_packet_allocate              Allocate packet from packet pool    */
2281 /*    nx_packet_release               Release packet back to packet pool  */
2282 /*    nx_udp_socket_send              Transmit packet via UDP socket      */
2283 /*    _nx_sntp_client_utility_convert_time_to_UCHAR                       */
2284 /*                                    Copy NX_SNTP_TIME data into a       */
2285 /*                                          UCHAR[4] time stamp field     */
2286 /*    _nx_sntp_client_create_time_request_packet                          */
2287 /*                                    Create packet with time request data*/
2288 /*                                                                        */
2289 /*  CALLED BY                                                             */
2290 /*                                                                        */
2291 /*    _nx_sntp_client_run_unicast   Send and receive unicast time data    */
2292 /*                                                                        */
2293 /*  RELEASE HISTORY                                                       */
2294 /*                                                                        */
2295 /*    DATE              NAME                      DESCRIPTION             */
2296 /*                                                                        */
2297 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2298 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2299 /*                                            resulting in version 6.1    */
2300 /*                                                                        */
2301 /**************************************************************************/
_nx_sntp_client_send_unicast_request(NX_SNTP_CLIENT * client_ptr)2302 UINT  _nx_sntp_client_send_unicast_request(NX_SNTP_CLIENT *client_ptr)
2303 {
2304 
2305 NX_PACKET   *packet_ptr;
2306 UINT        status;
2307 NX_SNTP_TIME_MESSAGE *unicast_request;
2308 NX_SNTP_TIME local_time;
2309 
2310 
2311     /* Lock access to the SNTP Client while we create a unicast request. */
2312     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
2313 
2314     unicast_request = &(client_ptr -> nx_sntp_current_time_message_request);
2315 
2316     /* Clear the time request.  */
2317     memset(unicast_request, 0, sizeof(NX_SNTP_TIME_MESSAGE));
2318 
2319     /* Add client version to the time request flags.  */
2320     unicast_request -> flags = NX_SNTP_CLIENT_NTP_VERSION << 3;
2321 
2322     /* Set the Client association (mode) in the last three bits of the flag field.  */
2323     unicast_request -> flags |= PROTOCOL_MODE_CLIENT;
2324 
2325     /* Release the mutex before a potentially blocking call. */
2326     tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2327 
2328     /* Allocate a packet from the Client pool.  */
2329     status =  nx_packet_allocate(client_ptr -> nx_sntp_client_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_SNTP_CLIENT_PACKET_TIMEOUT);
2330 
2331     /* Check for error.  */
2332     if (status != NX_SUCCESS)
2333     {
2334 
2335         /* Return error status.  */
2336         return status;
2337     }
2338 
2339     /* Reacquire the lock to SNTP Client while we process request. */
2340     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
2341 
2342     /* Check for minimal packet size requirement. */
2343 
2344 
2345     /* IPv6 packets require more space for the IPv6 header. */
2346     if (client_ptr -> nx_sntp_server_ip_address.nxd_ip_version == NX_IP_VERSION_V6)
2347     {
2348 
2349 #ifndef FEATURE_NX_IPV6
2350         nx_packet_release(packet_ptr);
2351 
2352         /* Release the mutex. */
2353         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2354 
2355         return NX_SNTP_INVALID_IP_ADDRESS;
2356 #else
2357 
2358         if  (client_ptr -> nx_sntp_client_packet_pool_ptr -> nx_packet_pool_payload_size <
2359                 (sizeof(NX_IPV6_HEADER) + sizeof(NX_UDP_HEADER) + NX_SNTP_CLIENT_PACKET_DATA_SIZE))
2360         {
2361 
2362             nx_packet_release(packet_ptr);
2363 
2364             /* Release the mutex. */
2365             tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2366 
2367             return NX_SNTP_INSUFFICIENT_PACKET_PAYLOAD;
2368         }
2369 #endif /* FEATURE_NX_IPV6 */
2370     }
2371     else  /* IPv4 */
2372     {
2373 
2374 #ifdef NX_DISABLE_IPV4
2375         nx_packet_release(packet_ptr);
2376 
2377         /* Release the mutex. */
2378         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2379 
2380         return NX_SNTP_INVALID_IP_ADDRESS;
2381 #else
2382 
2383         if  (client_ptr -> nx_sntp_client_packet_pool_ptr -> nx_packet_pool_payload_size <
2384                 (sizeof(NX_IPV4_HEADER) + sizeof(NX_UDP_HEADER) + NX_SNTP_CLIENT_PACKET_DATA_SIZE))
2385         {
2386 
2387             nx_packet_release(packet_ptr);
2388 
2389             /* Release the mutex. */
2390             tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2391 
2392             return NX_SNTP_INSUFFICIENT_PACKET_PAYLOAD;
2393         }
2394 #endif /* NX_DISABLE_IPV4 */
2395     }
2396 
2397 
2398     /* Convert the local time into the request's transmit time stamp field.  */
2399     local_time.seconds = client_ptr -> nx_sntp_client_local_ntp_time.seconds +
2400         client_ptr -> nx_sntp_client_local_ntp_time_elapsed;
2401     local_time.fraction = client_ptr -> nx_sntp_client_local_ntp_time.fraction;
2402     _nx_sntp_client_utility_convert_time_to_UCHAR(&local_time, unicast_request,  TRANSMIT_TIME);
2403 
2404     /* Create the request packet with the unicast request message.  */
2405     status = _nx_sntp_client_create_time_request_packet(client_ptr, packet_ptr, unicast_request);
2406 
2407     /* Check for error.  */
2408     if (status != NX_SUCCESS)
2409     {
2410 
2411         /* Release the packet.  */
2412         nx_packet_release(packet_ptr);
2413 
2414 
2415         /* Release the mutex. */
2416         tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2417 
2418         /* Return error status.  */
2419         return status;
2420     }
2421 
2422     /* Release the lock. we're done with the SNTP Client data. */
2423     tx_mutex_put(&client_ptr -> nx_sntp_client_mutex);
2424 
2425     /* Send the time request packet.  */
2426     status =  nxd_udp_socket_send(&(client_ptr -> nx_sntp_client_udp_socket), packet_ptr, &client_ptr -> nx_sntp_server_ip_address, NX_SNTP_SERVER_UDP_PORT);
2427 
2428 
2429     /* Check for error.  */
2430     if (status != NX_SUCCESS)
2431     {
2432 
2433         /* Release the packet.  */
2434         nx_packet_release(packet_ptr);
2435 
2436         return status;
2437     }
2438 
2439     send_timerticks = tx_time_get();
2440 
2441     /* Return completion status.  */
2442     return status;
2443 }
2444 
2445 
2446 /**************************************************************************/
2447 /*                                                                        */
2448 /*  FUNCTION                                               RELEASE        */
2449 /*                                                                        */
2450 /*    _nx_sntp_client_receive_time_update                 PORTABLE C      */
2451 /*                                                           6.3.0        */
2452 /*  AUTHOR                                                                */
2453 /*                                                                        */
2454 /*    Yuxin Zhou, Microsoft Corporation                                   */
2455 /*                                                                        */
2456 /*  DESCRIPTION                                                           */
2457 /*                                                                        */
2458 /*    This function receives UDP data on the Client socket with specified */
2459 /*    wait (timeout option).  Received packets are checked for valid      */
2460 /*    and sender IP and port.  Packet data is then extracted and stored   */
2461 /*    in the specified time message. The packet is released regardless of */
2462 /*    validity of packet received.                                        */
2463 /*                                                                        */
2464 /*   INPUT                                                                */
2465 /*                                                                        */
2466 /*    client_ptr                        Pointer to Client                 */
2467 /*    timeout                           Wait option to receive packet     */
2468 /*                                                                        */
2469 /*  OUTPUT                                                                */
2470 /*    status                            Actual completion status          */
2471 /*                                                                        */
2472 /*  CALLS                                                                 */
2473 /*                                                                        */
2474 /*    nx_udp_socket_receive             Listen for packets on UDP socket  */
2475 /*    nx_packet_release                 Release packet back to packet pool*/
2476 /*    tx_mutex_get                      Obtain exclusive lock on list     */
2477 /*    memset                            Clear specified area of memory    */
2478 /*    _nx_sntp_client_add_server_ULONG_to_list                            */
2479 /*                                      Add sender address to Client list */
2480 /*    _nx_sntp_client_utility_convert_LONG_to_IP                          */
2481 /*                                     Convert IP to string for display   */
2482 /*    _nx_sntp_client_extract_time_message_from_packet                    */
2483 /*                                     Extract packet data to time message*/
2484 /*                                                                        */
2485 /*  CALLED BY                                                             */
2486 /*                                                                        */
2487 /*    _nx_sntp_client_run_unicast     Send and receive server time updates*/
2488 /*    _nx_sntp_client_run_broadcast   Listen for server update broadcasts */
2489 /*                                                                        */
2490 /*  RELEASE HISTORY                                                       */
2491 /*                                                                        */
2492 /*    DATE              NAME                      DESCRIPTION             */
2493 /*                                                                        */
2494 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2495 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2496 /*                                            added support for disabling */
2497 /*                                            message check,              */
2498 /*                                            resulting in version 6.1    */
2499 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
2500 /*                                            corrected the port check,   */
2501 /*                                            resulting in version 6.1.12 */
2502 /*  10-31-2023     Tiejun Zhou              Modified comment(s), and      */
2503 /*                                            fixed packet chain issue,   */
2504 /*                                            resulting in version 6.3.0  */
2505 /*                                                                        */
2506 /**************************************************************************/
_nx_sntp_client_receive_time_update(NX_SNTP_CLIENT * client_ptr,ULONG timeout)2507 UINT  _nx_sntp_client_receive_time_update(NX_SNTP_CLIENT *client_ptr, ULONG timeout)
2508 {
2509 
2510 UINT            status;
2511 UINT            length;
2512 NX_PACKET       *receive_packet;
2513 #ifndef NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE
2514 UINT            sender_port;
2515 NX_UDP_HEADER   *udp_header_ptr;
2516 NXD_ADDRESS     source_ip_address, destination_ip_address;
2517 #endif /* NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE */
2518 
2519     /* Loop to receive packets. */
2520     for(;;)
2521     {
2522 
2523         /* Indicate the SNTP Client can be stopped while the SNTP client waits for a packet.  */
2524         client_ptr -> nx_sntp_client_sleep_flag =  NX_TRUE;
2525 
2526         /* Wait to receive packets on the Client UDP socket.  */
2527         status = nx_udp_socket_receive(&(client_ptr -> nx_sntp_client_udp_socket), &receive_packet, timeout * NX_IP_PERIODIC_RATE);
2528 
2529         /* Indicate the SNTP Client can not be stopped.  */
2530         client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
2531 
2532         /* Check for error.  */
2533         if (status != NX_SUCCESS)
2534         {
2535 
2536             /* Return error status.  */
2537             return status;
2538         }
2539 
2540 #ifndef NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE
2541         /* Check the sender port in the UDP packet header.  */
2542         udp_header_ptr = (NX_UDP_HEADER *)(receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER));
2543         sender_port = (UINT)udp_header_ptr -> nx_udp_header_word_0 >> NX_SHIFT_BY_16;
2544 
2545         /* Check if this is the server port the Client expects.  */
2546         if (sender_port != NX_SNTP_SERVER_UDP_PORT)
2547         {
2548 
2549             /* No, reject the packet.  */
2550             nx_packet_release(receive_packet);
2551 
2552             continue;
2553         }
2554 
2555 
2556         /* If this an IPv6 packet? An SNTP client with an IPv6 SNTP server will only accept IPv6 packets.   */
2557         if ((receive_packet -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
2558             (client_ptr -> nx_sntp_server_ip_address.nxd_ip_version == NX_IP_VERSION_V6))
2559         {
2560 
2561 #ifndef FEATURE_NX_IPV6
2562             nx_packet_release(receive_packet);
2563             continue;
2564 #else
2565             NX_IPV6_HEADER *ipv6_header_ptr;
2566 
2567             /* Pick up the IPv6 header from the packet. */
2568             ipv6_header_ptr =  (NX_IPV6_HEADER *) (receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV6_HEADER));
2569 
2570             /* Copy sender address into a local variable. */
2571             COPY_IPV6_ADDRESS(ipv6_header_ptr -> nx_ip_header_source_ip, &(source_ip_address.nxd_ip_address.v6[0]));
2572             source_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
2573 
2574             /* Copy destination address into a local variable. */
2575             COPY_IPV6_ADDRESS(ipv6_header_ptr -> nx_ip_header_destination_ip, &(destination_ip_address.nxd_ip_address.v6[0]));
2576             destination_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
2577 
2578             if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
2579             {
2580 
2581                 /* Does the source address match the expected server address?  */
2582                 if (!CHECK_IPV6_ADDRESSES_SAME(&client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v6[0], &source_ip_address.nxd_ip_address.v6[0]))
2583                 {
2584 
2585                     /* No further need for the receive packet. Release back to the client pool.  */
2586                     nx_packet_release(receive_packet);
2587 
2588                     /* Set update time to null.  */
2589                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2590 
2591                     continue;
2592                 }
2593             }
2594             else /* Multicast mode */
2595             {
2596 
2597                 /* Define the all hosts multicast address. */
2598                 NXD_ADDRESS All_Hosts_Multicast;
2599                 All_Hosts_Multicast.nxd_ip_version = NX_IP_VERSION_V6;
2600                 All_Hosts_Multicast.nxd_ip_address.v6[0] = 0xff020000;
2601                 All_Hosts_Multicast.nxd_ip_address.v6[1] = 0x00000000;
2602                 All_Hosts_Multicast.nxd_ip_address.v6[2] = 0x00000000;
2603                 All_Hosts_Multicast.nxd_ip_address.v6[3] = 0x00000001;
2604 
2605                 /* Does the source address match the expected server address )?  */
2606                 if (!CHECK_IPV6_ADDRESSES_SAME(&client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v6[0], &source_ip_address.nxd_ip_address.v6[0]))
2607                 {
2608 
2609                     /* No further need for the receive packet. Release back to the client pool.  */
2610                     nx_packet_release(receive_packet);
2611 
2612                     /* Set update time to null.  */
2613                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2614 
2615                     continue;
2616                 }
2617 
2618                 /* Does the destination address match the expected server address (all hosts address FF02::1)?  */
2619                 if (!CHECK_IPV6_ADDRESSES_SAME(&destination_ip_address.nxd_ip_address.v6[0], &All_Hosts_Multicast.nxd_ip_address.v6[0]))
2620                 {
2621 
2622                     /* No further need for the receive packet. Release back to the client pool.  */
2623                     nx_packet_release(receive_packet);
2624 
2625                     /* Set update time to null.  */
2626                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2627 
2628                     continue;
2629                 }
2630 
2631             }
2632 #endif  /* FEATURE_NX_IPV6 */
2633 
2634         }
2635         /* Otherwise is this an IPv4 packet and is the SNTP client set for IPv4? */
2636         else if ((receive_packet -> nx_packet_ip_version == NX_IP_VERSION_V4) &&
2637                  (client_ptr -> nx_sntp_server_ip_address.nxd_ip_version == NX_IP_VERSION_V4))
2638         {
2639 #ifdef NX_DISABLE_IPV4
2640             nx_packet_release(receive_packet);
2641             continue;
2642 #else
2643 
2644             NX_IPV4_HEADER *ipv4_header_ptr;
2645 
2646             ipv4_header_ptr =  (NX_IPV4_HEADER *) (receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV4_HEADER));
2647 
2648             /* Copy into a local variable. */
2649             source_ip_address.nxd_ip_address.v4 =  ipv4_header_ptr -> nx_ip_header_source_ip;
2650             source_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
2651 
2652             /* Copy into a local variable. */
2653             destination_ip_address.nxd_ip_address.v4 =  ipv4_header_ptr -> nx_ip_header_destination_ip;
2654             destination_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
2655 
2656             if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
2657             {
2658                 /* Compare the sender address with the Client's current sntp server. */
2659                 if (source_ip_address.nxd_ip_address.v4 != client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4)
2660                 {
2661                     /* This is an untrusted server or the client had a broadcast server already,
2662                        reject this packet and return an error condition.  */
2663 
2664                     /* No further need for the receive packet. Release back to the client pool.  */
2665                     nx_packet_release(receive_packet);
2666 
2667                     continue;
2668                 }
2669             }
2670             else /* BROADCAST_MODE */
2671             {
2672 
2673                 ULONG network_mask;
2674                 UINT  iface_index;
2675 
2676                 /* Compare the sender address with the Client's current sntp server. */
2677                 if (source_ip_address.nxd_ip_address.v4 != client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4)
2678                 {
2679 
2680                     /* This is an untrusted server or the client had a broadcast server already,
2681                        reject this packet and return an error condition.  */
2682 
2683                     /* No further need for the receive packet. Release back to the client pool.  */
2684                     nx_packet_release(receive_packet);
2685 
2686                     continue;
2687                 }
2688 
2689                 /* Set a local variable on the SNTP network index. */
2690                 iface_index = client_ptr -> nx_sntp_client_interface_index;
2691 
2692                 /* Set a local variable to the network mask. */
2693                 network_mask = client_ptr -> nx_sntp_client_ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_network_mask;
2694 
2695                 /* Now verify this is a broadcast packet. */
2696                 if ((destination_ip_address.nxd_ip_address.v4 & ~network_mask) != ~network_mask)
2697                 {
2698                     /* This is not a broadcast packet on the local network.  */
2699 
2700                     /* No further need for the receive packet. Release back to the client pool.  */
2701                     nx_packet_release(receive_packet);
2702 
2703                     continue;
2704                 }
2705             }
2706 #endif /* NX_DISABLE_IPV4 */
2707         }
2708         else
2709         {
2710             /* Not interested, discard the packet. */
2711             nx_packet_release(receive_packet);
2712 
2713             continue;
2714         }
2715 
2716 #endif /* NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE */
2717 
2718         /* Check that the packet has the proper length for an NTP message.  */
2719         length = receive_packet -> nx_packet_length;
2720 
2721         /* Verify the packet data contains at least the minimum time update data,
2722            but no more than the max size with authentication data appended.  */
2723 
2724         if ((length < NX_SNTP_TIME_MESSAGE_MIN_SIZE) || (length > NX_SNTP_TIME_MESSAGE_MAX_SIZE))
2725         {
2726 
2727             /* No further need for the receive packet. Release back to the client pool.  */
2728             nx_packet_release(receive_packet);
2729 
2730             continue;
2731         }
2732 
2733 #ifndef NX_DISABLE_PACKET_CHAIN
2734         /* Ignore packet chain.  */
2735         if (receive_packet -> nx_packet_next)
2736         {
2737 
2738             /* No further need for the receive packet. Release back to the client pool.  */
2739             nx_packet_release(receive_packet);
2740 
2741             continue;
2742         }
2743 #endif /* NX_DISABLE_PACKET_CHAIN */
2744 
2745         memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2746 
2747         /* Extract time message data from packet data into time message.  */
2748         _nx_sntp_client_extract_time_message_from_packet(client_ptr, receive_packet);
2749 
2750         /* No further need for the receive packet. Release back to the client pool.  */
2751         nx_packet_release(receive_packet);
2752 
2753         return NX_SUCCESS;
2754     }
2755 }
2756 
2757 
2758 /**************************************************************************/
2759 /*                                                                        */
2760 /*  FUNCTION                                               RELEASE        */
2761 /*                                                                        */
2762 /*    _nx_sntp_client_extract_time_message_from_packet    PORTABLE C      */
2763 /*                                                           6.1.10       */
2764 /*  AUTHOR                                                                */
2765 /*                                                                        */
2766 /*    Yuxin Zhou, Microsoft Corporation                                   */
2767 /*                                                                        */
2768 /*  DESCRIPTION                                                           */
2769 /*                                                                        */
2770 /*    This function extracts time data from an SNTP  server packet and    */
2771 /*    copies the information into the specified time message buffer.      */
2772 /*                                                                        */
2773 /*   INPUT                                                                */
2774 /*                                                                        */
2775 /*    client_ptr                          Pointer to SNTP Client          */
2776 /*    packet_ptr                          Pointer to server packet        */
2777 /*                                                                        */
2778 /*  OUTPUT                                                                */
2779 /*                                                                        */
2780 /*    NX_SUCCESS                          Successful completion status    */
2781 /*                                                                        */
2782 /*  CALLS                                                                 */
2783 /*                                                                        */
2784 /*    memcpy                              Copy data to area of memory     */
2785 /*                                                                        */
2786 /*  CALLED BY                                                             */
2787 /*                                                                        */
2788 /*    _nx_sntp_client_receive_time_update Process SNTP server packets     */
2789 /*                                                                        */
2790 /*  RELEASE HISTORY                                                       */
2791 /*                                                                        */
2792 /*    DATE              NAME                      DESCRIPTION             */
2793 /*                                                                        */
2794 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2795 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2796 /*                                            verified memcpy use cases,  */
2797 /*                                            resulting in version 6.1    */
2798 /*  01-31-2022     Yuxin Zhou               Modified comment(s), corrected*/
2799 /*                                            the Reference Identifier,  */
2800 /*                                            resulting in version 6.1.10 */
2801 /*                                                                        */
2802 /**************************************************************************/
_nx_sntp_client_extract_time_message_from_packet(NX_SNTP_CLIENT * client_ptr,NX_PACKET * packet_ptr)2803 UINT  _nx_sntp_client_extract_time_message_from_packet(NX_SNTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
2804 {
2805 
2806 ULONG   *ntp_word_0;
2807 NX_SNTP_TIME_MESSAGE *time_message_ptr;
2808 
2809 
2810     time_message_ptr = &(client_ptr -> nx_sntp_current_server_time_message);
2811 
2812     process_timerticks = tx_time_get();
2813 
2814     memset(time_message_ptr, 0, sizeof(NX_SNTP_TIME_MESSAGE));
2815 
2816     /* Pickup the pointer to the head of the UDP packet.  */
2817     ntp_word_0 = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
2818     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2819 
2820     /* Extract fields from the first 32 bits of the time message.  */
2821     time_message_ptr -> flags = (*ntp_word_0 & 0xFF000000UL) >> 24;
2822 
2823     time_message_ptr -> peer_clock_stratum = (*ntp_word_0 & 0x00FF0000UL) >> 16;
2824 
2825     time_message_ptr -> peer_poll_interval = (*ntp_word_0 & 0x0000FF00UL) >> 8;
2826 
2827     time_message_ptr -> peer_clock_precision =  (*ntp_word_0 & 0x00000000FFUL);
2828 
2829     /* Advance to the next 32 bit field and extract the root delay field.  */
2830     ntp_word_0++;
2831     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2832 
2833     time_message_ptr -> root_delay = (ULONG)(*ntp_word_0);
2834 
2835     /* Advance to the next 32 bit field and extract the clock dispersion field.  */
2836     ntp_word_0++;
2837     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2838 
2839     time_message_ptr -> clock_dispersion= *ntp_word_0;
2840 
2841     /* Advance to the next 32 bit field and extract the reference clock ID field.  */
2842     ntp_word_0++;
2843     memcpy(time_message_ptr -> reference_clock_id, ntp_word_0, 4); /* Use case of memcpy is verified. */
2844 
2845     /* Advance to the next field (64 bit field) and extract the reference time stamp field.  */
2846     ntp_word_0++;
2847     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2848     time_message_ptr -> reference_clock_update_time_stamp[0] = *ntp_word_0;
2849 
2850     ntp_word_0++;
2851     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2852     time_message_ptr -> reference_clock_update_time_stamp[1] = *ntp_word_0;
2853 
2854     /* If a non zero reference time was supplied, separate out seconds and fraction.  */
2855     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> reference_clock_update_time_stamp), 8) == NX_FALSE)
2856     {
2857 
2858         time_message_ptr -> reference_clock_update_time.seconds = time_message_ptr -> reference_clock_update_time_stamp[0];
2859 
2860         time_message_ptr -> reference_clock_update_time.fraction = time_message_ptr -> reference_clock_update_time_stamp[1];
2861     }
2862 
2863     /* Copy the first 32 bits into the originate time stamp seconds field. */
2864     ntp_word_0++;
2865     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2866     time_message_ptr -> originate_time_stamp[0] = *ntp_word_0;
2867 
2868     /* Copy the next 32 bits into the originate time stamp fraction field. */
2869     ntp_word_0++;
2870     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2871     time_message_ptr -> originate_time_stamp[1] = *ntp_word_0;
2872 
2873     /* If an originate time was supplied, separate out seconds and fraction.  */
2874     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> originate_time_stamp), 8) == NX_FALSE)
2875     {
2876 
2877         time_message_ptr -> originate_time.seconds = time_message_ptr -> originate_time_stamp[0];
2878 
2879         time_message_ptr -> originate_time.fraction = time_message_ptr -> originate_time_stamp[1];
2880     }
2881 
2882 
2883     /* Copy the first 32 bits into the receive time stamp seconds field. */
2884     ntp_word_0++;
2885     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2886     time_message_ptr -> receive_time_stamp[0] = *ntp_word_0;
2887 
2888     /* Copy the next 32 bits into the receive time stamp fraction field. */
2889     ntp_word_0++;
2890     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2891     time_message_ptr -> receive_time_stamp[1] = *ntp_word_0;
2892 
2893     /* If an receive time was supplied, separate out seconds and fraction.  */
2894     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> receive_time_stamp), 8) == NX_FALSE)
2895     {
2896 
2897         time_message_ptr -> receive_time.seconds = time_message_ptr -> receive_time_stamp[0];
2898         time_message_ptr -> receive_time.fraction = time_message_ptr -> receive_time_stamp[1];
2899     }
2900 
2901     /* Copy the first 32 bits into the transmit time stamp seconds field. */
2902     ntp_word_0++;
2903     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2904     time_message_ptr -> transmit_time_stamp[0] = *ntp_word_0;
2905 
2906     /* Copy the next 32 bits into the transmit time stamp fraction field. */
2907     ntp_word_0++;
2908     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2909     time_message_ptr -> transmit_time_stamp[1] = *ntp_word_0;
2910 
2911     /* If an transmit time was supplied, separate out seconds and fraction.  */
2912     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> transmit_time_stamp), 8) == NX_FALSE)
2913     {
2914 
2915         time_message_ptr -> transmit_time.seconds = time_message_ptr -> transmit_time_stamp[0];
2916 
2917         time_message_ptr -> transmit_time.fraction = time_message_ptr -> transmit_time_stamp[1];
2918 
2919     }
2920 
2921     /* Return completion status.  */
2922     return NX_SUCCESS;
2923 }
2924 
2925 
2926 /**************************************************************************/
2927 /*                                                                        */
2928 /*  FUNCTION                                               RELEASE        */
2929 /*                                                                        */
2930 /*    _nx_sntp_client_reset_current_time_message          PORTABLE C      */
2931 /*                                                           6.1          */
2932 /*  AUTHOR                                                                */
2933 /*                                                                        */
2934 /*    Yuxin Zhou, Microsoft Corporation                                   */
2935 /*                                                                        */
2936 /*  DESCRIPTION                                                           */
2937 /*                                                                        */
2938 /*    This function saves the current time message from the server to     */
2939 /*    the previous time message field, and clears the current time message*/
2940 /*    field.                                                              */
2941 /*                                                                        */
2942 /*   INPUT                                                                */
2943 /*                                                                        */
2944 /*    client_ptr                          Pointer to Client               */
2945 /*                                                                        */
2946 /*  OUTPUT                                                                */
2947 /*                                                                        */
2948 /*    NX_SUCCESS                          Successful completion status    */
2949 /*                                                                        */
2950 /*  CALLS                                                                 */
2951 /*                                                                        */
2952 /*    memset                              Clear specified area of memory  */
2953 /*    memcpy                              Copy data to area of memory     */
2954 /*                                                                        */
2955 /*  CALLED BY                                                             */
2956 /*                                                                        */
2957 /*    _nx_sntp_client_receive_time_update Process received update packets */
2958 /*                                                                        */
2959 /*  RELEASE HISTORY                                                       */
2960 /*                                                                        */
2961 /*    DATE              NAME                      DESCRIPTION             */
2962 /*                                                                        */
2963 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2964 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2965 /*                                            verified memcpy use cases,  */
2966 /*                                            resulting in version 6.1    */
2967 /*                                                                        */
2968 /**************************************************************************/
_nx_sntp_client_reset_current_time_message(NX_SNTP_CLIENT * client_ptr)2969 UINT  _nx_sntp_client_reset_current_time_message(NX_SNTP_CLIENT *client_ptr)
2970 {
2971 
2972     /* Does the client have a non NULL current server time update?  */
2973     if (client_ptr -> nx_sntp_current_server_time_message.flags)
2974     {
2975 
2976         /* Yes, copy to the previous time update.  */
2977         memcpy(&client_ptr -> nx_sntp_previous_server_time_message, &client_ptr -> nx_sntp_current_server_time_message, sizeof(NX_SNTP_TIME_MESSAGE)); /* Use case of memcpy is verified. */
2978 
2979         /* Clear the current time update data.  */
2980         memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2981 
2982     }
2983 
2984     /* Clear the current time update request.  */
2985     memset(&(client_ptr -> nx_sntp_current_time_message_request), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2986 
2987     return NX_SUCCESS;
2988 }
2989 
2990 
2991 /**************************************************************************/
2992 /*                                                                        */
2993 /*  FUNCTION                                               RELEASE        */
2994 /*                                                                        */
2995 /*    _nx_sntp_client_process_update_packet               PORTABLE C      */
2996 /*                                                           6.1          */
2997 /*  AUTHOR                                                                */
2998 /*                                                                        */
2999 /*    Yuxin Zhou, Microsoft Corporation                                   */
3000 /*                                                                        */
3001 /*  DESCRIPTION                                                           */
3002 /*                                                                        */
3003 /*    This function processes SNTP time data received in a server update  */
3004 /*    packet, applies sanity checks, calculates round trip time, and      */
3005 /*    updates the Client time with the SNTP server time.                  */
3006 /*                                                                        */
3007 /*   INPUT                                                                */
3008 /*                                                                        */
3009 /*    client_ptr                          Pointer to Client               */
3010 /*                                                                        */
3011 /*  OUTPUT                                                                */
3012 /*                                                                        */
3013 /*    NX_SUCCESS                          Successful completion status    */
3014 /*    NX_SNTP_BAD_SERVER_ROOT_DISPERSION  Server dispersion too high      */
3015 /*    receive_status                      Actual packet receive status    */
3016 /*                                                                        */
3017 /*  CALLS                                                                 */
3018 /*                                                                        */
3019 /*    memcmp                              Copy data to area of memory     */
3020 /*    _nx_sntp_client_apply_sanity_checks Apply sanity checks to update   */
3021 /*    _nx_sntp_client_check_server_clock_dispersion                       */
3022 /*                                        Check server clock dispersion   */
3023 /*    _nx_sntp_client_calculate_roundtrip                                 */
3024 /*                                        Compute roundtrip time to server*/
3025 /*   _nx_sntp_client_process_time_data    Apply server time to local time */
3026 /*                                                                        */
3027 /*  CALLED BY                                                             */
3028 /*                                                                        */
3029 /*    _nx_sntp_client_process_unicast     Process unicast SNTP data       */
3030 /*    _nx_sntp_client_process_broadcast   Process broadcast SNTP data     */
3031 /*                                                                        */
3032 /*  RELEASE HISTORY                                                       */
3033 /*                                                                        */
3034 /*    DATE              NAME                      DESCRIPTION             */
3035 /*                                                                        */
3036 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3037 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3038 /*                                            resulting in version 6.1    */
3039 /*                                                                        */
3040 /**************************************************************************/
_nx_sntp_client_process_update_packet(NX_SNTP_CLIENT * client_ptr)3041 UINT  _nx_sntp_client_process_update_packet(NX_SNTP_CLIENT *client_ptr)
3042 {
3043 
3044 UINT    status;
3045 
3046     /* Apply client's set of sanity checks on the data.  */
3047     status = _nx_sntp_client_apply_sanity_checks(client_ptr);
3048 
3049     /* Check for sanity check errors.  */
3050     if (status != NX_SUCCESS)
3051     {
3052 
3053         /* Count these  as bad updates from the server.  */
3054         client_ptr -> nx_sntp_client_invalid_time_updates++;
3055 
3056         /* Ok to continue Client task.  */
3057         return status;
3058     }
3059 
3060     /* Check server clock dispersion (if any reported) in first update
3061        from current server for unicast clients.  */
3062     if ((client_ptr -> nx_sntp_client_first_update_pending == NX_TRUE) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3063     {
3064 
3065         status = _nx_sntp_client_check_server_clock_dispersion(client_ptr);
3066 
3067         /* Is the server clock variance acceptable?  */
3068         if (status != NX_SUCCESS)
3069         {
3070 
3071             /* Return the error status.  */
3072             return status;
3073         }
3074     }
3075 
3076     /* At this point we have received a valid server response.  */
3077 
3078     /* Clear the count of (consecutive) bad time updates received from this server.  */
3079     client_ptr -> nx_sntp_client_invalid_time_updates = 0;
3080 
3081     /* Apply server time to local device time.  */
3082     status = _nx_sntp_client_process_time_data(client_ptr);
3083 
3084     /* Check for error.  */
3085     if (status != NX_SUCCESS)
3086     {
3087 
3088         /* Return the error condition*/
3089         return status;
3090     }
3091 
3092     /* If the Client is configured with a time update callback, call it now. */
3093     if (client_ptr -> nx_sntp_client_time_update_notify)
3094     {
3095 
3096         client_ptr -> nx_sntp_client_time_update_notify(&(client_ptr -> nx_sntp_current_server_time_message),
3097                                                         &(client_ptr -> nx_sntp_client_local_ntp_time));
3098     }
3099 
3100     return status;
3101 }
3102 
3103 
3104 /**************************************************************************/
3105 /*                                                                        */
3106 /*  FUNCTION                                               RELEASE        */
3107 /*                                                                        */
3108 /*    _nx_sntp_client_duplicate_update_check              PORTABLE C      */
3109 /*                                                           6.1          */
3110 /*  AUTHOR                                                                */
3111 /*                                                                        */
3112 /*    Yuxin Zhou, Microsoft Corporation                                   */
3113 /*                                                                        */
3114 /*  DESCRIPTION                                                           */
3115 /*                                                                        */
3116 /*    This function performs a comparison of time values between two      */
3117 /*    time messages to verify they are not duplicates.  Duplicate updates */
3118 /*    can be a form of denial of service/clogging attack on a host.       */
3119 /*                                                                        */
3120 /*   INPUT                                                                */
3121 /*                                                                        */
3122 /*    timeA_msg_ptr                       Pointer to first time update    */
3123 /*    timeB_msg_ptr                       Pointer to second time update   */
3124 /*    is_a_dupe                           Result of comparison            */
3125 /*                                                                        */
3126 /*  OUTPUT                                                                */
3127 /*                                                                        */
3128 /*    NX_SUCCESS                          Successful completion status    */
3129 /*                                                                        */
3130 /*  CALLS                                                                 */
3131 /*                                                                        */
3132 /*    memcmp                              Copy data to area of memory     */
3133 /*                                                                        */
3134 /*  CALLED BY                                                             */
3135 /*                                                                        */
3136 /*    _nx_sntp_client_apply_sanity_checks Verify received SNTP data       */
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),          */
3144 /*                                            resulting in version 6.1    */
3145 /*                                                                        */
3146 /**************************************************************************/
_nx_sntp_client_duplicate_update_check(NX_SNTP_TIME_MESSAGE * timeA_msg_ptr,NX_SNTP_TIME_MESSAGE * timeB_msg_ptr,UINT * is_a_dupe)3147 UINT  _nx_sntp_client_duplicate_update_check(NX_SNTP_TIME_MESSAGE *timeA_msg_ptr,
3148                                             NX_SNTP_TIME_MESSAGE *timeB_msg_ptr,
3149                                             UINT *is_a_dupe)
3150 {
3151 
3152     *is_a_dupe = NX_FALSE;
3153 
3154     if ( (!memcmp(timeA_msg_ptr -> transmit_time_stamp,
3155                   timeB_msg_ptr -> transmit_time_stamp, 8))                               &&
3156          (!memcmp(timeA_msg_ptr -> receive_time_stamp,
3157                   timeB_msg_ptr -> receive_time_stamp, 8))                                &&
3158          (!memcmp(timeA_msg_ptr -> originate_time_stamp,
3159                   timeB_msg_ptr -> originate_time_stamp, 8))                              &&
3160          (!memcmp(timeA_msg_ptr -> reference_clock_update_time_stamp,
3161                   timeB_msg_ptr -> reference_clock_update_time_stamp, 8))                 &&
3162          (!memcmp(timeA_msg_ptr -> reference_clock_id,
3163                   timeB_msg_ptr -> reference_clock_id, 4))                                &&
3164          (timeA_msg_ptr -> root_delay == timeB_msg_ptr -> root_delay)                     &&
3165          (timeA_msg_ptr -> clock_dispersion == timeB_msg_ptr -> clock_dispersion)
3166        )
3167     {
3168 
3169         *is_a_dupe = NX_TRUE;
3170     }
3171 
3172     return NX_SUCCESS;
3173 }
3174 
3175 
3176 /**************************************************************************/
3177 /*                                                                        */
3178 /*  FUNCTION                                               RELEASE        */
3179 /*                                                                        */
3180 /*    _nx_sntp_client_apply_sanity_checks                 PORTABLE C      */
3181 /*                                                           6.1          */
3182 /*  AUTHOR                                                                */
3183 /*                                                                        */
3184 /*    Yuxin Zhou, Microsoft Corporation                                   */
3185 /*                                                                        */
3186 /*  DESCRIPTION                                                           */
3187 /*                                                                        */
3188 /*    This function checks for invalid SNTP data received from server.    */
3189 /*                                                                        */
3190 /*   INPUT                                                                */
3191 /*                                                                        */
3192 /*    client_ptr                       Pointer to Client                  */
3193 /*                                                                        */
3194 /*  OUTPUT                                                                */
3195 /*                                                                        */
3196 /*    NX_SNTP_DUPE_SERVER_PACKET       Duplicate server packet received   */
3197 /*    NX_SNTP_INVALID_SERVER_MODE      Server mode won't work with Client */
3198 /*    NX_SNTP_INVALID_NTP_VERSION      Server NTP version won't work with */
3199 /*                                       Client NTP version.              */
3200 /*    NX_SNTP_SERVER_CLOCK_NOT_SYNC    Server is not ready to send updates*/
3201 /*    NX_SNTP_INVALID_SERVER_STRATUM   Server stratum not acceptable      */
3202 /*    NX_SNTP_NULL_SERVER_TIMESTAMP    Invalid or NULL timestamp in update*/
3203 /*    status                           Actual completion status           */
3204 /*                                                                        */
3205 /*  CALLS                                                                 */
3206 /*                                                                        */
3207 /*    memcmp                           Copy data into area of memory      */
3208 /*    _nx_sntp_client_duplicate_update_check                              */
3209 /*                                     Check for duplicate updates service*/
3210 /*    _nx_sntp_client_utility_get_msec_diff                               */
3211 /*                                     Check for time difference in msecs */
3212 /*                                                                        */
3213 /*  CALLED BY                                                             */
3214 /*                                                                        */
3215 /*    _nx_sntp_client_run_broadcast    Receive broadcast SNTP updates     */
3216 /*    _nx_sntp_client_run_unicast      Send and receive SNTP updates      */
3217 /*                                                                        */
3218 /*  RELEASE HISTORY                                                       */
3219 /*                                                                        */
3220 /*    DATE              NAME                      DESCRIPTION             */
3221 /*                                                                        */
3222 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3223 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3224 /*                                            resulting in version 6.1    */
3225 /*                                                                        */
3226 /**************************************************************************/
_nx_sntp_client_apply_sanity_checks(NX_SNTP_CLIENT * client_ptr)3227 UINT  _nx_sntp_client_apply_sanity_checks(NX_SNTP_CLIENT *client_ptr)
3228 {
3229 
3230 
3231 UINT    status;
3232 UINT    mode;
3233 UINT    leap_second_indicator;
3234 UINT    server_ntp_version;
3235 UINT    is_a_dupe_check;
3236 ULONG   msecs;
3237 NX_SNTP_TIME_MESSAGE *server_time_msg_ptr;
3238 
3239     server_time_msg_ptr = &(client_ptr -> nx_sntp_current_server_time_message);
3240 
3241     /* Was a previous response received from the server?  */
3242     if (client_ptr -> nx_sntp_previous_server_time_message.flags)
3243     {
3244 
3245         /* Yes; perform a duplicate packet check.  */
3246         status = _nx_sntp_client_duplicate_update_check(&(client_ptr -> nx_sntp_current_server_time_message),
3247                                                         &(client_ptr -> nx_sntp_previous_server_time_message),
3248                                                         &is_a_dupe_check);
3249         /* Check for error.  */
3250         if (status != NX_SUCCESS)
3251         {
3252 
3253             /* Return error status.  */
3254             return status;
3255         }
3256 
3257         /* Is this a duplicate packet (e.g. possible 'clogging' attack)?  */
3258         if (is_a_dupe_check)
3259         {
3260 
3261             return NX_SNTP_DUPE_SERVER_PACKET;
3262         }
3263     }
3264 
3265     /* Get the association type from the server.  */
3266     mode = server_time_msg_ptr ->flags & 0x07;
3267 
3268     /* Is the server of the correct association for a unicast client?  */
3269     if ((mode != PROTOCOL_MODE_SERVER_UNICAST) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3270     {
3271 
3272         /* Return error status.  */
3273         return NX_SNTP_INVALID_SERVER_MODE;
3274     }
3275     /* Is the server of the correct association for a broadcast client?  */
3276     else if ((mode != PROTOCOL_MODE_SERVER_BROADCAST) && (client_ptr -> nx_sntp_client_protocol_mode == BROADCAST_MODE))
3277     {
3278 
3279         /* Return error status.  */
3280         return NX_SNTP_INVALID_SERVER_MODE;
3281     }
3282 
3283     /* Extract server's NTP version from the flags field.  */
3284     server_ntp_version = (server_time_msg_ptr -> flags & 0x38) >> 3;
3285 
3286     /* As per NTP protocol, check if the server reply has the same SNTP version that
3287       the Client sent in its unicast request.  */
3288     if ((server_ntp_version != NX_SNTP_CLIENT_NTP_VERSION) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3289     {
3290 
3291         /* Return the error condition.  */
3292         return NX_SNTP_INVALID_NTP_VERSION;
3293     }
3294     /* If broadcast, verify the server SNTP version is compatible with the Client.  */
3295     else if ((server_ntp_version < NX_SNTP_CLIENT_MIN_NTP_VERSION) && (client_ptr -> nx_sntp_client_protocol_mode == BROADCAST_MODE))
3296     {
3297 
3298         /* Return the error condition.  */
3299         return NX_SNTP_INVALID_NTP_VERSION;
3300     }
3301 
3302     /* Get the leap second indicator from the flags field.  */
3303     leap_second_indicator = (server_time_msg_ptr -> flags & 0xC0) >> 6;
3304 
3305     /* Is the server clock not yet synchronized?  */
3306     if (leap_second_indicator == 3)
3307     {
3308         /* Return the error condition.  */
3309         return NX_SNTP_SERVER_CLOCK_NOT_SYNC;
3310     }
3311 
3312     /* Has the server sent a 'kiss of death' (stratum = 0) packet?  */
3313     if (server_time_msg_ptr -> peer_clock_stratum == 0)
3314     {
3315 
3316         /* Does the Client have a kiss of death handler?  */
3317         if (client_ptr -> kiss_of_death_handler)
3318         {
3319             UINT code_id;
3320 
3321             /* Convert the message to code.*/
3322             _nx_sntp_client_utility_convert_refID_KOD_code(server_time_msg_ptr -> reference_clock_id, &code_id);
3323 
3324             /* Yes, let the handler deal with this server response.  */
3325             status = (client_ptr -> kiss_of_death_handler)(client_ptr, code_id);
3326 
3327             /* Is it ok to continue with this server?  */
3328             if (status != NX_SUCCESS)
3329             {
3330 
3331                 /* No, it is not. Return the error condition.  */
3332                 return status;
3333             }
3334         }
3335         else
3336         {
3337             /* It is not ok to continue. Return the error condition. */
3338             return NX_SNTP_KOD_SERVER_NOT_AVAILABLE;
3339         }
3340     }
3341 
3342     /* Is the server stratum a valid stratum ?  */
3343     else if (server_time_msg_ptr -> peer_clock_stratum & STRATUM_RESERVED)
3344     {
3345 
3346         /* Return error status.  */
3347         return NX_SNTP_INVALID_SERVER_STRATUM;
3348 
3349     }
3350     /* Does the server stratum acceptable to the Client?  */
3351     else if (server_time_msg_ptr -> peer_clock_stratum > NX_SNTP_CLIENT_MIN_SERVER_STRATUM)
3352     {
3353 
3354         /* Return error status.  */
3355         return NX_SNTP_INVALID_SERVER_STRATUM;
3356     }
3357 
3358     /* Is the Client operating in unicast mode?  */
3359     if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
3360     {
3361     UINT pos_diff = NX_TRUE;
3362 
3363         /* Yes; Are any server time stamps NULL?  */
3364 
3365         /* Special case: the client has not set its local time. Only check server's receive and transmit time. */
3366         if (client_ptr -> nx_sntp_client_local_ntp_time.seconds == 0)
3367         {
3368             if ((_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> receive_time_stamp), 8) == NX_TRUE) ||
3369                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE))
3370             {
3371 
3372                 /* Return error status.  */
3373                 return NX_SNTP_INVALID_TIMESTAMP;
3374             }
3375 
3376         }
3377         else
3378         {
3379             /* Check all server time stamps to be non null.  */
3380             if ((_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> originate_time_stamp), 8) == NX_TRUE) ||
3381                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> receive_time_stamp), 8) == NX_TRUE) ||
3382                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE))
3383             {
3384 
3385                 /* Return error status.  */
3386                 return NX_SNTP_INVALID_TIMESTAMP;
3387             }
3388 
3389         }
3390 
3391         /* Get the time difference  server transmit time - server receive time.  */
3392         status = _nx_sntp_client_utility_get_msec_diff(&(server_time_msg_ptr -> receive_time),
3393                                                        &(server_time_msg_ptr -> transmit_time),
3394                                                        &msecs, &pos_diff);
3395 
3396         /* Is the server transmit time <= server receive time [physically not possible]?  */
3397         if (status != NX_SUCCESS)
3398         {
3399 
3400             /* Yes; Return the error condition.  */
3401             return status;
3402         }
3403         else if (pos_diff == NX_FALSE)
3404         {
3405 
3406             /* treat as an error in this case. */
3407             return NX_SNTP_INVALID_TIMESTAMP;
3408         }
3409     }
3410     /* Client is in broadcast mode.  */
3411     else
3412     {
3413 
3414         /* Is the broadcast server transmit time stamp is NULL?  */
3415         if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE)
3416 
3417         {
3418 
3419             /* Return the error status.  */
3420             return NX_SNTP_INVALID_TIMESTAMP;
3421         }
3422     }
3423 
3424     /* Is there an impending leap second adjustment?  */
3425     if ((leap_second_indicator == 1) || (leap_second_indicator == 2))
3426     {
3427 
3428         /* Does the Client have a leap second handler?*/
3429         if (client_ptr -> leap_second_handler)
3430         {
3431 
3432             /* Yes, invoke the leap second handler for impending leap second event.  */
3433             (client_ptr -> leap_second_handler)(client_ptr, leap_second_indicator);
3434         }
3435     }
3436 
3437     /* Return successful completion status.  */
3438     return NX_SUCCESS;
3439 }
3440 
3441 
3442 /**************************************************************************/
3443 /*                                                                        */
3444 /*  FUNCTION                                               RELEASE        */
3445 /*                                                                        */
3446 /*    _nx_sntp_client_check_server_clock_dispersion       PORTABLE C      */
3447 /*                                                           6.1          */
3448 /*  AUTHOR                                                                */
3449 /*                                                                        */
3450 /*    Yuxin Zhou, Microsoft Corporation                                   */
3451 /*                                                                        */
3452 /*  DESCRIPTION                                                           */
3453 /*                                                                        */
3454 /*    This function checks server clock dispersion extracted from server  */
3455 /*    time message in 32 bit representation:                              */
3456 /*        sum of 1/(2 ^ bit) of bits 16-31 in the time message format     */
3457 /*    and compares it against the Client's dispersion tolerance.          */
3458 /*                                                                        */
3459 /*    If NX_SNTP_CLIENT_MAX_ROOT_DISPERSION is set to zero, the function  */
3460 /*    simply returns a successful result but does no calculations.        */
3461 /*                                                                        */
3462 /*   INPUT                                                                */
3463 /*                                                                        */
3464 /*    client_ptr                         Pointer to Client                */
3465 /*                                                                        */
3466 /*  OUTPUT                                                                */
3467 /*                                                                        */
3468 /*    NX_SUCCESS                         dispersion is acceptable         */
3469 /*    NX_SNTP_BAD_SERVER_ROOT_DISPERSION dispersion is too large          */
3470 /*                                                                        */
3471 /*  CALLS                                                                 */
3472 /*                                                                        */
3473 /*    None                                                                */
3474 /*                                                                        */
3475 /*  CALLED BY                                                             */
3476 /*                                                                        */
3477 /*    _nx_sntp_client_process_update_packet                               */
3478 /*                                    Process time data in update packets */
3479 /*                                                                        */
3480 /*  RELEASE HISTORY                                                       */
3481 /*                                                                        */
3482 /*    DATE              NAME                      DESCRIPTION             */
3483 /*                                                                        */
3484 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3485 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3486 /*                                            resulting in version 6.1    */
3487 /*                                                                        */
3488 /**************************************************************************/
3489 
_nx_sntp_client_check_server_clock_dispersion(NX_SNTP_CLIENT * client_ptr)3490 UINT  _nx_sntp_client_check_server_clock_dispersion(NX_SNTP_CLIENT *client_ptr)
3491 {
3492 
3493 #if (NX_SNTP_CLIENT_MAX_ROOT_DISPERSION != 0)
3494 UINT    mask = 0x8000;
3495 UINT    bit = 1;
3496 ULONG   divisor;
3497 ULONG   dispersion_usecs;
3498 
3499     /* Check for zero clock dispersion reported in server update.  */
3500     if (client_ptr -> nx_sntp_current_server_time_message.clock_dispersion == 0)
3501     {
3502 
3503         /* Return successful status.  */
3504         return NX_SUCCESS;
3505     }
3506 
3507     /* Get the most significant 16 bits of dispersion field and convert to microseconds.*/
3508     dispersion_usecs = (client_ptr -> nx_sntp_current_server_time_message.clock_dispersion >> 16) * 1000000;
3509 
3510     /* Compare seconds in the most significant 16 bits against the Client dispersion tolerance.  */
3511     if (dispersion_usecs > NX_SNTP_CLIENT_MAX_ROOT_DISPERSION)
3512     {
3513 
3514         /* Yes, indicate that server clock dispersion exceeds tolerance.  */
3515         return NX_SNTP_BAD_SERVER_ROOT_DISPERSION;
3516     }
3517 
3518     /* Compare fraction from least significant 16 bits; sum of (1 / 2 ^ bit field) of lower 16 bits.  */
3519 
3520     /* Get the lower 16 bits.  */
3521     client_ptr -> nx_sntp_current_server_time_message.clock_dispersion =
3522         client_ptr -> nx_sntp_current_server_time_message.clock_dispersion & 0xFFFF;
3523 
3524     /* Compute the dispersion.  */
3525     while(mask)
3526     {
3527         if (mask & client_ptr -> nx_sntp_current_server_time_message.clock_dispersion)
3528         {
3529             divisor = (ULONG)(1 << bit);
3530             if ((divisor < 1000000) && (divisor > 0))
3531             {
3532                 dispersion_usecs += 1000000/divisor;
3533             }
3534         }
3535         bit++;
3536         mask >>= 1;
3537     }
3538 
3539     /* Is the computed clock dispersion more than the max tolerance?  */
3540     if (dispersion_usecs > NX_SNTP_CLIENT_MAX_ROOT_DISPERSION)
3541     {
3542         /* Yes, indicate that server clock dispersion exceeds tolerance.  */
3543         return NX_SNTP_BAD_SERVER_ROOT_DISPERSION;
3544     }
3545 #else
3546     NX_PARAMETER_NOT_USED(client_ptr);
3547 #endif /* (NX_SNTP_CLIENT_MAX_ROOT_DISPERSION != 0) */
3548 
3549     /* Return successful computation.  */
3550     return NX_SUCCESS;
3551 }
3552 
3553 
3554 /**************************************************************************/
3555 /*                                                                        */
3556 /*  FUNCTION                                               RELEASE        */
3557 /*                                                                        */
3558 /*    _nx_sntp_client_thread_entry                        PORTABLE C      */
3559 /*                                                           6.1          */
3560 /*  AUTHOR                                                                */
3561 /*                                                                        */
3562 /*    Yuxin Zhou, Microsoft Corporation                                   */
3563 /*                                                                        */
3564 /*  DESCRIPTION                                                           */
3565 /*                                                                        */
3566 /*    This function is the processing thread for the SNTP Client. It      */
3567 /*    executes periodic SNTP tasks with SNTP Client mutex protection, then*/
3568 /*    briefly sleeps to allow the host application to call SNTP Client    */
3569 /*    services.                                                           */
3570 /*                                                                        */
3571 /*  INPUT                                                                 */
3572 /*                                                                        */
3573 /*    sntp_instance                         Pointer to SNTP instance      */
3574 /*                                                                        */
3575 /*  OUTPUT                                                                */
3576 /*                                                                        */
3577 /*    None                                                                */
3578 /*                                                                        */
3579 /*  CALLS                                                                 */
3580 /*                                                                        */
3581 /*    _nx_sntp_client_process               Main SNTP processing function */
3582 /*    tx_thread_sleep                       Sleep for specified time      */
3583 /*    tx_mutex_get                          Get the SNTP mutex            */
3584 /*    tx_mutex_put                          Release the SNTP mutex        */
3585 /*    tx_thread_preemption_change           Change thread preemption      */
3586 /*                                                                        */
3587 /*  CALLED BY                                                             */
3588 /*                                                                        */
3589 /*    ThreadX                                                             */
3590 /*                                                                        */
3591 /*  RELEASE HISTORY                                                       */
3592 /*                                                                        */
3593 /*    DATE              NAME                      DESCRIPTION             */
3594 /*                                                                        */
3595 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3596 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3597 /*                                            resulting in version 6.1    */
3598 /*                                                                        */
3599 /**************************************************************************/
_nx_sntp_client_thread_entry(ULONG sntp_instance)3600 VOID  _nx_sntp_client_thread_entry(ULONG sntp_instance)
3601 {
3602 
3603 NX_SNTP_CLIENT *client_ptr;
3604 UINT    status;
3605 UINT    current_preemption;
3606 
3607 
3608     /* Setup the SNTP pointer.  */
3609     client_ptr =    (NX_SNTP_CLIENT *) sntp_instance;
3610 
3611     /* Enter while loop.  */
3612     do
3613     {
3614 
3615         /* Loop for obtaining the SNTP mutex.  */
3616         do
3617         {
3618 
3619             /* Get the SNTP mutex.  */
3620             status =  tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
3621 
3622         } while (status != TX_SUCCESS);
3623 
3624         /* Perform periodic tasks for the SNTP Client.  */
3625         _nx_sntp_client_process(client_ptr);
3626 
3627          /* Release the SNTP mutex.  */
3628         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
3629 
3630         /* Disable preemption for critical section.  */
3631         tx_thread_preemption_change(tx_thread_identify(), 0, &current_preemption);
3632 
3633         /* Indicate the SNTP Client process is idle. */
3634         client_ptr -> nx_sntp_client_sleep_flag =  NX_TRUE;
3635 
3636         /* Sleep for timer interval.  */
3637         tx_thread_sleep(NX_SNTP_CLIENT_SLEEP_INTERVAL);
3638 
3639         /* Clear flag to indicate SNTP thread is not in a position to be stopped.  */
3640         client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
3641 
3642         /* Restore original preemption.  */
3643         tx_thread_preemption_change(tx_thread_identify(), current_preemption, &current_preemption);
3644 
3645 
3646     } while (1);
3647 }
3648 
3649 
3650 /**************************************************************************/
3651 /*                                                                        */
3652 /*  FUNCTION                                               RELEASE        */
3653 /*                                                                        */
3654 /*    _nx_sntp_client_receive_notify                      PORTABLE C      */
3655 /*                                                           6.1          */
3656 /*  AUTHOR                                                                */
3657 /*                                                                        */
3658 /*    Yuxin Zhou, Microsoft Corporation                                   */
3659 /*                                                                        */
3660 /*  DESCRIPTION                                                           */
3661 /*                                                                        */
3662 /*    This function sets the socket receive callback for the SNTP Client  */
3663 /*    UDP socket.  It sets a flag for the SNTP Client thread to know there*/
3664 /*    is a packet waiting to be processed.                                */
3665 /*                                                                        */
3666 /*  INPUT                                                                 */
3667 /*                                                                        */
3668 /*    socket_ptr                           Pointer to Client UDP socket   */
3669 /*                                                                        */
3670 /*  OUTPUT                                                                */
3671 /*                                                                        */
3672 /*    None                                                                */
3673 /*                                                                        */
3674 /*  CALLS                                                                 */
3675 /*                                                                        */
3676 /*    tx_event_flags_set                    Sets a receive event          */
3677 /*                                                                        */
3678 /*  CALLED BY                                                             */
3679 /*                                                                        */
3680 /*    ThreadX                                                             */
3681 /*                                                                        */
3682 /*  RELEASE HISTORY                                                       */
3683 /*                                                                        */
3684 /*    DATE              NAME                      DESCRIPTION             */
3685 /*                                                                        */
3686 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3687 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3688 /*                                            resulting in version 6.1    */
3689 /*                                                                        */
3690 /**************************************************************************/
_nx_sntp_client_receive_notify(NX_UDP_SOCKET * socket_ptr)3691 VOID  _nx_sntp_client_receive_notify(NX_UDP_SOCKET *socket_ptr)
3692 {
3693     NX_PARAMETER_NOT_USED(socket_ptr);
3694 
3695     /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied.  */
3696     tx_event_flags_set(&nx_sntp_client_events, NX_SNTP_CLIENT_RECEIVE_EVENT, TX_OR);
3697 
3698     receive_timerticks = tx_time_get();
3699 
3700     return;
3701 }
3702 
3703 
3704 /**************************************************************************/
3705 /*                                                                        */
3706 /*  FUNCTION                                               RELEASE        */
3707 /*                                                                        */
3708 /*    _nx_sntp_client_process                             PORTABLE C      */
3709 /*                                                           6.1          */
3710 /*  AUTHOR                                                                */
3711 /*                                                                        */
3712 /*    Yuxin Zhou, Microsoft Corporation                                   */
3713 /*                                                                        */
3714 /*  DESCRIPTION                                                           */
3715 /*                                                                        */
3716 /*    This function is called periodically by the SNTP client thread, and */
3717 /*    depending on the CLient mode (unicast or broadcast) calls the       */
3718 /*    unicast or broadcast process function.                              */
3719 /*                                                                        */
3720 /*  INPUT                                                                 */
3721 /*                                                                        */
3722 /*    client_ptr                            Pointer to the SNTP client    */
3723 /*                                                                        */
3724 /*  OUTPUT                                                                */
3725 /*                                                                        */
3726 /*    None                                                                */
3727 /*                                                                        */
3728 /*  CALLS                                                                 */
3729 /*                                                                        */
3730 /*    _nx_sntp_client_process_unicast       Process unicast tasks         */
3731 /*    _nx_sntp_client_process_broadcast     Process broadcast tasks       */
3732 /*                                                                        */
3733 /*  CALLED BY                                                             */
3734 /*                                                                        */
3735 /*    ThreadX                                                             */
3736 /*                                                                        */
3737 /*  RELEASE HISTORY                                                       */
3738 /*                                                                        */
3739 /*    DATE              NAME                      DESCRIPTION             */
3740 /*                                                                        */
3741 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3742 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3743 /*                                            resulting in version 6.1    */
3744 /*                                                                        */
3745 /**************************************************************************/
_nx_sntp_client_process(NX_SNTP_CLIENT * client_ptr)3746 VOID  _nx_sntp_client_process(NX_SNTP_CLIENT *client_ptr)
3747 {
3748 
3749 
3750     /* Is the client using unicast or unicast to receive updates? */
3751     if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
3752     {
3753         /* Call the unicast process function. */
3754         _nx_sntp_client_process_unicast(client_ptr);
3755     }
3756     else
3757     {
3758 
3759         /* Call the broadcast process function. */
3760         _nx_sntp_client_process_broadcast(client_ptr);
3761     }
3762 
3763     return;
3764 }
3765 
3766 
3767 /**************************************************************************/
3768 /*                                                                        */
3769 /*  FUNCTION                                               RELEASE        */
3770 /*                                                                        */
3771 /*    _nx_sntp_client_process_time_data                   PORTABLE C      */
3772 /*                                                           6.1          */
3773 /*  AUTHOR                                                                */
3774 /*                                                                        */
3775 /*    Yuxin Zhou, Microsoft Corporation                                   */
3776 /*                                                                        */
3777 /*  DESCRIPTION                                                           */
3778 /*                                                                        */
3779 /*  This function applies the server time data to client local time taking*/
3780 /*  into account the round trip time.  Time updates are checked for a max */
3781 /*  time offset set by the Client max_time_adjustment parameter.          */
3782 /*                                                                        */
3783 /*   INPUT                                                                */
3784 /*                                                                        */
3785 /*    client_ptr                        Pointer to Client                 */
3786 /*                                                                        */
3787 /*  OUTPUT                                                                */
3788 /*                                                                        */
3789 /*    NX_SUCCESS                        Successful completion status      */
3790 /*    NX_SNTP_INVALID_SERVER_UPDATE_TIME No time of server update recorded*/
3791 /*    status                            Actual completion status          */
3792 /*                                                                        */
3793 /*  CALLS                                                                 */
3794 /*                                                                        */
3795 /*    memset                           Clear specified area of memory     */
3796 /*    memcpy                           Copy data to area of memory        */
3797 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
3798 /*                                     Add msec to NTP time fraction field*/
3799 /*    _nx_sntp_client_utility_get_msec_diff                               */
3800 /*                                     Compute time difference in msecs   */
3801 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
3802 /*                                     Add time in msecs to an NTP time   */
3803 /*                                                                        */
3804 /*  CALLED BY                                                             */
3805 /*                                                                        */
3806 /*    _nx_sntp_client_run_broadcast   Listen and process broadcast updates*/
3807 /*    _nx_sntp_client_process_update_packet                               */
3808 /*                                    Process update SNTP packets         */
3809 /*                                                                        */
3810 /*  RELEASE HISTORY                                                       */
3811 /*                                                                        */
3812 /*    DATE              NAME                      DESCRIPTION             */
3813 /*                                                                        */
3814 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3815 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3816 /*                                            verified memcpy use cases,  */
3817 /*                                            resulting in version 6.1    */
3818 /*                                                                        */
3819 /**************************************************************************/
_nx_sntp_client_process_time_data(NX_SNTP_CLIENT * client_ptr)3820 UINT  _nx_sntp_client_process_time_data(NX_SNTP_CLIENT *client_ptr)
3821 {
3822 
3823 UINT            status;
3824 UINT            ignore_max_adjustment_limit;
3825 ULONG           elapsed_msecs_difference;
3826 UINT            adjustment;
3827 NX_SNTP_TIME    local_time;
3828 
3829 
3830     /* Copy the received time update to the update time just received from the server. */
3831     memcpy(&client_ptr -> nx_sntp_server_update_time, &client_ptr -> nx_sntp_current_server_time_message.transmit_time, sizeof(NX_SNTP_TIME)); /* Use case of memcpy is verified. */
3832 
3833     /* Check if the client is configured for round trip time calculation.  */
3834     if (NX_SNTP_CLIENT_RTT_REQUIRED == NX_TRUE)
3835     {
3836 
3837         /* Compute roundtrip delay. */
3838         _nx_sntp_client_calculate_roundtrip(&(client_ptr -> nx_sntp_client_roundtrip_time_msec));
3839 
3840         /* Has the client computed a valid round trip time?  */
3841         if (client_ptr -> nx_sntp_client_roundtrip_time_msec)
3842         {
3843 
3844             /* Yes, Add 1/2 round trip to server's reported time.  */
3845             status =_nx_sntp_client_utility_add_msecs_to_ntp_time(&(client_ptr -> nx_sntp_current_server_time_message.transmit_time),
3846                                                                    ((client_ptr -> nx_sntp_client_roundtrip_time_msec) / 2));
3847 
3848             if (status != NX_SUCCESS)
3849             {
3850 
3851                 /* Cannot use this time update. */
3852                 return status;
3853             }
3854         }
3855     }
3856 
3857     /* Is this the first update?  */
3858     if (client_ptr -> nx_sntp_client_first_update_pending == NX_TRUE)
3859     {
3860         /* Check Client configuration if we ignore max adjustment limit on first update.  */
3861         ignore_max_adjustment_limit = NX_SNTP_CLIENT_IGNORE_MAX_ADJUST_STARTUP;
3862     }
3863     else
3864         ignore_max_adjustment_limit = NX_FALSE;
3865 
3866     /* If not ignoring the max adjustment, deal with time difference between client and server. */
3867     if (ignore_max_adjustment_limit == NX_FALSE)
3868     {
3869     UINT pos_diff = NX_TRUE;
3870 
3871         /* Compute difference of server update packet minus the client's local time. It is reasonable
3872            to assume that the Client time is 'behind' the server time because it is updated by the
3873            server time.  */
3874         local_time.seconds = client_ptr -> nx_sntp_client_local_ntp_time.seconds +
3875             client_ptr -> nx_sntp_client_local_ntp_time_elapsed;
3876         local_time.fraction = client_ptr -> nx_sntp_client_local_ntp_time.fraction;
3877         status = _nx_sntp_client_utility_get_msec_diff(&local_time,
3878                                                        &(client_ptr -> nx_sntp_server_update_time),
3879                                                        &elapsed_msecs_difference, &pos_diff);
3880 
3881 
3882         /* Note that a positive difference vs negative difference is not an error. */
3883         if (status != NX_SUCCESS)
3884         {
3885 
3886             /* Cannot use this time update. */
3887             return status;
3888         }
3889 
3890         /* Is the difference less than the client's minimum adjustment?  */
3891         if (elapsed_msecs_difference > NX_SNTP_CLIENT_MIN_TIME_ADJUSTMENT)
3892         {
3893 
3894             /* The adjustment is larger than the Client's minimum adjustment. */
3895 
3896             /* Set the local clock to the server time only if 1)we are ignoring the maximum adjustment on startup,
3897                or 2) the difference is within the Client's max time adjustment.  */
3898             if (elapsed_msecs_difference > NX_SNTP_CLIENT_MAX_TIME_ADJUSTMENT)
3899             {
3900                 /* Cannot use this time update. */
3901                 return NX_SNTP_INVALID_TIME;
3902             }
3903         }
3904     }
3905 
3906     /* Ok to update client local time. */
3907     memcpy(&client_ptr -> nx_sntp_client_local_ntp_time, &client_ptr -> nx_sntp_current_server_time_message.transmit_time, sizeof(NX_SNTP_TIME)); /* Use case of memcpy is verified. */
3908     client_ptr -> nx_sntp_client_local_ntp_time_elapsed = 0;
3909 
3910      /* Apply a correction to server's time for internal SNTP Client delays e.g. periodic task intervals. */
3911     adjustment = ((process_timerticks - receive_timerticks) * 1000) / NX_IP_PERIODIC_RATE;
3912 
3913     status = _nx_sntp_client_utility_add_msecs_to_ntp_time(&(client_ptr -> nx_sntp_client_local_ntp_time), (LONG)adjustment);
3914 
3915     /* Done processing time update. */
3916     return status;
3917 }
3918 
3919 
3920 /**************************************************************************/
3921 /*                                                                        */
3922 /*  FUNCTION                                               RELEASE        */
3923 /*                                                                        */
3924 /*    _nx_sntp_client_calculate_roundtrip                 PORTABLE C      */
3925 /*                                                           6.1          */
3926 /*  AUTHOR                                                                */
3927 /*                                                                        */
3928 /*    Yuxin Zhou, Microsoft Corporation                                   */
3929 /*                                                                        */
3930 /*  DESCRIPTION                                                           */
3931 /*                                                                        */
3932 /*   This function computes roundtrip based on the elapsed time from      */
3933 /*   sending the unicast request to receiving the SNTP response.          */
3934 /*                                                                        */
3935 /*   INPUT                                                                */
3936 /*                                                                        */
3937 /*    roundtrip_time                    round trip time computation       */
3938 /*                                                                        */
3939 /*  OUTPUT                                                                */
3940 /*                                                                        */
3941 /*    NX_SUCCESS                        Valid time computations result    */
3942 /*                                                                        */
3943 /*  CALLS                                                                 */
3944 /*                                                                        */
3945 /*    None                                                                */
3946 /*                                                                        */
3947 /*  CALLED BY                                                             */
3948 /*                                                                        */
3949 /*    _nx_sntp_client_process_update_packet                               */
3950 /*                                      Process server update packet      */
3951 /*                                                                        */
3952 /*  RELEASE HISTORY                                                       */
3953 /*                                                                        */
3954 /*    DATE              NAME                      DESCRIPTION             */
3955 /*                                                                        */
3956 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3957 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3958 /*                                            resulting in version 6.1    */
3959 /*                                                                        */
3960 /**************************************************************************/
_nx_sntp_client_calculate_roundtrip(LONG * roundtrip_time)3961 UINT  _nx_sntp_client_calculate_roundtrip(LONG *roundtrip_time)
3962 {
3963 
3964 ULONG x;
3965 
3966 
3967     /* Initialize invalid results. */
3968     *roundtrip_time = 0;
3969 
3970     /* Compute the roundtrip as the time the packet left the SNTP Client
3971        to the time it received a response from the SNTP server. */
3972 
3973     /* Check for wrapped timer value. */
3974     if (send_timerticks > receive_timerticks)
3975     {
3976         /* The time has wrapped.  */
3977         x = 0xFFFFFFFF - send_timerticks;
3978         *roundtrip_time = (LONG)(receive_timerticks + x);
3979     }
3980     else
3981     {
3982          *roundtrip_time = (LONG)(receive_timerticks - send_timerticks);
3983     }
3984 
3985     /* Convert to milliseconds. */
3986     *roundtrip_time = (LONG)((ULONG)(*roundtrip_time) * NX_SNTP_MILLISECONDS_PER_TICK);
3987 
3988      /* Return successful completion.  */
3989      return NX_SUCCESS;
3990 }
3991 
3992 
3993 /**************************************************************************/
3994 /*                                                                        */
3995 /*  FUNCTION                                               RELEASE        */
3996 /*                                                                        */
3997 /*    _nxe_sntp_client_get_local_time                      PORTABLE C     */
3998 /*                                                           6.1          */
3999 /*  AUTHOR                                                                */
4000 /*                                                                        */
4001 /*    Yuxin Zhou, Microsoft Corporation                                   */
4002 /*                                                                        */
4003 /*  DESCRIPTION                                                           */
4004 /*                                                                        */
4005 /*   This function performs error checking for the get local time service.*/
4006 /*                                                                        */
4007 /*   INPUT                                                                */
4008 /*                                                                        */
4009 /*    client_ptr                        Pointer to SNTP Client            */
4010 /*    seconds                           Pointer to SNTP seconds           */
4011 /*    fraction                          Local time fraction component     */
4012 /*    buffer                            Pointer for time in string format */
4013 /*                                                                        */
4014 /*  OUTPUT                                                                */
4015 /*                                                                        */
4016 /*    status                            Completion status                 */
4017 /*                                                                        */
4018 /*  CALLS                                                                 */
4019 /*                                                                        */
4020 /*    _nx_sntp_client_get_local_time    Get local time service            */
4021 /*                                                                        */
4022 /*  CALLED BY                                                             */
4023 /*                                                                        */
4024 /*    Application Code                                                    */
4025 /*                                                                        */
4026 /*  RELEASE HISTORY                                                       */
4027 /*                                                                        */
4028 /*    DATE              NAME                      DESCRIPTION             */
4029 /*                                                                        */
4030 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4031 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4032 /*                                            resulting in version 6.1    */
4033 /*                                                                        */
4034 /**************************************************************************/
_nxe_sntp_client_get_local_time(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer)4035 UINT  _nxe_sntp_client_get_local_time(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer)
4036 {
4037 
4038 UINT status;
4039 
4040 
4041     /* Check input pointer parameters.  */
4042     if ((client_ptr == NX_NULL) || (seconds == NX_NULL) || (fraction == NX_NULL))
4043     {
4044 
4045         /* Return pointer error.  */
4046         return NX_PTR_ERROR;
4047     }
4048 
4049     /* Check if this function is called from the appropriate thread.  */
4050     NX_THREADS_ONLY_CALLER_CHECKING
4051 
4052     /* Call the actual service.  */
4053     status = _nx_sntp_client_get_local_time(client_ptr, seconds, fraction, buffer);
4054 
4055     /* Return completion status.  */
4056     return status;
4057 }
4058 
4059 
4060 /**************************************************************************/
4061 /*                                                                        */
4062 /*  FUNCTION                                               RELEASE        */
4063 /*                                                                        */
4064 /*    _nx_sntp_client_get_local_time                      PORTABLE C      */
4065 /*                                                           6.1          */
4066 /*  AUTHOR                                                                */
4067 /*                                                                        */
4068 /*    Yuxin Zhou, Microsoft Corporation                                   */
4069 /*                                                                        */
4070 /*  DESCRIPTION                                                           */
4071 /*                                                                        */
4072 /*   This function retrieves the current SNTP Client local time and       */
4073 /*   returns the data in seconds and fractions, and if a non zero         */
4074 /*   buffer pointer is supplied, a string containing the data in ASCII.   */
4075 /*                                                                        */
4076 /*   INPUT                                                                */
4077 /*                                                                        */
4078 /*    client_ptr                        Pointer to SNTP Client            */
4079 /*    seconds                           Pointer to SNTP seconds           */
4080 /*    fraction                          Local time fraction component     */
4081 /*    buffer                            Pointer for time in string format */
4082 /*                                                                        */
4083 /*  OUTPUT                                                                */
4084 /*                                                                        */
4085 /*    status                                Completion status             */
4086 /*                                                                        */
4087 /*  CALLS                                                                 */
4088 /*                                                                        */
4089 /*    _nx_utility_string_length_check       Check string length           */
4090 /*    _nx_sntp_client_get_local_time_extended                             */
4091 /*                                          Get local time service        */
4092 /*                                                                        */
4093 /*  CALLED BY                                                             */
4094 /*                                                                        */
4095 /*    Application Code                                                    */
4096 /*                                                                        */
4097 /*  RELEASE HISTORY                                                       */
4098 /*                                                                        */
4099 /*    DATE              NAME                      DESCRIPTION             */
4100 /*                                                                        */
4101 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4102 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4103 /*                                            resulting in version 6.1    */
4104 /*                                                                        */
4105 /**************************************************************************/
_nx_sntp_client_get_local_time(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer)4106 UINT  _nx_sntp_client_get_local_time(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer)
4107 {
4108 
4109 UINT  status;
4110 
4111     status = _nx_sntp_client_get_local_time_extended(client_ptr, seconds, fraction, buffer, NX_MAX_STRING_LENGTH);
4112 
4113     return status;
4114 }
4115 
4116 /**************************************************************************/
4117 /*                                                                        */
4118 /*  FUNCTION                                               RELEASE        */
4119 /*                                                                        */
4120 /*    _nxe_sntp_client_get_local_time_extended             PORTABLE C     */
4121 /*                                                           6.1          */
4122 /*  AUTHOR                                                                */
4123 /*                                                                        */
4124 /*    Yuxin Zhou, Microsoft Corporation                                   */
4125 /*                                                                        */
4126 /*  DESCRIPTION                                                           */
4127 /*                                                                        */
4128 /*   This function performs error checking for the get extended local     */
4129 /*   time service.                                                        */
4130 /*                                                                        */
4131 /*   INPUT                                                                */
4132 /*                                                                        */
4133 /*    client_ptr                        Pointer to SNTP Client            */
4134 /*    seconds                           Pointer to SNTP seconds           */
4135 /*    fraction                          Local time fraction component     */
4136 /*    buffer                            Pointer for time in string format */
4137 /*    buffer_size                       Size of buffer                    */
4138 /*                                                                        */
4139 /*  OUTPUT                                                                */
4140 /*                                                                        */
4141 /*    status                            Completion status                 */
4142 /*                                                                        */
4143 /*  CALLS                                                                 */
4144 /*                                                                        */
4145 /*    _nx_sntp_client_get_local_time_extended                             */
4146 /*                                      Get extended local time service   */
4147 /*                                                                        */
4148 /*  CALLED BY                                                             */
4149 /*                                                                        */
4150 /*    Application Code                                                    */
4151 /*                                                                        */
4152 /*  RELEASE HISTORY                                                       */
4153 /*                                                                        */
4154 /*    DATE              NAME                      DESCRIPTION             */
4155 /*                                                                        */
4156 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4157 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4158 /*                                            resulting in version 6.1    */
4159 /*                                                                        */
4160 /**************************************************************************/
_nxe_sntp_client_get_local_time_extended(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer,UINT buffer_size)4161 UINT  _nxe_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size)
4162 {
4163 
4164 UINT status;
4165 
4166 
4167     /* Check input pointer parameters.  */
4168     if ((client_ptr == NX_NULL) || (seconds == NX_NULL) || (fraction == NX_NULL))
4169     {
4170 
4171         /* Return pointer error.  */
4172         return NX_PTR_ERROR;
4173     }
4174 
4175     /* Check if this function is called from the appropriate thread.  */
4176     NX_THREADS_ONLY_CALLER_CHECKING
4177 
4178     /* Call the actual service.  */
4179     status = _nx_sntp_client_get_local_time_extended(client_ptr, seconds, fraction, buffer, buffer_size);
4180 
4181     /* Return completion status.  */
4182     return status;
4183 }
4184 
4185 
4186 /**************************************************************************/
4187 /*                                                                        */
4188 /*  FUNCTION                                               RELEASE        */
4189 /*                                                                        */
4190 /*    _nx_sntp_client_get_local_time_extended             PORTABLE C      */
4191 /*                                                           6.1.8        */
4192 /*  AUTHOR                                                                */
4193 /*                                                                        */
4194 /*    Yuxin Zhou, Microsoft Corporation                                   */
4195 /*                                                                        */
4196 /*  DESCRIPTION                                                           */
4197 /*                                                                        */
4198 /*   This function retrieves the current SNTP Client local time and       */
4199 /*   returns the data in seconds and fractions, and if a non zero         */
4200 /*   buffer pointer is supplied, a string containing the data in ASCII.   */
4201 /*                                                                        */
4202 /*   INPUT                                                                */
4203 /*                                                                        */
4204 /*    client_ptr                        Pointer to SNTP Client            */
4205 /*    seconds                           Pointer to SNTP seconds           */
4206 /*    fraction                          Local time fraction component     */
4207 /*    buffer                            Pointer for time in string format */
4208 /*    buffer_size                       Size of buffer                    */
4209 /*                                                                        */
4210 /*  OUTPUT                                                                */
4211 /*                                                                        */
4212 /*    status                            Completion status                 */
4213 /*                                                                        */
4214 /*  CALLS                                                                 */
4215 /*                                                                        */
4216 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
4217 /*                                      Convert NTP fraction to usecs     */
4218 /*    _nx_utility_uint_to_string        Converts number to ascii text     */
4219 /*                                                                        */
4220 /*  CALLED BY                                                             */
4221 /*                                                                        */
4222 /*    Application Code                                                    */
4223 /*                                                                        */
4224 /*  RELEASE HISTORY                                                       */
4225 /*                                                                        */
4226 /*    DATE              NAME                      DESCRIPTION             */
4227 /*                                                                        */
4228 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4229 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4230 /*                                            verified memmove use cases, */
4231 /*                                            resulting in version 6.1    */
4232 /*  08-02-2021     Yuxin Zhou               Modified comment(s),          */
4233 /*                                            improved the logic of       */
4234 /*                                            converting number to string,*/
4235 /*                                            resulting in version 6.1.8  */
4236 /*                                                                        */
4237 /**************************************************************************/
_nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer,UINT buffer_size)4238 UINT  _nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size)
4239 {
4240 
4241 ULONG usecs;
4242 UINT offset = 0;
4243 UINT length = 0;
4244 
4245     *seconds = client_ptr -> nx_sntp_client_local_ntp_time.seconds;
4246     *fraction = client_ptr -> nx_sntp_client_local_ntp_time.fraction;
4247 
4248     if (buffer != NX_NULL)
4249     {
4250 
4251         /* Convert SNTP fraction component into microseconds.  */
4252         _nx_sntp_client_utility_fraction_to_usecs(client_ptr -> nx_sntp_client_local_ntp_time.fraction, &usecs);
4253 
4254         /* Decrease length for terminal zero. */
4255         buffer_size--;
4256 
4257         /* Create a string with just the time.  */
4258         /* Format: "Time: %lu.%06lu sec.\r\n" */
4259         if (buffer_size < 6)
4260         {
4261             return(NX_SIZE_ERROR);
4262         }
4263         buffer[offset++] = 'T';
4264         buffer[offset++] = 'i';
4265         buffer[offset++] = 'm';
4266         buffer[offset++] = 'e';
4267         buffer[offset++] = ':';
4268         buffer[offset++] = ' ';
4269         length = _nx_utility_uint_to_string(client_ptr -> nx_sntp_client_local_ntp_time.seconds,
4270                                             10, &buffer[offset], buffer_size - offset);
4271         if (length == 0)
4272         {
4273             return(NX_SIZE_ERROR);
4274         }
4275         offset += length;
4276         if ((buffer_size - offset) < 14)
4277         {
4278             return(NX_SIZE_ERROR);
4279         }
4280         buffer[offset++] = '.';
4281         length = _nx_utility_uint_to_string(usecs, 10, &buffer[offset], buffer_size - offset);
4282         if (length == 0)
4283         {
4284             return(NX_SIZE_ERROR);
4285         }
4286 
4287         if (length < 6)
4288         {
4289 
4290             /* Append zeroes. */
4291             memmove(&buffer[offset + (6 - length)], &buffer[offset], length); /* Use case of memmove is verified.  */
4292             memset(&buffer[offset], '0', (6 - length));
4293         }
4294 
4295         offset += 6;
4296         buffer[offset++] = ' ';
4297         buffer[offset++] = 's';
4298         buffer[offset++] = 'e';
4299         buffer[offset++] = 'c';
4300         buffer[offset++] = '.';
4301         buffer[offset++] = '\r';
4302         buffer[offset++] = '\n';
4303         buffer[offset] = '\0';
4304     }
4305 
4306     return NX_SUCCESS;
4307 }
4308 
4309 
4310 /**************************************************************************/
4311 /*                                                                        */
4312 /*  FUNCTION                                               RELEASE        */
4313 /*                                                                        */
4314 /*    _nx_sntp_client_utility_convert_time_to_UCHAR       PORTABLE C      */
4315 /*                                                           6.1          */
4316 /*  AUTHOR                                                                */
4317 /*                                                                        */
4318 /*    Yuxin Zhou, Microsoft Corporation                                   */
4319 /*                                                                        */
4320 /*  DESCRIPTION                                                           */
4321 /*                                                                        */
4322 /*    This function converts time from the ULONG seconds and msecs in the */
4323 /*    NX_SNTP_TIME data to the 32 bit UCHAR seconds and fraction fields in*/
4324 /*    the NTP time message.  The caller specifies which time stamp in the */
4325 /*    NTP time message (transmit,receive, origination, or reference clock)*/
4326 /*    and that field is converted over.                                   */
4327 /*                                                                        */
4328 /*   INPUT                                                                */
4329 /*                                                                        */
4330 /*    time_ptr                        Pointer to NX_SNTP_TIME time        */
4331 /*    time_message_ptr                Pointer to NTP (UCHAR) time         */
4332 /*    which_stamp                     Which time stamp to convert         */
4333 /*                                                                        */
4334 /*  OUTPUT                                                                */
4335 /*                                                                        */
4336 /*    NX_SNTP_PARAM_ERROR             Invalid time stamp requested        */
4337 /*    NX_SUCCESS                      Successful completion status        */
4338 /*                                                                        */
4339 /*  CALLS                                                                 */
4340 /*                                                                        */
4341 /*    memset                         Clear specified area of memory       */
4342 /*                                                                        */
4343 /*  CALLED BY                                                             */
4344 /*                                                                        */
4345 /*    _nx_sntp_client_send_unicast_request                                */
4346 /*                                   Create a time request and transmit it*/
4347 /*                                                                        */
4348 /*  RELEASE HISTORY                                                       */
4349 /*                                                                        */
4350 /*    DATE              NAME                      DESCRIPTION             */
4351 /*                                                                        */
4352 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4353 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4354 /*                                            resulting in version 6.1    */
4355 /*                                                                        */
4356 /**************************************************************************/
_nx_sntp_client_utility_convert_time_to_UCHAR(NX_SNTP_TIME * time_ptr,NX_SNTP_TIME_MESSAGE * time_message_ptr,UINT which_stamp)4357 UINT  _nx_sntp_client_utility_convert_time_to_UCHAR(NX_SNTP_TIME *time_ptr,
4358                                      NX_SNTP_TIME_MESSAGE *time_message_ptr, UINT which_stamp)
4359 {
4360 
4361 ULONG *buffer;
4362 
4363     /* Copy the buffer to the requested time stamp field.  */
4364     switch (which_stamp)
4365     {
4366 
4367         case REFERENCE_TIME:
4368             buffer = time_message_ptr -> reference_clock_update_time_stamp;
4369         break;
4370 
4371         case ORIGINATE_TIME:
4372             buffer = time_message_ptr -> originate_time_stamp;
4373         break;
4374 
4375         case RECEIVE_TIME:
4376             buffer = time_message_ptr -> receive_time_stamp;
4377         break;
4378 
4379         case TRANSMIT_TIME:
4380             buffer = time_message_ptr -> transmit_time_stamp;
4381         break;
4382 
4383         default:
4384             /* Invalid time stamp. Return as error.  */
4385             return NX_SNTP_PARAM_ERROR;
4386     }
4387 
4388     /* Copy NX_SNTP_TIME seconds and fraction to the buffer.  */
4389     *(buffer) = time_ptr -> seconds;
4390     *(buffer + 1) = time_ptr -> fraction;
4391 
4392     /* Return successful completion.  */
4393     return NX_SUCCESS;
4394 }
4395 
4396 /* The conventional civil timescale used in most parts of the world is based on Coordinated Universal Time (UTC),
4397    which replaced Greenwich Mean Time (GMT) many years ago. UTC is based on International Atomic Time (TAI),
4398    which is derived from hundreds of cesium oscillators in the national standards laboratories of many regions.
4399    Deviations of UTC from TAI are implemented in the form of leap seconds, which occur at intervals from a
4400    few months to serveral years. */
4401 
4402 
4403 /**************************************************************************/
4404 /*                                                                        */
4405 /*  FUNCTION                                               RELEASE        */
4406 /*                                                                        */
4407 /*    _nx_sntp_client_utility_convert_seconds_to_date     PORTABLE C      */
4408 /*                                                           6.1          */
4409 /*  AUTHOR                                                                */
4410 /*                                                                        */
4411 /*    Yuxin Zhou, Microsoft Corporation                                   */
4412 /*                                                                        */
4413 /*  DESCRIPTION                                                           */
4414 /*                                                                        */
4415 /*  This function computes the month, day, and time in an NTP time based  */
4416 /*  on the known number of seconds at 1/1/1999 since 1/1/1900 (the NTP    */
4417 /*  time epoch) and the current NTP time.  The caller must indicated the  */
4418 /*  year of the NTP time to convert to simplify the computation.  The data*/
4419 /*  is written to an NX_SNTP_DATE_TIME object from which the call can     */
4420 /*  extract date and time data, or call the NetX SNTP API to display the  */
4421 /*  data/time string.                                                     */
4422 /*                                                                        */
4423 /*   INPUT                                                                */
4424 /*                                                                        */
4425 /*    current_NTP_time_ptr              Pointer to NTP time               */
4426 /*    current_year                      Year in the NTP time data         */
4427 /*    current_date_time_ptr             Pointer to date time object       */
4428 /*                                                                        */
4429 /*  OUTPUT                                                                */
4430 /*                                                                        */
4431 /*    NX_SUCCESS                         Successful completion status     */
4432 /*    NX_SNTP_ERROR_CONVERTING_DATETIME  Internal error converting time   */
4433 /*    NX_SNTP_UNABLE_TO_CONVERT_DATETIME Insufficient data for converting */
4434 /*                                                                        */
4435 /*  CALLS                                                                 */
4436 /*                                                                        */
4437 /*    _nx_sntp_client_utility_convert_fraction_to_msecs                   */
4438 /*                                      Converts the 32 bit fraction field*/
4439 /*                                      in an NTP time to milliseconds    */
4440 /*                                                                        */
4441 /*  CALLED BY                                                             */
4442 /*                                                                        */
4443 /*    Application                                                         */
4444 /*                                                                        */
4445 /*  RELEASE HISTORY                                                       */
4446 /*                                                                        */
4447 /*    DATE              NAME                      DESCRIPTION             */
4448 /*                                                                        */
4449 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4450 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4451 /*                                            fixed leap year calculation,*/
4452 /*                                            resulting in version 6.1    */
4453 /*                                                                        */
4454 /**************************************************************************/
_nx_sntp_client_utility_convert_seconds_to_date(NX_SNTP_TIME * current_NTP_time_ptr,UINT current_year,NX_SNTP_DATE_TIME * current_date_time_ptr)4455 UINT _nx_sntp_client_utility_convert_seconds_to_date(NX_SNTP_TIME *current_NTP_time_ptr, UINT current_year,
4456                                                      NX_SNTP_DATE_TIME *current_date_time_ptr)
4457 {
4458 
4459     /* Check if there is a base number of seconds set. */
4460 #if (NTP_SECONDS_AT_01011999 == 0)
4461 
4462     /* No, so we cannot convert time into months and years. */
4463     return NX_SNTP_UNABLE_TO_CONVERT_DATETIME;
4464 #else
4465 
4466 UINT seconds_diff;
4467 UINT years_diff;
4468 UINT leapyears_diff;
4469 UINT leaps;
4470 UINT seconds_of_year;
4471 UINT seconds_into_currentyear;
4472 UINT seconds_into_currentmonth;
4473 UINT seconds_into_currentday;
4474 UINT seconds_into_currenthour;
4475 
4476     memset(current_date_time_ptr, 0, sizeof(NX_SNTP_DATE_TIME));
4477 
4478     do
4479     {
4480 
4481         current_date_time_ptr -> year = current_year;
4482 
4483         seconds_diff = current_NTP_time_ptr -> seconds - NTP_SECONDS_AT_01011999;
4484 
4485         years_diff = current_year - 1999;
4486 
4487         /* Figure out number of leap years since 1999 not including the current year. */
4488         leapyears_diff = (current_year - 1 - 1996) >> 2;
4489 
4490         /* Determine if this is a leap year. */
4491         leaps = (current_year - 1996) & 3;
4492 
4493         /* Check if this is a leap year. */
4494         if (leaps == 0 )
4495         {
4496             /* It is! */
4497             current_date_time_ptr -> leap_year = NX_TRUE;
4498             seconds_of_year = SECONDS_PER_LEAPYEAR;
4499         }
4500         else
4501         {
4502 
4503             /* Not a leap year. Clear the leap year flag. */
4504             current_date_time_ptr -> leap_year = NX_FALSE;
4505             seconds_of_year = SECONDS_PER_NONLEAPYEAR;
4506         }
4507 
4508         /* Compute number of seconds into the current year e.g. as of 01/01 at midnite by subtracting
4509            the total number of seconds since 1/1/1999 up to the end of the previous year.  Remember to compute
4510            the leapyear seconds at a different rate. */
4511         seconds_into_currentyear = seconds_diff - ((years_diff - leapyears_diff) * SECONDS_PER_NONLEAPYEAR)
4512                                                 - (leapyears_diff * SECONDS_PER_LEAPYEAR);
4513 
4514         current_year++;
4515 
4516     }while(seconds_into_currentyear > seconds_of_year);
4517 
4518     /* Initialize month to January till we find out what the month is. */
4519     current_date_time_ptr -> month = JANUARY;
4520 
4521     while (1)
4522     {
4523 
4524         /* Does the number of seconds goes past January? */
4525         if (seconds_into_currentyear >= SEC_IN_JAN)
4526         {
4527 
4528             /* Yes, reset month to Feb and subtract seconds in January. */
4529             current_date_time_ptr -> month = FEBRUARY;
4530             seconds_into_currentyear -= SEC_IN_JAN;
4531         }
4532         /* No, we're done going month to month. */
4533         else break;
4534 
4535         /* Handle February differently because it is a leap month. */
4536         if (current_date_time_ptr -> leap_year)
4537         {
4538 
4539             /* This is a leap year so Feb has 29 days. */
4540             if (seconds_into_currentyear >= SEC_IN_LEAPFEB)
4541             {
4542                 current_date_time_ptr -> month = MARCH;
4543                 seconds_into_currentyear -= SEC_IN_LEAPFEB;
4544             }
4545             else break;
4546 
4547         }
4548         else
4549         {
4550             /* Not a leap year, Feb has the usual 28 days. */
4551             if (seconds_into_currentyear >= SEC_IN_NONLEAPFEB)
4552             {
4553                 current_date_time_ptr -> month = MARCH;
4554                 seconds_into_currentyear -= SEC_IN_NONLEAPFEB;
4555             }
4556             else break;
4557 
4558         }
4559 
4560         /* Repeat for each month for the rest of the year. */
4561 
4562         if (seconds_into_currentyear >= SEC_IN_MAR)
4563         {
4564             current_date_time_ptr -> month = APRIL;
4565             seconds_into_currentyear -= SEC_IN_MAR;
4566         }
4567         else break;
4568 
4569         if (seconds_into_currentyear >= SEC_IN_APR)
4570         {
4571             current_date_time_ptr -> month = MAY;
4572             seconds_into_currentyear -= SEC_IN_APR;
4573         }
4574         else break;
4575 
4576         if (seconds_into_currentyear >= SEC_IN_MAY)
4577         {
4578             current_date_time_ptr -> month = JUNE;
4579             seconds_into_currentyear -= SEC_IN_MAY;
4580         }
4581         else break;
4582 
4583         if (seconds_into_currentyear >= SEC_IN_JUN)
4584         {
4585             current_date_time_ptr -> month = JULY;
4586             seconds_into_currentyear -= SEC_IN_JUN;
4587         }
4588         else break;
4589 
4590         if (seconds_into_currentyear >= SEC_IN_JUL)
4591         {
4592             current_date_time_ptr -> month = AUGUST;
4593             seconds_into_currentyear -= SEC_IN_JUL;
4594         }
4595         else break;
4596 
4597         if (seconds_into_currentyear >= SEC_IN_AUG)
4598         {
4599             current_date_time_ptr -> month = SEPTEMBER;
4600             seconds_into_currentyear -= SEC_IN_AUG;
4601         }
4602         else break;
4603 
4604         if (seconds_into_currentyear >= SEC_IN_SEP)
4605         {
4606             current_date_time_ptr -> month = OCTOBER;
4607             seconds_into_currentyear -= SEC_IN_SEP;
4608         }
4609         else break;
4610 
4611         if (seconds_into_currentyear >= SEC_IN_OCT)
4612         {
4613             current_date_time_ptr -> month = NOVEMBER;
4614             seconds_into_currentyear -= SEC_IN_OCT;
4615         }
4616         else break;
4617 
4618         if (seconds_into_currentyear >= SEC_IN_NOV)
4619         {
4620             current_date_time_ptr -> month = DECEMBER;
4621             seconds_into_currentyear -= SEC_IN_NOV;
4622         }
4623         else break;
4624 
4625         /* We should not have more than the seconds in december or there is an error. */
4626         if (seconds_into_currentyear > SEC_IN_DEC)
4627         {
4628 
4629             /* Return the error status. */
4630             return NX_SNTP_ERROR_CONVERTING_DATETIME;
4631         }
4632         else break;
4633     }
4634 
4635     /* Time is now in the current month. */
4636     seconds_into_currentmonth = seconds_into_currentyear;
4637 
4638     /* Compute how many complete days the time goes into the current month and
4639        add one for the current day. */
4640     current_date_time_ptr -> day = seconds_into_currentmonth/SECONDS_PER_DAY + 1;
4641 
4642     /* Compute the number of seconds into the current day. */
4643     seconds_into_currentday = seconds_into_currentmonth % SECONDS_PER_DAY;
4644 
4645     /* Compute the number of complete hours into the current day we are. */
4646     current_date_time_ptr -> hour = seconds_into_currentday/SECONDS_PER_HOUR;
4647 
4648     /* Compute the number of seconds into the current hour. */
4649     seconds_into_currenthour = seconds_into_currentday % SECONDS_PER_HOUR;
4650 
4651     /* Break this down into minutes. */
4652     current_date_time_ptr -> minute = seconds_into_currenthour/SECONDS_PER_MINUTE;
4653 
4654     /* Finally the remainder is the seconds. */
4655     current_date_time_ptr -> second = seconds_into_currenthour % SECONDS_PER_MINUTE;
4656 
4657     /* Convert time fraction field into milliseconds.  */
4658     _nx_sntp_client_utility_convert_fraction_to_msecs((ULONG *)(&(current_date_time_ptr -> millisecond)), current_NTP_time_ptr);
4659 
4660     return NX_SUCCESS;
4661 #endif
4662 }
4663 
4664 
4665 /**************************************************************************/
4666 /*                                                                        */
4667 /*  FUNCTION                                               RELEASE        */
4668 /*                                                                        */
4669 /*    _nxe_sntp_client_utility_display_date_time          PORTABLE C      */
4670 /*                                                           6.1          */
4671 /*  AUTHOR                                                                */
4672 /*                                                                        */
4673 /*    Yuxin Zhou, Microsoft Corporation                                   */
4674 /*                                                                        */
4675 /*  DESCRIPTION                                                           */
4676 /*                                                                        */
4677 /*  This function performs error checking services on the display date    */
4678 /*  time service.                                                         */
4679 /*                                                                        */
4680 /*   INPUT                                                                */
4681 /*                                                                        */
4682 /*    client_ptr                        Pointer to SNTP Client            */
4683 /*    buffer                            Pointer to string buffer          */
4684 /*    length                            Size of the string buffer         */
4685 /*                                                                        */
4686 /*  OUTPUT                                                                */
4687 /*                                                                        */
4688 /*    NX_PTR_ERROR                     Invalid pointer input              */
4689 /*    NX_SNTP_PARAM_ERROR              Invalid non pointer input          */
4690 /*    status                           Actual completion status           */
4691 /*                                                                        */
4692 /*  CALLS                                                                 */
4693 /*                                                                        */
4694 /*    _nx_sntp_client_utility_display_date_time                           */
4695 /*                                     Actual display date/time service   */
4696 /*                                                                        */
4697 /*  CALLED BY                                                             */
4698 /*                                                                        */
4699 /*    Application                                                         */
4700 /*                                                                        */
4701 /*  RELEASE HISTORY                                                       */
4702 /*                                                                        */
4703 /*    DATE              NAME                      DESCRIPTION             */
4704 /*                                                                        */
4705 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4706 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4707 /*                                            resulting in version 6.1    */
4708 /*                                                                        */
4709 /**************************************************************************/
_nxe_sntp_client_utility_display_date_time(NX_SNTP_CLIENT * client_ptr,CHAR * buffer,UINT length)4710 UINT _nxe_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length)
4711 {
4712 
4713 UINT status;
4714 
4715 
4716     /* Check for invalid pointer input.  */
4717     if ((client_ptr == NX_NULL) || (buffer == NX_NULL))
4718     {
4719 
4720         /* Return pointer error.  */
4721         return NX_PTR_ERROR;
4722     }
4723 
4724     /* Check for invalid parameter input.  */
4725     if (length == 0)
4726     {
4727 
4728         /* Return parameter error.  */
4729         return NX_SNTP_PARAM_ERROR;
4730     }
4731 
4732     /* Call the actual display time service.  */
4733     status = _nx_sntp_client_utility_display_date_time(client_ptr, buffer, length);
4734 
4735     /* Return completion status.  */
4736     return status;
4737 }
4738 
4739 
4740 
4741 /**************************************************************************/
4742 /*                                                                        */
4743 /*  FUNCTION                                               RELEASE        */
4744 /*                                                                        */
4745 /*    _nxe_sntp_client_request_unicast_time               PORTABLE C      */
4746 /*                                                           6.1          */
4747 /*  AUTHOR                                                                */
4748 /*                                                                        */
4749 /*    Yuxin Zhou, Microsoft Corporation                                   */
4750 /*                                                                        */
4751 /*  DESCRIPTION                                                           */
4752 /*                                                                        */
4753 /*    This function performs error checking for the service that          */
4754 /*    forwards a unicast request from the SNTP Client application.        */
4755 /*                                                                        */
4756 /*   INPUT                                                                */
4757 /*                                                                        */
4758 /*    client_ptr                       Pointer to Client struct           */
4759 /*    wait_option                      Time to wait for response (ticks)  */
4760 /*                                                                        */
4761 /*  OUTPUT                                                                */
4762 /*                                                                        */
4763 /*    NX_PTR_ERROR                      Invalid pointer input             */
4764 /*    status                            Actual completion status          */
4765 /*                                                                        */
4766 /*  CALLED BY                                                             */
4767 /*                                                                        */
4768 /*    Application Code                                                    */
4769 /*                                                                        */
4770 /*  RELEASE HISTORY                                                       */
4771 /*                                                                        */
4772 /*    DATE              NAME                      DESCRIPTION             */
4773 /*                                                                        */
4774 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4775 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4776 /*                                            resulting in version 6.1    */
4777 /*                                                                        */
4778 /**************************************************************************/
_nxe_sntp_client_request_unicast_time(NX_SNTP_CLIENT * client_ptr,UINT wait_option)4779 UINT _nxe_sntp_client_request_unicast_time(NX_SNTP_CLIENT *client_ptr, UINT wait_option)
4780 {
4781 
4782 UINT status;
4783 
4784     /* Check for invalid pointer input. */
4785     if (client_ptr == NX_NULL)
4786     {
4787         return NX_PTR_ERROR;
4788     }
4789 
4790     status = _nx_sntp_client_request_unicast_time(client_ptr, wait_option);
4791 
4792     return status;
4793 }
4794 
4795 
4796 /**************************************************************************/
4797 /*                                                                        */
4798 /*  FUNCTION                                               RELEASE        */
4799 /*                                                                        */
4800 /*    _nx_sntp_client_request_unicast_time                PORTABLE C      */
4801 /*                                                           6.1          */
4802 /*  AUTHOR                                                                */
4803 /*                                                                        */
4804 /*    Yuxin Zhou, Microsoft Corporation                                   */
4805 /*                                                                        */
4806 /*  DESCRIPTION                                                           */
4807 /*                                                                        */
4808 /*    This function sends a unicast request regardless if the SNTP Client */
4809 /*    is configured for unicast or broadcast mode. After sending the      */
4810 /*    request, the function waits for the specified time for a response.  */
4811 /*                                                                        */
4812 /*    If received, the SNTP Server response is processed as it normally is*/
4813 /*    for valid SNTP data, and applied to the SNTP Client's notion of time*/
4814 /*    "local time".                                                       */
4815 /*                                                                        */
4816 /*    This will not interfere with subsequent unicast requests in unicast */
4817 /*    mode, or the processing of periodic updates in broadcast mode.      */
4818 /*                                                                        */
4819 /*   INPUT                                                                */
4820 /*                                                                        */
4821 /*    client_ptr                       Pointer to Client struct           */
4822 /*    wait_option                      Time to wait for response (ticks)  */
4823 /*                                                                        */
4824 /*  OUTPUT                                                                */
4825 /*                                                                        */
4826 /*    NX_PTR_ERROR                      Invalid pointer input             */
4827 /*    status                            Actual completion status          */
4828 /*                                                                        */
4829 /*  CALLED BY                                                             */
4830 /*                                                                        */
4831 /*    Application Code                                                    */
4832 /*                                                                        */
4833 /*  RELEASE HISTORY                                                       */
4834 /*                                                                        */
4835 /*    DATE              NAME                      DESCRIPTION             */
4836 /*                                                                        */
4837 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4838 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4839 /*                                            resulting in version 6.1    */
4840 /*                                                                        */
4841 /**************************************************************************/
_nx_sntp_client_request_unicast_time(NX_SNTP_CLIENT * client_ptr,UINT wait_option)4842 UINT _nx_sntp_client_request_unicast_time(NX_SNTP_CLIENT *client_ptr, UINT wait_option)
4843 {
4844 
4845 UINT status;
4846 
4847 
4848     /* Make sure the client is started. */
4849     if (!client_ptr -> nx_sntp_client_started)
4850     {
4851         return NX_SNTP_CLIENT_NOT_STARTED;
4852     }
4853 
4854     /* Create and send a unicast request.  */
4855     status = _nx_sntp_client_send_unicast_request(client_ptr);
4856 
4857     if (status != NX_SUCCESS)
4858     {
4859         return status;
4860     }
4861 
4862     /* Wait to receive a response. */
4863     status = _nx_sntp_client_receive_time_update(client_ptr, wait_option);
4864 
4865     /* If we got a valid SNTP packet, process the data. */
4866     if (status == NX_SUCCESS)
4867     {
4868 
4869         /* Process the server update packet and apply to local time if valid.  */
4870         status =  _nx_sntp_client_process_update_packet(client_ptr);
4871     }
4872 
4873     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
4874     /* Return completion status.  */
4875     return status;
4876 }
4877 
4878 /**************************************************************************/
4879 /*                                                                        */
4880 /*  FUNCTION                                               RELEASE        */
4881 /*                                                                        */
4882 /*    _nx_sntp_client_utility_display_date_time           PORTABLE C      */
4883 /*                                                           6.2.0        */
4884 /*  AUTHOR                                                                */
4885 /*                                                                        */
4886 /*    Yuxin Zhou, Microsoft Corporation                                   */
4887 /*                                                                        */
4888 /*  DESCRIPTION                                                           */
4889 /*                                                                        */
4890 /*  This function converts an NTP time data into a month-date-year time,  */
4891 /*  including seconds and second fraction string. It is intended as a     */
4892 /*  human readable representation of NTP time.  The caller must supply a  */
4893 /*  pointer to a buffer large enough (40 chars is enough) to hold the     */
4894 /*  string and define the NX_SNTP_CURRENT_YEAR parameter, usually as the  */
4895 /*  current year.                                                         */
4896 /*                                                                        */
4897 /*   INPUT                                                                */
4898 /*                                                                        */
4899 /*    client_ptr                        Pointer to SNTP Client            */
4900 /*    buffer                            Pointer to string buffer          */
4901 /*    length                            Size of the string buffer         */
4902 /*                                                                        */
4903 /*  OUTPUT                                                                */
4904 /*                                                                        */
4905 /*    NX_SUCCESS                        Successful completion status      */
4906 /*    NX_SNTP_INVALID_DATETIME_BUFFER   Buffer not large enough           */
4907 /*    NX_SNTP_ERROR_CONVERTING_DATETIME Internal error converting NTP time*/
4908 /*    status                            Convert seconds completion status */
4909 /*                                                                        */
4910 /*  CALLS                                                                 */
4911 /*    _nx_sntp_client_utility_convert_seconds_to_date                     */
4912 /*                                      Converts seconds to year, month   */
4913 /*    _nx_utility_uint_to_string        Converts number to ascii text     */
4914 /*                                                                        */
4915 /*  CALLED BY                                                             */
4916 /*                                                                        */
4917 /*    Application                                                         */
4918 /*                                                                        */
4919 /*  RELEASE HISTORY                                                       */
4920 /*                                                                        */
4921 /*    DATE              NAME                      DESCRIPTION             */
4922 /*                                                                        */
4923 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4924 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4925 /*                                            resulting in version 6.1    */
4926 /*  08-02-2021     Yuxin Zhou               Modified comment(s),          */
4927 /*                                            improved the logic of       */
4928 /*                                            converting number to string,*/
4929 /*                                            resulting in version 6.1.8  */
4930 /*  10-31-2022     Yuxin Zhou               Modified comment(s), fixed    */
4931 /*                                            the typo of August string,  */
4932 /*                                            resulting in version 6.2.0  */
4933 /*                                                                        */
4934 /**************************************************************************/
_nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT * client_ptr,CHAR * buffer,UINT length)4935 UINT _nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length)
4936 {
4937 
4938 UINT                status;
4939 UINT                offset;
4940 UINT                return_length;
4941 NX_SNTP_DATE_TIME   DisplayTime;
4942 const CHAR         *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
4943                                   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
4944 
4945 
4946 #ifndef  NX_SNTP_CURRENT_YEAR
4947     return NX_SNTP_ERROR_CONVERTING_DATETIME;
4948 #else
4949 
4950     /* Verify the client has set a local time. */
4951     if (client_ptr -> nx_sntp_client_local_ntp_time.seconds == 0)
4952     {
4953        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4954     }
4955 
4956     status = _nx_sntp_client_utility_convert_seconds_to_date(&(client_ptr -> nx_sntp_client_local_ntp_time), NX_SNTP_CURRENT_YEAR, &DisplayTime);
4957     if (status != NX_SUCCESS)
4958     {
4959         return status;
4960     }
4961 
4962     /* Check if we have a long enough buffer. */
4963     if (length < 5)
4964     {
4965 
4966         /* Return the error status. */
4967         return NX_SNTP_INVALID_DATETIME_BUFFER;
4968     }
4969 
4970     /* Decrease length for terminal zero. */
4971     length--;
4972 
4973     /* Substitute numeric month to name of the month. */
4974     if ((DisplayTime.month < JANUARY) || (DisplayTime.month > DECEMBER))
4975     {
4976        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4977     }
4978     buffer[0] = months[DisplayTime.month - JANUARY][0];
4979     buffer[1] = months[DisplayTime.month - JANUARY][1];
4980     buffer[2] = months[DisplayTime.month - JANUARY][2];
4981     buffer[3] = ' ';
4982     offset = 4;
4983 
4984     /* Write in the rest of the data as numeric from the Date Time objext. */
4985     return_length = _nx_utility_uint_to_string(DisplayTime.day, 10, &buffer[offset], length - offset);
4986     offset += return_length;
4987     if ((return_length == 0) || ((length - offset) < 2))
4988     {
4989        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4990     }
4991     buffer[offset++] = ',';
4992     buffer[offset++] = ' ';
4993     return_length = _nx_utility_uint_to_string(DisplayTime.year, 10, &buffer[offset], length - offset);
4994     offset += return_length;
4995     if ((return_length == 0) || ((length - offset) < 1))
4996     {
4997        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4998     }
4999     buffer[offset++] = ' ';
5000     return_length = _nx_utility_uint_to_string(DisplayTime.hour, 10, &buffer[offset], length - offset);
5001     offset += return_length;
5002     if ((return_length == 0) || ((length - offset) < 1))
5003     {
5004        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5005     }
5006     buffer[offset++] = ':';
5007     return_length = _nx_utility_uint_to_string(DisplayTime.minute, 10, &buffer[offset], length - offset);
5008     offset += return_length;
5009     if ((return_length == 0) || ((length - offset) < 1))
5010     {
5011        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5012     }
5013     buffer[offset++] = ':';
5014     return_length = _nx_utility_uint_to_string(DisplayTime.second, 10, &buffer[offset], length - offset);
5015     offset += return_length;
5016     if ((return_length == 0) || ((length - offset) < 1))
5017     {
5018        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5019     }
5020     buffer[offset++] = '.';
5021     return_length = _nx_utility_uint_to_string(DisplayTime.millisecond, 10, &buffer[offset], length - offset);
5022     offset += return_length;
5023     if ((return_length == 0) || ((length - offset) < 5))
5024     {
5025        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5026     }
5027     buffer[offset++] = ' ';
5028     buffer[offset++] = 'U';
5029     buffer[offset++] = 'T';
5030     buffer[offset++] = 'C';
5031     buffer[offset++] = ' ';
5032     buffer[offset] = '\0';
5033 
5034 #endif
5035 
5036     return NX_SUCCESS;
5037 }
5038 
5039 
5040 /**************************************************************************/
5041 /*                                                                        */
5042 /*  FUNCTION                                               RELEASE        */
5043 /*                                                                        */
5044 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time       PORTABLE C      */
5045 /*                                                           6.1          */
5046 /*  AUTHOR                                                                */
5047 /*                                                                        */
5048 /*    Yuxin Zhou, Microsoft Corporation                                   */
5049 /*                                                                        */
5050 /*  DESCRIPTION                                                           */
5051 /*                                                                        */
5052 /*   This function adds msecs (not necessarily a positive value and not   */
5053 /*   limited to less than a second) to an NTP time value. Msecs cannot be */
5054 /*   added directly to the fraction field in the NTP time field because   */
5055 /*   this field is represented in fixed point notation.  Arithmetic       */
5056 /*   overflow and loss of sign errors as a result of adding numbers are   */
5057 /*   handled as errors.                                                   */
5058 /*                                                                        */
5059 /*   INPUT                                                                */
5060 /*                                                                        */
5061 /*    timeA_ptr                        Pointer to NTP time operand        */
5062 /*    msecs_to_add                     Time (msecs) to add                */
5063 /*                                                                        */
5064 /*  OUTPUT                                                                */
5065 /*                                                                        */
5066 /*    NX_SUCCESS                       Successful completion status       */
5067 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result adding numbers     */
5068 /*    NX_SNTP_INVALID_TIME             An invalid result (e.g. negative   */
5069 /*                                        time) from adding numbers       */
5070 /*    status                           Actual completion status           */
5071 /*                                                                        */
5072 /*  CALLS                                                                 */
5073 /*                                                                        */
5074 /*    None                                                                */
5075 /*                                                                        */
5076 /*  CALLED BY                                                             */
5077 /*                                                                        */
5078 /*   _nx_sntp_client_process_time_data  Apply server time to local time   */
5079 /*                                                                        */
5080 /*  RELEASE HISTORY                                                       */
5081 /*                                                                        */
5082 /*    DATE              NAME                      DESCRIPTION             */
5083 /*                                                                        */
5084 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5085 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5086 /*                                            resulting in version 6.1    */
5087 /*                                                                        */
5088 /**************************************************************************/
5089 
_nx_sntp_client_utility_add_msecs_to_ntp_time(NX_SNTP_TIME * timeA_ptr,LONG msecs_to_add)5090 UINT  _nx_sntp_client_utility_add_msecs_to_ntp_time(NX_SNTP_TIME *timeA_ptr, LONG msecs_to_add)
5091 {
5092 
5093 UINT  status;
5094 ULONG timeA_usec;
5095 LONG  seconds;
5096 LONG  usecs;
5097 
5098 
5099     /* Separate msecs_to_add into seconds and milliseconds.  */
5100     seconds = msecs_to_add / 1000;
5101     usecs = (msecs_to_add % 1000) * 1000;
5102 
5103     /* Are we adding a positive number?  */
5104     if (msecs_to_add > 0)
5105     {
5106         /* Yes; check for overflow before trying to add seconds to the TimeA operand.  */
5107         status = _nx_sntp_client_utility_addition_overflow_check(timeA_ptr -> seconds, (ULONG)seconds);
5108 
5109         /* Check for error (overflow).  */
5110         if (status != NX_SUCCESS)
5111         {
5112 
5113             /* Return the error condition.  */
5114             return status;
5115         }
5116     }
5117     /* Check if a negative number larger than the timeA operand is being added (creates negative time!)*/
5118     else if (timeA_ptr -> seconds < (ULONG)abs(seconds))
5119     {
5120 
5121         /* Yes; return the error condition.  */
5122         return NX_SNTP_INVALID_TIME;
5123     }
5124 
5125     /* Ok to add seconds to the NTP time seconds.  */
5126     timeA_ptr -> seconds += (ULONG)seconds;
5127 
5128     /* Next get the usecs from the timeA operand (always positive and < 1000000).  */
5129     _nx_sntp_client_utility_fraction_to_usecs(timeA_ptr -> fraction, &timeA_usec);
5130 
5131     /* In case usecs is < 0, we might have to perform a carry.  */
5132     if ((usecs + (LONG)timeA_usec) < 0)
5133     {
5134         /* Perform a carry by subtracting a second from timeA seconds...*/
5135         timeA_ptr -> seconds--;
5136 
5137         /* And adding it to the usecs of timeA.  */
5138         timeA_usec += 1000000;
5139     }
5140 
5141     /* OK to add the usecs up.  */
5142     usecs += (LONG)timeA_usec;
5143 
5144     /* Check for a positive carry over into seconds.  */
5145     if (usecs >= 1000000)
5146     {
5147         /* Yes there's a carry; check for possibility of overflow
5148            before adding carry (unlikely for another 30 years).  */
5149         if (timeA_ptr -> seconds == 0xFFFFFFFF)
5150         {
5151 
5152             return NX_SNTP_OVERFLOW_ERROR;
5153         }
5154 
5155         /* OK to increment the seconds.  */
5156         timeA_ptr -> seconds++;
5157 
5158         /* Set milliseconds to remainder.  */
5159         usecs = usecs % 1000000;
5160     }
5161 
5162     /* Convert usecs to the fixed point notation fraction and store in TimeA fraction.  */
5163     status = _nx_sntp_client_utility_usecs_to_fraction((ULONG)usecs, &(timeA_ptr ->fraction));
5164 
5165     /* Return completion status.  */
5166     return status;
5167 }
5168 
5169 
5170 /**************************************************************************/
5171 /*                                                                        */
5172 /*  FUNCTION                                               RELEASE        */
5173 /*                                                                        */
5174 /*    _nxe_sntp_client_receiving_updates                  PORTABLE C      */
5175 /*                                                           6.1          */
5176 /*  AUTHOR                                                                */
5177 /*                                                                        */
5178 /*    Yuxin Zhou, Microsoft Corporation                                   */
5179 /*                                                                        */
5180 /*  DESCRIPTION                                                           */
5181 /*                                                                        */
5182 /*   This function performs error checking for the get SNTP get receive   */
5183 /*   status service.                                                      */
5184 /*                                                                        */
5185 /*   INPUT                                                                */
5186 /*                                                                        */
5187 /*    client_ptr                       Pointer to SNTP client instance    */
5188 /*    receive_status                   Pointer to server status           */
5189 /*                                                                        */
5190 /*  OUTPUT                                                                */
5191 /*                                                                        */
5192 /*    NX_PTR_ERROR                     Invalid input status               */
5193 /*    status                           Actual completion status           */
5194 /*                                                                        */
5195 /*  CALLS                                                                 */
5196 /*                                                                        */
5197 /*    _nx_sntp_client_receiving_updates                                   */
5198 /*                                     Actual get server status service   */
5199 /*                                                                        */
5200 /*  CALLED BY                                                             */
5201 /*                                                                        */
5202 /*    Application Code                                                    */
5203 /*                                                                        */
5204 /*  RELEASE HISTORY                                                       */
5205 /*                                                                        */
5206 /*    DATE              NAME                      DESCRIPTION             */
5207 /*                                                                        */
5208 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5209 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5210 /*                                            resulting in version 6.1    */
5211 /*                                                                        */
5212 /**************************************************************************/
_nxe_sntp_client_receiving_updates(NX_SNTP_CLIENT * client_ptr,UINT * receive_status)5213 UINT _nxe_sntp_client_receiving_updates(NX_SNTP_CLIENT *client_ptr, UINT *receive_status)
5214 {
5215 
5216 UINT status;
5217 
5218     /* Check for the validity of input parameter.  */
5219     if ((client_ptr == NX_NULL) || (receive_status == NX_NULL))
5220     {
5221 
5222         /* Return error status.  */
5223         return(NX_PTR_ERROR);
5224     }
5225 
5226     status = _nx_sntp_client_receiving_updates(client_ptr, receive_status);
5227 
5228     return status;
5229 }
5230 
5231 /**************************************************************************/
5232 /*                                                                        */
5233 /*  FUNCTION                                               RELEASE        */
5234 /*                                                                        */
5235 /*    _nx_sntp_client_receiving_updates                   PORTABLE C      */
5236 /*                                                           6.1          */
5237 /*  AUTHOR                                                                */
5238 /*                                                                        */
5239 /*    Yuxin Zhou, Microsoft Corporation                                   */
5240 /*                                                                        */
5241 /*  DESCRIPTION                                                           */
5242 /*                                                                        */
5243 /*   This function returns the status of the Client SNTP server. If the   */
5244 /*   client has not received a valid update within the NX_SNTP_CLIENT_MAX_*/
5245 /*   _TIME_LAPSE interval or if the number of invalid updates received by */
5246 /*   the client exceeds the NX_SNTP_CLIENT_INVALID_UPDATE_LIMIT limit,    */
5247 /*   the status is set to NX_FALSE.  If the Client has not yet received   */
5248 /*   its first valid update from the current SNTP server, status is set to*/
5249 /*   false.                                                               */
5250 /*                                                                        */
5251 /*   INPUT                                                                */
5252 /*                                                                        */
5253 /*    client_ptr                       Pointer to SNTP client instance    */
5254 /*    receive_status                   Pointer to receive_status          */
5255 /*                                     NX_FALSE: not receiving updates    */
5256 /*                                     NX_TRUE: receiving valid updates   */
5257 /*                                                                        */
5258 /*  OUTPUT                                                                */
5259 /*                                                                        */
5260 /*    NX_PTR_ERROR                     Invalid input status               */
5261 /*    status                           Actual completion status           */
5262 /*                                                                        */
5263 /*  CALLS                                                                 */
5264 /*                                                                        */
5265 /*    tx_mutex_get                     Get the SNTP mutex                 */
5266 /*    tx_mutex_put                     Release the SNTP mutex             */
5267 /*                                                                        */
5268 /*  CALLED BY                                                             */
5269 /*                                                                        */
5270 /*    Application Code                                                    */
5271 /*                                                                        */
5272 /*  RELEASE HISTORY                                                       */
5273 /*                                                                        */
5274 /*    DATE              NAME                      DESCRIPTION             */
5275 /*                                                                        */
5276 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5277 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5278 /*                                            resulting in version 6.1    */
5279 /*                                                                        */
5280 /**************************************************************************/
_nx_sntp_client_receiving_updates(NX_SNTP_CLIENT * client_ptr,UINT * receive_status)5281 UINT _nx_sntp_client_receiving_updates(NX_SNTP_CLIENT *client_ptr, UINT *receive_status)
5282 {
5283 
5284 
5285     /* Get the SNTP mutex.  */
5286     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
5287 
5288     /* Verify the client's SNTP server is valid, and the Client has received at least one valid udpate from it. */
5289     *receive_status = ((client_ptr -> nx_sntp_valid_server_status == NX_TRUE) && (client_ptr -> nx_sntp_client_first_update_pending == NX_FALSE));
5290 
5291     /* Release the SNTP mutex.  */
5292     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
5293 
5294     /* Return completion status.  */
5295     return(NX_SUCCESS);
5296 
5297 }
5298 
5299 
5300 /**************************************************************************/
5301 /*                                                                        */
5302 /*  FUNCTION                                               RELEASE        */
5303 /*                                                                        */
5304 /*    _nxe_sntp_client_set_local_time                     PORTABLE C      */
5305 /*                                                           6.1          */
5306 /*  AUTHOR                                                                */
5307 /*                                                                        */
5308 /*    Yuxin Zhou, Microsoft Corporation                                   */
5309 /*                                                                        */
5310 /*  DESCRIPTION                                                           */
5311 /*                                                                        */
5312 /*   This function performs error checking for the set client local time  */
5313 /*   service.                                                             */
5314 /*                                                                        */
5315 /*   INPUT                                                                */
5316 /*                                                                        */
5317 /*    client_ptr                       Pointer to SNTP Client             */
5318 /*    seconds                          Local time seconds component       */
5319 /*    fraction                         Local time fraction component      */
5320 /*                                                                        */
5321 /*  OUTPUT                                                                */
5322 /*                                                                        */
5323 /*    status                           Actual completion status           */
5324 /*    NX_PTR_ERROR                     Invalid pointer input              */
5325 /*                                                                        */
5326 /*  CALLS                                                                 */
5327 /*                                                                        */
5328 /*    _nx_sntp_client_set_local_time  Actual set client local time service*/
5329 /*                                                                        */
5330 /*  CALLED BY                                                             */
5331 /*                                                                        */
5332 /*    Application Code                                                    */
5333 /*                                                                        */
5334 /*  RELEASE HISTORY                                                       */
5335 /*                                                                        */
5336 /*    DATE              NAME                      DESCRIPTION             */
5337 /*                                                                        */
5338 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5339 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5340 /*                                            resulting in version 6.1    */
5341 /*                                                                        */
5342 /**************************************************************************/
_nxe_sntp_client_set_local_time(NX_SNTP_CLIENT * client_ptr,ULONG seconds,ULONG fraction)5343 UINT  _nxe_sntp_client_set_local_time(NX_SNTP_CLIENT *client_ptr, ULONG seconds, ULONG fraction)
5344 {
5345 
5346 UINT status;
5347 
5348 
5349     /* Check for invalid input. */
5350    if (client_ptr == NX_NULL)
5351    {
5352        return NX_PTR_ERROR;
5353    }
5354 
5355    /* Call the actual service. */
5356    status = _nx_sntp_client_set_local_time(client_ptr, seconds, fraction);
5357 
5358    /* Return completion status. */
5359    return status;
5360 }
5361 
5362 
5363 /**************************************************************************/
5364 /*                                                                        */
5365 /*  FUNCTION                                               RELEASE        */
5366 /*                                                                        */
5367 /*    _nx_sntp_client_set_local_time                      PORTABLE C      */
5368 /*                                                           6.1          */
5369 /*  AUTHOR                                                                */
5370 /*                                                                        */
5371 /*    Yuxin Zhou, Microsoft Corporation                                   */
5372 /*                                                                        */
5373 /*  DESCRIPTION                                                           */
5374 /*                                                                        */
5375 /*   This function takes the seconds and fraction input from the caller   */
5376 /*   (or more accurately the independent time clock source, and applies it*/
5377 /*   to the SNTP client local time.                                       */
5378 /*                                                                        */
5379 /*   In between SNTP server updates, it is expected that the SNTP Client  */
5380 /*   host application will update the SNTP client local time from the     */
5381 /*   independent time source (e.g. real time clock on board) and then     */
5382 /*   use the SNTP Server time updates to correct the local time for drifts*/
5383 /*   from the correct time.                                               */
5384 /*                                                                        */
5385 /*   It can also set the SNTP Client's base time before starting up the   */
5386 /*   SNTP Client. If the host application cannot obtain a base time, the  */
5387 /*   SNTP Client will take the first SNTP update as the absolute time. If */
5388 /*   the host application does have a real time clock or independent time */
5389 /*   keeper, the SNTP client can set a large enough max adjustment that   */
5390 /*   any Server time udpate will be accepted to the SNTP Client. This     */
5391 /*   leaves the SNTP Client completely dependent on the network and SNTP  */
5392 /*   Server, plus it is vulnerable to rogue SNTP packets.                 */
5393 /*                                                                        */
5394 /*   INPUT                                                                */
5395 /*                                                                        */
5396 /*    client_ptr                       Pointer to SNTP Client             */
5397 /*    seconds                          Local time seconds component       */
5398 /*    fraction                         Local time fraction component      */
5399 /*                                                                        */
5400 /*  OUTPUT                                                                */
5401 /*                                                                        */
5402 /*    NX_SUCCESS                       Successful completion status       */
5403 /*                                                                        */
5404 /*  CALLS                                                                 */
5405 /*                                                                        */
5406 /*    None                                                                */
5407 /*                                                                        */
5408 /*  CALLED BY                                                             */
5409 /*                                                                        */
5410 /*    Application Code                                                    */
5411 /*                                                                        */
5412 /*  RELEASE HISTORY                                                       */
5413 /*                                                                        */
5414 /*    DATE              NAME                      DESCRIPTION             */
5415 /*                                                                        */
5416 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5417 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5418 /*                                            resulting in version 6.1    */
5419 /*                                                                        */
5420 /**************************************************************************/
_nx_sntp_client_set_local_time(NX_SNTP_CLIENT * client_ptr,ULONG seconds,ULONG fraction)5421 UINT  _nx_sntp_client_set_local_time(NX_SNTP_CLIENT *client_ptr, ULONG seconds, ULONG fraction)
5422 {
5423 
5424 
5425     client_ptr -> nx_sntp_client_local_ntp_time.seconds = seconds;
5426     client_ptr -> nx_sntp_client_local_ntp_time.fraction = fraction;
5427     client_ptr -> nx_sntp_client_local_ntp_time_elapsed = 0;
5428 
5429     /* Return completion status.  */
5430     return NX_SUCCESS;
5431 }
5432 
5433 
5434 /**************************************************************************/
5435 /*                                                                        */
5436 /*  FUNCTION                                               RELEASE        */
5437 /*                                                                        */
5438 /*    _nxe_sntp_client_set_time_update_notify             PORTABLE C      */
5439 /*                                                           6.1          */
5440 /*  AUTHOR                                                                */
5441 /*                                                                        */
5442 /*    Yuxin Zhou, Microsoft Corporation                                   */
5443 /*                                                                        */
5444 /*  DESCRIPTION                                                           */
5445 /*                                                                        */
5446 /*    This function performs error checking for the set time update       */
5447 /*    callback service.                                                   */
5448 /*                                                                        */
5449 /*   INPUT                                                                */
5450 /*                                                                        */
5451 /*    client_ptr                        Pointer to Client struct          */
5452 /*    time_update_cb                    Pointer to callback when Client   */
5453 /*                                        receives an SNTP update         */
5454 /*                                                                        */
5455 /*  OUTPUT                                                                */
5456 /*                                                                        */
5457 /*    NX_SUCCESS                        Successful completion status      */
5458 /*    NX_PTR_ERROR                      Invalid pointer input             */
5459 /*                                                                        */
5460 /*  CALLS                                                                 */
5461 /*                                                                        */
5462 /*    _nx_sntp_client_set_time_update_notify                              */
5463 /*                                                                        */
5464 /*  CALLED BY                                                             */
5465 /*                                                                        */
5466 /*    Application                                                         */
5467 /*                                                                        */
5468 /*  RELEASE HISTORY                                                       */
5469 /*                                                                        */
5470 /*    DATE              NAME                      DESCRIPTION             */
5471 /*                                                                        */
5472 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5473 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5474 /*                                            resulting in version 6.1    */
5475 /*                                                                        */
5476 /**************************************************************************/
_nxe_sntp_client_set_time_update_notify(NX_SNTP_CLIENT * client_ptr,VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE * time_update_ptr,NX_SNTP_TIME * local_time))5477 UINT    _nxe_sntp_client_set_time_update_notify(NX_SNTP_CLIENT *client_ptr,
5478                        VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE *time_update_ptr, NX_SNTP_TIME *local_time))
5479 {
5480 
5481 UINT status;
5482 
5483 
5484     /* Check for valid input. */
5485     if ((client_ptr == NX_NULL) || (time_update_cb == NX_NULL))
5486     {
5487         return NX_PTR_ERROR;
5488     }
5489 
5490     status = _nx_sntp_client_set_time_update_notify(client_ptr, time_update_cb);
5491 
5492     return status;
5493 }
5494 
5495 /**************************************************************************/
5496 /*                                                                        */
5497 /*  FUNCTION                                               RELEASE        */
5498 /*                                                                        */
5499 /*    _nx_sntp_client_set_time_update_notify              PORTABLE C      */
5500 /*                                                           6.1          */
5501 /*  AUTHOR                                                                */
5502 /*                                                                        */
5503 /*    Yuxin Zhou, Microsoft Corporation                                   */
5504 /*                                                                        */
5505 /*  DESCRIPTION                                                           */
5506 /*                                                                        */
5507 /*    This function notifies the application of a valid SNTP time update. */
5508 /*                                                                        */
5509 /*   INPUT                                                                */
5510 /*                                                                        */
5511 /*    client_ptr                        Pointer to Client struct          */
5512 /*    time_update_cb                    Pointer to callback when Client   */
5513 /*                                        receives an SNTP update         */
5514 /*                                                                        */
5515 /*  OUTPUT                                                                */
5516 /*                                                                        */
5517 /*    NX_SUCCESS                        Successful completion status      */
5518 /*                                                                        */
5519 /*  CALLS                                                                 */
5520 /*                                                                        */
5521 /*    None                                                                */
5522 /*                                                                        */
5523 /*  CALLED BY                                                             */
5524 /*                                                                        */
5525 /*    Application                                                         */
5526 /*                                                                        */
5527 /*  RELEASE HISTORY                                                       */
5528 /*                                                                        */
5529 /*    DATE              NAME                      DESCRIPTION             */
5530 /*                                                                        */
5531 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5532 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5533 /*                                            resulting in version 6.1    */
5534 /*                                                                        */
5535 /**************************************************************************/
_nx_sntp_client_set_time_update_notify(NX_SNTP_CLIENT * client_ptr,VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE * time_update_ptr,NX_SNTP_TIME * local_time))5536 UINT    _nx_sntp_client_set_time_update_notify(NX_SNTP_CLIENT *client_ptr,
5537                              VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE *time_update_ptr, NX_SNTP_TIME *local_time))
5538 {
5539 
5540 
5541     client_ptr -> nx_sntp_client_time_update_notify = time_update_cb;
5542 
5543     return NX_SUCCESS;
5544 }
5545 
5546 
5547 
5548 
5549 /**************************************************************************/
5550 /*                                                                        */
5551 /*  FUNCTION                                               RELEASE        */
5552 /*                                                                        */
5553 /*    _nx_sntp_client_utility_get_msec_diff               PORTABLE C      */
5554 /*                                                           6.1          */
5555 /*  AUTHOR                                                                */
5556 /*                                                                        */
5557 /*    Yuxin Zhou, Microsoft Corporation                                   */
5558 /*                                                                        */
5559 /*  DESCRIPTION                                                           */
5560 /*                                                                        */
5561 /*    This function computes the difference in milliseconds between two   */
5562 /*    NTP times, receiving an NTP packet, and transmitting it back.       */
5563 /*    The logic calculates the difference in the seconds component and    */
5564 /*    converts it to milliseconds.  It converts the fraction to useconds  */
5565 /*    and calculates that difference. Useconds are rounded to the nearest */
5566 /*    millisecond.  This logic assumes the transmit time occurs after     */
5567 /*    receive time.                                                       */
5568 /*                                                                        */
5569 /*    The net difference is the difference in milliseconds from the       */
5570 /*    fractions added to (or subtracted from) the difference in           */
5571 /*    milliseconds from the seconds component.                            */
5572 /*                                                                        */
5573 /*    Note that the conversion of useconds to milliseconds may result     */
5574 /*    in the two times' difference to be zero, when they are actually     */
5575 /*    different by useconds.                                              */
5576 /*                                                                        */
5577 /*   INPUT                                                                */
5578 /*                                                                        */
5579 /*    timeReceived_ptr                 NTP time of received message       */
5580 /*    timeTransmit_ptr                 NTP time of transmitted message    */
5581 /*    total_difference_msecs           Millseconds of difference in time  */
5582 /*    pos_diff                         True if Transmit Time >=           */
5583 /*                                          Receive Time                  */
5584 /*                                                                        */
5585 /*  OUTPUT                                                                */
5586 /*                                                                        */
5587 /*    NX_SUCCESS                       Valid transmit/receive times       */
5588 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result                    */
5589 /*    NX_SNTP_INVALID_TIME             Transmit time<receive time seconds */
5590 /*                                                                        */
5591 /*  CALLS                                                                 */
5592 /*                                                                        */
5593 /*    _nx_sntp_client_utility_convert_fraction_to_msecs                   */
5594 /*                                      Convert fraction to milliseconds  */
5595 /*                                                                        */
5596 /*  CALLED BY                                                             */
5597 /*                                                                        */
5598 /*    _nx_sntp_client_apply_sanity_checks                                 */
5599 /*                                     Apply sanity checks to time data   */
5600 /*    _nx_sntp_client_process_time_data                                   */
5601 /*                                     Apply server time to local time    */
5602 /*                                                                        */
5603 /*  RELEASE HISTORY                                                       */
5604 /*                                                                        */
5605 /*    DATE              NAME                      DESCRIPTION             */
5606 /*                                                                        */
5607 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5608 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5609 /*                                            resulting in version 6.1    */
5610 /*                                                                        */
5611 /**************************************************************************/
_nx_sntp_client_utility_get_msec_diff(NX_SNTP_TIME * timeReceived_ptr,NX_SNTP_TIME * timeTransmit_ptr,ULONG * total_difference_msecs,UINT * pos_diff)5612 UINT  _nx_sntp_client_utility_get_msec_diff(NX_SNTP_TIME *timeReceived_ptr, NX_SNTP_TIME *timeTransmit_ptr, ULONG *total_difference_msecs, UINT *pos_diff)
5613 {
5614 
5615 ULONG    usecsReceived, usecsTransmit;
5616 ULONG    msecsReceived, msecsTransmit;
5617 ULONG    seconds_difference_in_msecs;
5618 ULONG    temp;
5619 
5620 
5621     /* Check for overflow with a very large positive difference result.  */
5622     if (timeReceived_ptr -> seconds > timeTransmit_ptr -> seconds)
5623     {
5624 
5625         /* Use a temporary variable to store the difference in the seconds.  */
5626         temp = timeReceived_ptr -> seconds - timeTransmit_ptr -> seconds;
5627         *pos_diff = NX_FALSE;
5628     }
5629     else
5630     {
5631 
5632         /* Reverse the operand to get the absolute difference in the seconds.  */
5633         temp = timeTransmit_ptr -> seconds -timeReceived_ptr -> seconds;
5634         *pos_diff = NX_TRUE;
5635     }
5636 
5637     /* Check for overflow when converting seconds to milliseconds
5638        (0x3E8 = 1000).  */
5639     if (temp > (0xFFFFFFFF / 0x3E8))
5640     {
5641 
5642         /* Return error status.  */
5643         return NX_SNTP_OVERFLOW_ERROR;
5644     }
5645 
5646     /* Convert to msecs.  */
5647     seconds_difference_in_msecs = temp * 1000;
5648 
5649     /* Convert the Received time fraction to usecs and msecs.  */
5650     _nx_sntp_client_utility_fraction_to_usecs(timeReceived_ptr -> fraction, &usecsReceived);
5651 
5652     msecsReceived = usecsReceived / 1000;
5653 
5654     if (usecsReceived % 1000 >= 500)
5655         msecsReceived++;
5656 
5657     /* Convert the Transmit Time fraction to usecs and msecs.  */
5658     _nx_sntp_client_utility_fraction_to_usecs(timeTransmit_ptr -> fraction, &usecsTransmit);
5659 
5660     msecsTransmit = usecsTransmit / 1000;
5661 
5662     if (usecsTransmit % 1000 >= 500)
5663         msecsTransmit++;
5664 
5665     /* Get the difference of the two time stamps' fraction in milliseconds. */
5666     if (timeReceived_ptr -> seconds == timeTransmit_ptr -> seconds)
5667     {
5668 
5669         /* Determine the absolute difference in the millisecond component. */
5670         if (usecsTransmit >= usecsReceived)
5671         {
5672 
5673             *total_difference_msecs = msecsTransmit - msecsReceived;
5674         }
5675         else
5676         {
5677 
5678             /* Transmit time usecs < Received time usecs. */
5679             *pos_diff = NX_FALSE;
5680             *total_difference_msecs = msecsReceived - msecsTransmit;
5681         }
5682     }
5683     else
5684     {
5685 
5686         /* Consider the case where the transmit time seconds is greater. */
5687         if (timeTransmit_ptr -> seconds > timeReceived_ptr -> seconds)
5688         {
5689 
5690             if ( usecsTransmit >= usecsReceived)
5691             {
5692 
5693                 /*  This will add to the total milliseconds' difference. */
5694                *total_difference_msecs = seconds_difference_in_msecs + (msecsTransmit - msecsReceived);
5695             }
5696             else /* (usecsReceived > usecsTransmit) */
5697             {
5698 
5699                 /* This will subtract from the total milliseconds' difference . */
5700                 *total_difference_msecs = seconds_difference_in_msecs - (msecsReceived - msecsTransmit);
5701             }
5702         }
5703 
5704         /* Consider the case where the transmit time seconds is less. */
5705         else
5706         {
5707 
5708             if (usecsReceived >= usecsTransmit)
5709             {
5710 
5711                 /*  This will add to the total milliseconds' difference. */
5712                *total_difference_msecs = seconds_difference_in_msecs + (msecsReceived - msecsTransmit);
5713             }
5714             else /* (usecsTransmit > usecsReceived) */
5715             {
5716 
5717                 /* This will subtract from the total milliseconds' difference . */
5718                 *total_difference_msecs = seconds_difference_in_msecs - (msecsTransmit - msecsReceived);
5719             }
5720         }
5721     }
5722 
5723     /* Return successful completion status.  */
5724     return NX_SUCCESS;
5725 
5726 }
5727 
5728 /**************************************************************************/
5729 /*                                                                        */
5730 /*  FUNCTION                                               RELEASE        */
5731 /*                                                                        */
5732 /*    _nx_sntp_client_utility_is_zero_data                PORTABLE C      */
5733 /*                                                           6.1          */
5734 /*  AUTHOR                                                                */
5735 /*                                                                        */
5736 /*    Yuxin Zhou, Microsoft Corporation                                   */
5737 /*                                                                        */
5738 /*  DESCRIPTION                                                           */
5739 /*                                                                        */
5740 /*   This function tests each byte (UCHAR) of data to be non zero.  The   */
5741 /*   return value indicates if the entire data is zero.                   */
5742 /*                                                                        */
5743 /*   INPUT                                                                */
5744 /*                                                                        */
5745 /*    data                               Pointer to first byte of data    */
5746 /*    size                               Number of bytes in data          */
5747 /*                                                                        */
5748 /*  OUTPUT                                                                */
5749 /*                                                                        */
5750 /*    NX_TRUE                            Each byte of data is zero        */
5751 /*    NX_FALSE                           At least one byte is non zero    */
5752 /*                                                                        */
5753 /*  CALLS                                                                 */
5754 /*                                                                        */
5755 /*    None                                                                */
5756 /*                                                                        */
5757 /*  CALLED BY                                                             */
5758 /*                                                                        */
5759 /*   _nx_sntp_client_apply_sanity_checks Checks SNTP server reply validity*/
5760 /*                                                                        */
5761 /*  RELEASE HISTORY                                                       */
5762 /*                                                                        */
5763 /*    DATE              NAME                      DESCRIPTION             */
5764 /*                                                                        */
5765 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5766 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5767 /*                                            resulting in version 6.1    */
5768 /*                                                                        */
5769 /**************************************************************************/
_nx_sntp_client_utility_is_zero_data(UCHAR * data,UINT size)5770 UINT _nx_sntp_client_utility_is_zero_data(UCHAR *data, UINT size)
5771 {
5772 
5773 UINT i;
5774 UINT is_zero;
5775 
5776 
5777     /* Initialize local variables. */
5778     i = 0;
5779     is_zero = NX_TRUE;
5780 
5781     while(i < size)
5782     {
5783 
5784         if (*data != 0x0)
5785         {
5786 
5787             is_zero = NX_FALSE;
5788             break;
5789         }
5790 
5791         data += sizeof(UCHAR);
5792         i++;
5793     }
5794 
5795     return is_zero;
5796 }
5797 
5798 
5799 /**************************************************************************/
5800 /*                                                                        */
5801 /*  FUNCTION                                               RELEASE        */
5802 /*                                                                        */
5803 /*    _nx_sntp_client_utility_convert_fraction_to_msecs   PORTABLE C      */
5804 /*                                                           6.1          */
5805 /*  AUTHOR                                                                */
5806 /*                                                                        */
5807 /*    Yuxin Zhou, Microsoft Corporation                                   */
5808 /*                                                                        */
5809 /*  DESCRIPTION                                                           */
5810 /*                                                                        */
5811 /*   This function converts the fraction in an NTP time to milliseconds.  */
5812 /*                                                                        */
5813 /*   INPUT                                                                */
5814 /*                                                                        */
5815 /*    milliseconds                     Pointer to milliseconds converted  */
5816 /*    time_ptr                         Pointer to an NTP time             */
5817 /*                                                                        */
5818 /*  OUTPUT                                                                */
5819 /*                                                                        */
5820 /*    NX_SUCCESS                       Successful completion              */
5821 /*                                                                        */
5822 /*  CALLS                                                                 */
5823 /*                                                                        */
5824 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
5825 /*                                     Convert fraction to usecs          */
5826 /*                                                                        */
5827 /*  CALLED BY                                                             */
5828 /*                                                                        */
5829 /*   _nx_sntp_client_utility_display_NTP_time                             */
5830 /*                                     Display NTP time in seconds        */
5831 /*                                                                        */
5832 /*  RELEASE HISTORY                                                       */
5833 /*                                                                        */
5834 /*    DATE              NAME                      DESCRIPTION             */
5835 /*                                                                        */
5836 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5837 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5838 /*                                            resulting in version 6.1    */
5839 /*                                                                        */
5840 /**************************************************************************/
_nx_sntp_client_utility_convert_fraction_to_msecs(ULONG * milliseconds,NX_SNTP_TIME * time_ptr)5841 UINT  _nx_sntp_client_utility_convert_fraction_to_msecs(ULONG *milliseconds, NX_SNTP_TIME *time_ptr)
5842 {
5843 
5844 ULONG usecs;
5845 
5846 
5847     /* Convert to usecs first.  */
5848     _nx_sntp_client_utility_fraction_to_usecs(time_ptr ->fraction, &usecs);
5849 
5850     /* Then convert to milliseconds.  */
5851     *milliseconds = usecs / 1000;
5852 
5853     /* Round up if greater than 500 usecs left over*/
5854     if (usecs % 1000 >= 500)
5855     {
5856 
5857         (*milliseconds)++;
5858     }
5859 
5860     /* Return successful completion.  */
5861     return NX_SUCCESS;
5862 }
5863 
5864 
5865 /**************************************************************************/
5866 /*                                                                        */
5867 /*  FUNCTION                                               RELEASE        */
5868 /*                                                                        */
5869 /*    _nxe_sntp_client_utility_usecs_to_fraction          PORTABLE C      */
5870 /*                                                           6.1          */
5871 /*  AUTHOR                                                                */
5872 /*                                                                        */
5873 /*    Yuxin Zhou, Microsoft Corporation                                   */
5874 /*                                                                        */
5875 /*  DESCRIPTION                                                           */
5876 /*                                                                        */
5877 /*   This function performs error checking on the utility to convert      */
5878 /*   microseconds to fraction.                                            */
5879 /*                                                                        */
5880 /*   INPUT                                                                */
5881 /*                                                                        */
5882 /*    usecs                            Microseconds to convert            */
5883 /*    fraction                         Pointer to converted fraction      */
5884 /*                                                                        */
5885 /*  OUTPUT                                                                */
5886 /*                                                                        */
5887 /*    NX_SNTP_INVALID_TIME             Invalid SNTP data input            */
5888 /*    status                           Actual completion status           */
5889 /*                                                                        */
5890 /*  CALLS                                                                 */
5891 /*                                                                        */
5892 /*    _nx_sntp_client_utility_usecs_to_fraction                           */
5893 /*                                     Actual usecs conversion service    */
5894 /*                                                                        */
5895 /*  CALLED BY                                                             */
5896 /*                                                                        */
5897 /*   Application code                                                     */
5898 /*                                                                        */
5899 /*  RELEASE HISTORY                                                       */
5900 /*                                                                        */
5901 /*    DATE              NAME                      DESCRIPTION             */
5902 /*                                                                        */
5903 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5904 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5905 /*                                            resulting in version 6.1    */
5906 /*                                                                        */
5907 /**************************************************************************/
_nxe_sntp_client_utility_usecs_to_fraction(ULONG usecs,ULONG * fraction)5908 UINT    _nxe_sntp_client_utility_usecs_to_fraction(ULONG usecs, ULONG *fraction)
5909 {
5910 
5911 UINT status;
5912 
5913 
5914     if ((usecs == 0) || (fraction == NX_NULL))
5915     {
5916 
5917         return NX_SNTP_INVALID_TIME;
5918     }
5919 
5920     status = _nx_sntp_client_utility_usecs_to_fraction(usecs, fraction);
5921 
5922     return status;
5923 }
5924 
5925 
5926 /**************************************************************************/
5927 /*                                                                        */
5928 /*  FUNCTION                                               RELEASE        */
5929 /*                                                                        */
5930 /*    _nx_sntp_client_utility_usecs_to_fraction           PORTABLE C      */
5931 /*                                                           6.1          */
5932 /*  AUTHOR                                                                */
5933 /*                                                                        */
5934 /*    Yuxin Zhou, Microsoft Corporation                                   */
5935 /*                                                                        */
5936 /*  DESCRIPTION                                                           */
5937 /*                                                                        */
5938 /*   This function converts microseconds to a time stamp fraction.  It is */
5939 /*   primarily an intermediary function used in the process of converting */
5940 /*   millliseconds to fixed point time fraction data.                     */
5941 /*                                                                        */
5942 /*   This conversion scheme is limited to microseconds less than 1000000. */
5943 /*                                                                        */
5944 /*   INPUT                                                                */
5945 /*                                                                        */
5946 /*    usecs                            Microseconds to convert            */
5947 /*    fraction                         Fraction to converted fraction     */
5948 /*                                                                        */
5949 /*  OUTPUT                                                                */
5950 /*                                                                        */
5951 /*    NX_SUCCESS                       Successful completion status       */
5952 /*    NX_SNTP_OVERFLOW_ERROR           Overflow error status              */
5953 /*                                                                        */
5954 /*  CALLS                                                                 */
5955 /*                                                                        */
5956 /*    None                                                                */
5957 /*                                                                        */
5958 /*  CALLED BY                                                             */
5959 /*                                                                        */
5960 /*   _nx_sntp_client_utility_msecs_to_fraction                            */
5961 /*                                     Convert milliseconds to fixed point*/
5962 /*                                                                        */
5963 /*  RELEASE HISTORY                                                       */
5964 /*                                                                        */
5965 /*    DATE              NAME                      DESCRIPTION             */
5966 /*                                                                        */
5967 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5968 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5969 /*                                            resulting in version 6.1    */
5970 /*                                                                        */
5971 /**************************************************************************/
_nx_sntp_client_utility_usecs_to_fraction(ULONG usecs,ULONG * fraction)5972 UINT  _nx_sntp_client_utility_usecs_to_fraction(ULONG usecs, ULONG *fraction)
5973 {
5974 
5975 ULONG _frac = usecs * 3962;
5976 
5977 
5978     *fraction = (usecs * 4294) + (_frac >> 12);
5979 
5980     if((_frac & 4095) >= 2048)
5981         *fraction = *fraction + 1;
5982 
5983     /* Successful completion.  */
5984     return NX_SUCCESS;
5985 }
5986 
5987 
5988 /**************************************************************************/
5989 /*                                                                        */
5990 /*  FUNCTION                                               RELEASE        */
5991 /*                                                                        */
5992 /*    _nxe_sntp_client_utility_msecs_to_fraction          PORTABLE C      */
5993 /*                                                           6.1          */
5994 /*  AUTHOR                                                                */
5995 /*                                                                        */
5996 /*    Yuxin Zhou, Microsoft Corporation                                   */
5997 /*                                                                        */
5998 /*  DESCRIPTION                                                           */
5999 /*                                                                        */
6000 /*   This function performs error checking on the utility to convert      */
6001 /*   milliseconds to fraction.                                            */
6002 /*                                                                        */
6003 /*   INPUT                                                                */
6004 /*                                                                        */
6005 /*    msecs                            Milliseconds to convert            */
6006 /*    fraction                         Pointer to converted fraction      */
6007 /*                                                                        */
6008 /*  OUTPUT                                                                */
6009 /*                                                                        */
6010 /*    NX_SNTP_INVALID_TIME             Invalid SNTP data input            */
6011 /*    status                           Actual completion status           */
6012 /*                                                                        */
6013 /*  CALLS                                                                 */
6014 /*                                                                        */
6015 /*    _nx_sntp_client_utility_msecs_to_fraction                           */
6016 /*                                     Actual msecs conversion service    */
6017 /*                                                                        */
6018 /*  CALLED BY                                                             */
6019 /*                                                                        */
6020 /*   Application code                                                     */
6021 /*                                                                        */
6022 /*  RELEASE HISTORY                                                       */
6023 /*                                                                        */
6024 /*    DATE              NAME                      DESCRIPTION             */
6025 /*                                                                        */
6026 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6027 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6028 /*                                            resulting in version 6.1    */
6029 /*                                                                        */
6030 /**************************************************************************/
_nxe_sntp_client_utility_msecs_to_fraction(ULONG msecs,ULONG * fraction)6031 UINT    _nxe_sntp_client_utility_msecs_to_fraction(ULONG msecs, ULONG *fraction)
6032 {
6033 
6034 UINT status;
6035 
6036 
6037     if ((msecs == 0) || (fraction == NX_NULL))
6038     {
6039 
6040         return NX_SNTP_INVALID_TIME;
6041     }
6042 
6043     status = _nx_sntp_client_utility_msecs_to_fraction(msecs, fraction);
6044 
6045     return status;
6046 }
6047 
6048 
6049 /**************************************************************************/
6050 /*                                                                        */
6051 /*  FUNCTION                                               RELEASE        */
6052 /*                                                                        */
6053 /*    _nx_sntp_client_utility_msecs_to_fraction           PORTABLE C      */
6054 /*                                                           6.1          */
6055 /*  AUTHOR                                                                */
6056 /*                                                                        */
6057 /*    Yuxin Zhou, Microsoft Corporation                                   */
6058 /*                                                                        */
6059 /*  DESCRIPTION                                                           */
6060 /*                                                                        */
6061 /*   This function converts milliseconds to fixed point notation used in  */
6062 /*   the NTP time fraction field. This will not accept msecs >= 1000      */
6063 /*   because that number cannot be represented in an NTP time fraction.   */
6064 /*                                                                        */
6065 /*   INPUT                                                                */
6066 /*                                                                        */
6067 /*    msecs                            Milliseconds to convert            */
6068 /*    fraction                         Pointer to converted fraction      */
6069 /*                                                                        */
6070 /*  OUTPUT                                                                */
6071 /*                                                                        */
6072 /*    NX_SUCCESS                       Successful completion status       */
6073 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result                    */
6074 /*    status                           Actual completion status           */
6075 /*                                                                        */
6076 /*  CALLS                                                                 */
6077 /*                                                                        */
6078 /*    _nx_sntp_client_utility_usecs_to_fraction                           */
6079 /*                                     Convert usecs to fixed point       */
6080 /*                                                                        */
6081 /*  CALLED BY                                                             */
6082 /*                                                                        */
6083 /*   _nx_sntp_client_utility_add_msecs_to_ntp_time                        */
6084 /*                                     Add msecs to an NTP time data      */
6085 /*   _nx_sntp_client_utility_add_NTPtime                                  */
6086 /*                                     Add two NTP time fields            */
6087 /*                                                                        */
6088 /*  RELEASE HISTORY                                                       */
6089 /*                                                                        */
6090 /*    DATE              NAME                      DESCRIPTION             */
6091 /*                                                                        */
6092 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6093 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6094 /*                                            resulting in version 6.1    */
6095 /*                                                                        */
6096 /**************************************************************************/
_nx_sntp_client_utility_msecs_to_fraction(ULONG msecs,ULONG * fraction)6097 UINT  _nx_sntp_client_utility_msecs_to_fraction(ULONG msecs, ULONG *fraction)
6098 {
6099 
6100 UINT    status;
6101 ULONG   usecs;
6102 
6103 
6104     /* Check for possible overflow.  */
6105     if (msecs > 1000)
6106     {
6107 
6108         /* Return error condition.  */
6109         return NX_SNTP_OVERFLOW_ERROR;
6110     }
6111 
6112     /* Convert msecs to usecs first.  */
6113     usecs = msecs * 1000;
6114 
6115     /* Convert usecs to fraction.  */
6116     status = _nx_sntp_client_utility_usecs_to_fraction(usecs, fraction);
6117 
6118     /* Check for error.  */
6119     if (status != NX_SUCCESS)
6120     {
6121 
6122         /* Return the error status.  */
6123         return status;
6124     }
6125 
6126     /* Successful completion.  */
6127     return NX_SUCCESS;
6128 }
6129 
6130 
6131 /**************************************************************************/
6132 /*                                                                        */
6133 /*  FUNCTION                                               RELEASE        */
6134 /*                                                                        */
6135 /*    _nxe_sntp_client_utility_fraction_to_usecs          PORTABLE C      */
6136 /*                                                           6.1          */
6137 /*  AUTHOR                                                                */
6138 /*                                                                        */
6139 /*    Yuxin Zhou, Microsoft Corporation                                   */
6140 /*                                                                        */
6141 /*  DESCRIPTION                                                           */
6142 /*                                                                        */
6143 /*   This function performs error checking on the utility to convert      */
6144 /*   fraction to microseconds.                                            */
6145 /*                                                                        */
6146 /*   INPUT                                                                */
6147 /*                                                                        */
6148 /*    fraction                         Fraction to convert                */
6149 /*    usecs                            Pointer to converted microseconds  */
6150 /*                                                                        */
6151 /*  OUTPUT                                                                */
6152 /*                                                                        */
6153 /*    status                           Actual completion status           */
6154 /*                                                                        */
6155 /*  CALLS                                                                 */
6156 /*                                                                        */
6157 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
6158 /*                                     Actual usecs conversion service    */
6159 /*                                                                        */
6160 /*  CALLED BY                                                             */
6161 /*                                                                        */
6162 /*   Application code                                                     */
6163 /*                                                                        */
6164 /*  RELEASE HISTORY                                                       */
6165 /*                                                                        */
6166 /*    DATE              NAME                      DESCRIPTION             */
6167 /*                                                                        */
6168 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6169 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6170 /*                                            resulting in version 6.1    */
6171 /*                                                                        */
6172 /**************************************************************************/
_nxe_sntp_client_utility_fraction_to_usecs(ULONG fraction,ULONG * usecs)6173 UINT    _nxe_sntp_client_utility_fraction_to_usecs(ULONG fraction, ULONG *usecs)
6174 {
6175 
6176 UINT status;
6177 
6178 
6179     if (usecs == NX_NULL)
6180     {
6181         return NX_SNTP_INVALID_TIME;
6182     }
6183 
6184     status = _nx_sntp_client_utility_fraction_to_usecs(fraction, usecs);
6185 
6186     return status;
6187 }
6188 
6189 
6190 /**************************************************************************/
6191 /*                                                                        */
6192 /*  FUNCTION                                               RELEASE        */
6193 /*                                                                        */
6194 /*    _nx_sntp_client_utility_fraction_to_usecs           PORTABLE C      */
6195 /*                                                           6.1          */
6196 /*  AUTHOR                                                                */
6197 /*                                                                        */
6198 /*    Yuxin Zhou, Microsoft Corporation                                   */
6199 /*                                                                        */
6200 /*  DESCRIPTION                                                           */
6201 /*                                                                        */
6202 /*   This function converts a time stamp fraction to microseconds.  It is */
6203 /*   primarily an intermediary function used in the process of converting */
6204 /*   fixed point time fraction data to msecs.                             */
6205 /*                                                                        */
6206 /*   INPUT                                                                */
6207 /*                                                                        */
6208 /*    fraction                         Fraction to convert to usecs       */
6209 /*    usecs                            Pointer to ucsecs from fraction    */
6210 /*                                                                        */
6211 /*  OUTPUT                                                                */
6212 /*                                                                        */
6213 /*    None                                                                */
6214 /*                                                                        */
6215 /*  CALLS                                                                 */
6216 /*                                                                        */
6217 /*    None                                                                */
6218 /*                                                                        */
6219 /*  CALLED BY                                                             */
6220 /*                                                                        */
6221 /*   _nx_sntp_client_get_local_time_extended                              */
6222 /*                                     Get extended local time            */
6223 /*   _nx_sntp_client_utility_convert_fraction_to_msecs                    */
6224 /*                                     Convert time fraction to msecs     */
6225 /*                                                                        */
6226 /*  RELEASE HISTORY                                                       */
6227 /*                                                                        */
6228 /*    DATE              NAME                      DESCRIPTION             */
6229 /*                                                                        */
6230 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6231 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6232 /*                                            resulting in version 6.1    */
6233 /*                                                                        */
6234 /**************************************************************************/
_nx_sntp_client_utility_fraction_to_usecs(ULONG fraction,ULONG * usecs)6235 UINT  _nx_sntp_client_utility_fraction_to_usecs(ULONG fraction, ULONG *usecs)
6236 {
6237 
6238 ULONG value, segment;
6239 int i;
6240 
6241     value = 0;
6242 
6243     for(i = 2; i < 32; i+=6)
6244     {
6245         segment = (fraction >> i) & 0x3F;
6246 
6247         if((value & 0x3F) >= 32)
6248             value = (value  >> 6) + segment * 15625 + 1;
6249         else
6250             value = (value  >> 6) + segment * 15625;
6251     }
6252     *usecs = value;
6253 
6254     return(NX_SUCCESS);
6255 }
6256 
6257 
6258 /**************************************************************************/
6259 /*                                                                        */
6260 /*  FUNCTION                                               RELEASE        */
6261 /*                                                                        */
6262 /*    _nx_sntp_client_utility_convert_refID_KOD_code      PORTABLE C      */
6263 /*                                                           6.1          */
6264 /*  AUTHOR                                                                */
6265 /*                                                                        */
6266 /*    Yuxin Zhou, Microsoft Corporation                                   */
6267 /*                                                                        */
6268 /*  DESCRIPTION                                                           */
6269 /*                                                                        */
6270 /*  This function converts the reference ID field in a NTP time message   */
6271 /*  data to a known Kiss of Death reference_id.                           */
6272 /*                                                                        */
6273 /*  Note the Kiss of Death reference_id list is subject to change.  This  */
6274 /*  is current as of 4/01/2007.                                           */
6275 /*                                                                        */
6276 /*  INPUT                                                                 */
6277 /*                                                                        */
6278 /*    reference_id                 Pointer to the reference ID to convert */
6279 /*    code_id                      Pointer to converted code              */
6280 /*                                                                        */
6281 /*  OUTPUT                                                                */
6282 /*                                                                        */
6283 /*    NX_SUCCESS                   Successful completion status           */
6284 /*                                                                        */
6285 /*  CALLS                                                                 */
6286 /*                                                                        */
6287 /*    memcmp                       Copy data to specified area of memory  */
6288 /*                                                                        */
6289 /*  CALLED BY                                                             */
6290 /*                                                                        */
6291 /*    Application Code (e.g. the Client kiss of death handler callback)   */
6292 /*                                                                        */
6293 /*  RELEASE HISTORY                                                       */
6294 /*                                                                        */
6295 /*    DATE              NAME                      DESCRIPTION             */
6296 /*                                                                        */
6297 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6298 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6299 /*                                            resulting in version 6.1    */
6300 /*                                                                        */
6301 /**************************************************************************/
_nx_sntp_client_utility_convert_refID_KOD_code(UCHAR * reference_id,UINT * code_id)6302 UINT  _nx_sntp_client_utility_convert_refID_KOD_code(UCHAR *reference_id, UINT *code_id)
6303 {
6304 
6305 /* This is the internal list of Kiss of Death codes and their meaning.  */
6306 
6307 
6308     /* Compare the reference_id to each known reference_id and if it matches return the reference_id ID.  */
6309     if (!memcmp(reference_id, ANYCAST, 4))
6310     {
6311         *code_id = NX_SNTP_KOD_ANYCAST;
6312     }
6313     else if (!memcmp(reference_id, AUTH_FAIL, 4))
6314     {
6315         *code_id = NX_SNTP_KOD_AUTH_FAIL;
6316     }
6317     else if (!memcmp(reference_id, AUTOKEY_FAIL, 4))
6318     {
6319         *code_id = NX_SNTP_KOD_AUTOKEY_FAIL;
6320     }
6321     else if (!memcmp(reference_id, BROADCAST, 4))
6322     {
6323         *code_id = NX_SNTP_KOD_BROADCAST;
6324     }
6325     else if (!memcmp(reference_id, CRYP_FAIL, 4))
6326     {
6327         *code_id = NX_SNTP_KOD_CRYP_FAIL;
6328     }
6329     else if (!memcmp(reference_id, DENY, 4))
6330     {
6331         *code_id = NX_SNTP_KOD_DENY;
6332     }
6333     else if (!memcmp(reference_id, DROP, 4))
6334     {
6335         *code_id = NX_SNTP_KOD_DROP;
6336     }
6337     else if (!memcmp(reference_id, DENY_POLICY, 4))
6338     {
6339         *code_id = NX_SNTP_KOD_DENY_POLICY;
6340     }
6341     else if (!memcmp(reference_id, NOT_INIT, 4))
6342     {
6343         *code_id = NX_SNTP_KOD_NOT_INIT;
6344     }
6345     else if (!memcmp(reference_id, MANYCAST, 4))
6346     {
6347         *code_id = NX_SNTP_KOD_MANYCAST;
6348     }
6349     else if (!memcmp(reference_id, NO_KEY, 4))
6350     {
6351         *code_id = NX_SNTP_KOD_NO_KEY;
6352     }
6353     else if (!memcmp(reference_id, RATE, 4))
6354     {
6355         *code_id = NX_SNTP_KOD_RATE;
6356     }
6357     else if (!memcmp(reference_id, RMOT, 4))
6358     {
6359         *code_id = NX_SNTP_KOD_RMOT;
6360     }
6361     else if (!memcmp(reference_id, STEP, 4))
6362     {
6363         *code_id = NX_SNTP_KOD_STEP;
6364     }
6365     else
6366     {
6367         /* Set reference_id ID to generic KOD 'other' reference_id.  */
6368         *code_id = NX_SNTP_KISS_OF_DEATH_PACKET;
6369     }
6370 
6371     /* Return successful completion.  */
6372     return NX_SUCCESS;
6373 }
6374 
6375 
6376 /**************************************************************************/
6377 /*                                                                        */
6378 /*  FUNCTION                                               RELEASE        */
6379 /*                                                                        */
6380 /*    _nx_sntp_client_utility_addition_overflow_check     PORTABLE C      */
6381 /*                                                           6.1          */
6382 /*  AUTHOR                                                                */
6383 /*                                                                        */
6384 /*    Yuxin Zhou, Microsoft Corporation                                   */
6385 /*                                                                        */
6386 /*  DESCRIPTION                                                           */
6387 /*                                                                        */
6388 /*   This function performs a simple platform independent check for       */
6389 /*   overflow when adding two operands.                                   */
6390 /*                                                                        */
6391 /*   INPUT                                                                */
6392 /*                                                                        */
6393 /*    temp1                            First addition operand             */
6394 /*    temp2                            Second addition operand            */
6395 /*                                                                        */
6396 /*  OUTPUT                                                                */
6397 /*                                                                        */
6398 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result adding time        */
6399 /*    NX_SUCCESS                       Successful completion status       */
6400 /*                                                                        */
6401 /*  CALLS                                                                 */
6402 /*                                                                        */
6403 /*    None                                                                */
6404 /*                                                                        */
6405 /*  CALLED BY                                                             */
6406 /*                                                                        */
6407 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
6408 /*                                     Add msecs to an NTP time           */
6409 /*    _nx_sntp_client_utility_add_NTPtime                                 */
6410 /*                                     Add two NTP times                  */
6411 /*                                                                        */
6412 /*  RELEASE HISTORY                                                       */
6413 /*                                                                        */
6414 /*    DATE              NAME                      DESCRIPTION             */
6415 /*                                                                        */
6416 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6417 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6418 /*                                            resulting in version 6.1    */
6419 /*                                                                        */
6420 /**************************************************************************/
_nx_sntp_client_utility_addition_overflow_check(ULONG temp1,ULONG temp2)6421 UINT  _nx_sntp_client_utility_addition_overflow_check(ULONG temp1, ULONG temp2)
6422 {
6423 
6424 ULONG sum_lower_16, sum_upper_16;
6425 UINT  carry;
6426 
6427 
6428     carry = 0;
6429 
6430     /* Add the lower 16 bits.  */
6431     sum_lower_16 = (temp1 & NX_LOWER_16_MASK) + (temp2 & NX_LOWER_16_MASK);
6432 
6433     /* Check for carry.  */
6434     if (sum_lower_16 & NX_CARRY_BIT)
6435     {
6436 
6437         /* Use variable to add the carry to the upper 16 bits.*/
6438         carry = 1;
6439     }
6440 
6441     /* Add the upper 16 bits.  */
6442     sum_upper_16 = (temp1 >> NX_SHIFT_BY_16) + (temp2 >> NX_SHIFT_BY_16) + carry;
6443 
6444     /* Check for carry.  */
6445     if (sum_upper_16 & NX_CARRY_BIT)
6446     {
6447 
6448         /* This indicates an overflow. Return as an error.  */
6449         return NX_SNTP_OVERFLOW_ERROR;
6450     }
6451 
6452     /* Ok to add operands!*/
6453     return NX_SUCCESS;
6454 }