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