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.1.12       */
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 /*                                                                        */
2504 /**************************************************************************/
_nx_sntp_client_receive_time_update(NX_SNTP_CLIENT * client_ptr,ULONG timeout)2505 UINT  _nx_sntp_client_receive_time_update(NX_SNTP_CLIENT *client_ptr, ULONG timeout)
2506 {
2507 
2508 UINT            status;
2509 UINT            length;
2510 NX_PACKET       *receive_packet;
2511 #ifndef NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE
2512 UINT            sender_port;
2513 NX_UDP_HEADER   *udp_header_ptr;
2514 NXD_ADDRESS     source_ip_address, destination_ip_address;
2515 #endif /* NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE */
2516 
2517     /* Loop to receive packets. */
2518     for(;;)
2519     {
2520 
2521         /* Indicate the SNTP Client can be stopped while the SNTP client waits for a packet.  */
2522         client_ptr -> nx_sntp_client_sleep_flag =  NX_TRUE;
2523 
2524         /* Wait to receive packets on the Client UDP socket.  */
2525         status = nx_udp_socket_receive(&(client_ptr -> nx_sntp_client_udp_socket), &receive_packet, timeout * NX_IP_PERIODIC_RATE);
2526 
2527         /* Indicate the SNTP Client can not be stopped.  */
2528         client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
2529 
2530         /* Check for error.  */
2531         if (status != NX_SUCCESS)
2532         {
2533 
2534             /* Return error status.  */
2535             return status;
2536         }
2537 
2538 #ifndef NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE
2539         /* Check the sender port in the UDP packet header.  */
2540         udp_header_ptr = (NX_UDP_HEADER *)(receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER));
2541         sender_port = (UINT)udp_header_ptr -> nx_udp_header_word_0 >> NX_SHIFT_BY_16;
2542 
2543         /* Check if this is the server port the Client expects.  */
2544         if (sender_port != NX_SNTP_SERVER_UDP_PORT)
2545         {
2546 
2547             /* No, reject the packet.  */
2548             nx_packet_release(receive_packet);
2549 
2550             continue;
2551         }
2552 
2553 
2554         /* If this an IPv6 packet? An SNTP client with an IPv6 SNTP server will only accept IPv6 packets.   */
2555         if ((receive_packet -> nx_packet_ip_version == NX_IP_VERSION_V6) &&
2556             (client_ptr -> nx_sntp_server_ip_address.nxd_ip_version == NX_IP_VERSION_V6))
2557         {
2558 
2559 #ifndef FEATURE_NX_IPV6
2560             nx_packet_release(receive_packet);
2561             continue;
2562 #else
2563             NX_IPV6_HEADER *ipv6_header_ptr;
2564 
2565             /* Pick up the IPv6 header from the packet. */
2566             ipv6_header_ptr =  (NX_IPV6_HEADER *) (receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV6_HEADER));
2567 
2568             /* Copy sender address into a local variable. */
2569             COPY_IPV6_ADDRESS(ipv6_header_ptr -> nx_ip_header_source_ip, &(source_ip_address.nxd_ip_address.v6[0]));
2570             source_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
2571 
2572             /* Copy destination address into a local variable. */
2573             COPY_IPV6_ADDRESS(ipv6_header_ptr -> nx_ip_header_destination_ip, &(destination_ip_address.nxd_ip_address.v6[0]));
2574             destination_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
2575 
2576             if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
2577             {
2578 
2579                 /* Does the source address match the expected server address?  */
2580                 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]))
2581                 {
2582 
2583                     /* No further need for the receive packet. Release back to the client pool.  */
2584                     nx_packet_release(receive_packet);
2585 
2586                     /* Set update time to null.  */
2587                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2588 
2589                     continue;
2590                 }
2591             }
2592             else /* Multicast mode */
2593             {
2594 
2595                 /* Define the all hosts multicast address. */
2596                 NXD_ADDRESS All_Hosts_Multicast;
2597                 All_Hosts_Multicast.nxd_ip_version = NX_IP_VERSION_V6;
2598                 All_Hosts_Multicast.nxd_ip_address.v6[0] = 0xff020000;
2599                 All_Hosts_Multicast.nxd_ip_address.v6[1] = 0x00000000;
2600                 All_Hosts_Multicast.nxd_ip_address.v6[2] = 0x00000000;
2601                 All_Hosts_Multicast.nxd_ip_address.v6[3] = 0x00000001;
2602 
2603                 /* Does the source address match the expected server address )?  */
2604                 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]))
2605                 {
2606 
2607                     /* No further need for the receive packet. Release back to the client pool.  */
2608                     nx_packet_release(receive_packet);
2609 
2610                     /* Set update time to null.  */
2611                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2612 
2613                     continue;
2614                 }
2615 
2616                 /* Does the destination address match the expected server address (all hosts address FF02::1)?  */
2617                 if (!CHECK_IPV6_ADDRESSES_SAME(&destination_ip_address.nxd_ip_address.v6[0], &All_Hosts_Multicast.nxd_ip_address.v6[0]))
2618                 {
2619 
2620                     /* No further need for the receive packet. Release back to the client pool.  */
2621                     nx_packet_release(receive_packet);
2622 
2623                     /* Set update time to null.  */
2624                     memset(&(client_ptr -> nx_sntp_server_update_time), 0, sizeof(NX_SNTP_TIME));
2625 
2626                     continue;
2627                 }
2628 
2629             }
2630 #endif  /* FEATURE_NX_IPV6 */
2631 
2632         }
2633         /* Otherwise is this an IPv4 packet and is the SNTP client set for IPv4? */
2634         else if ((receive_packet -> nx_packet_ip_version == NX_IP_VERSION_V4) &&
2635                  (client_ptr -> nx_sntp_server_ip_address.nxd_ip_version == NX_IP_VERSION_V4))
2636         {
2637 #ifdef NX_DISABLE_IPV4
2638             nx_packet_release(receive_packet);
2639             continue;
2640 #else
2641 
2642             NX_IPV4_HEADER *ipv4_header_ptr;
2643 
2644             ipv4_header_ptr =  (NX_IPV4_HEADER *) (receive_packet -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER) - sizeof(NX_IPV4_HEADER));
2645 
2646             /* Copy into a local variable. */
2647             source_ip_address.nxd_ip_address.v4 =  ipv4_header_ptr -> nx_ip_header_source_ip;
2648             source_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
2649 
2650             /* Copy into a local variable. */
2651             destination_ip_address.nxd_ip_address.v4 =  ipv4_header_ptr -> nx_ip_header_destination_ip;
2652             destination_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
2653 
2654             if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
2655             {
2656                 /* Compare the sender address with the Client's current sntp server. */
2657                 if (source_ip_address.nxd_ip_address.v4 != client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4)
2658                 {
2659                     /* This is an untrusted server or the client had a broadcast server already,
2660                        reject this packet and return an error condition.  */
2661 
2662                     /* No further need for the receive packet. Release back to the client pool.  */
2663                     nx_packet_release(receive_packet);
2664 
2665                     continue;
2666                 }
2667             }
2668             else /* BROADCAST_MODE */
2669             {
2670 
2671                 ULONG network_mask;
2672                 UINT  iface_index;
2673 
2674                 /* Compare the sender address with the Client's current sntp server. */
2675                 if (source_ip_address.nxd_ip_address.v4 != client_ptr -> nx_sntp_server_ip_address.nxd_ip_address.v4)
2676                 {
2677 
2678                     /* This is an untrusted server or the client had a broadcast server already,
2679                        reject this packet and return an error condition.  */
2680 
2681                     /* No further need for the receive packet. Release back to the client pool.  */
2682                     nx_packet_release(receive_packet);
2683 
2684                     continue;
2685                 }
2686 
2687                 /* Set a local variable on the SNTP network index. */
2688                 iface_index = client_ptr -> nx_sntp_client_interface_index;
2689 
2690                 /* Set a local variable to the network mask. */
2691                 network_mask = client_ptr -> nx_sntp_client_ip_ptr -> nx_ip_interface[iface_index].nx_interface_ip_network_mask;
2692 
2693                 /* Now verify this is a broadcast packet. */
2694                 if ((destination_ip_address.nxd_ip_address.v4 & ~network_mask) != ~network_mask)
2695                 {
2696                     /* This is not a broadcast packet on the local network.  */
2697 
2698                     /* No further need for the receive packet. Release back to the client pool.  */
2699                     nx_packet_release(receive_packet);
2700 
2701                     continue;
2702                 }
2703             }
2704 #endif /* NX_DISABLE_IPV4 */
2705         }
2706         else
2707         {
2708             /* Not interested, discard the packet. */
2709             nx_packet_release(receive_packet);
2710 
2711             continue;
2712         }
2713 
2714 #endif /* NX_SNTP_CLIENT_MESSAGE_CHECK_DISABLE */
2715 
2716         /* Check that the packet has the proper length for an NTP message.  */
2717         length = receive_packet -> nx_packet_length;
2718 
2719         /* Verify the packet data contains at least the minimum time update data,
2720            but no more than the max size with authentication data appended.  */
2721 
2722         if ((length < NX_SNTP_TIME_MESSAGE_MIN_SIZE) || (length > NX_SNTP_TIME_MESSAGE_MAX_SIZE))
2723         {
2724 
2725             /* No further need for the receive packet. Release back to the client pool.  */
2726             nx_packet_release(receive_packet);
2727 
2728             continue;
2729         }
2730 
2731         memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2732 
2733         /* Extract time message data from packet data into time message.  */
2734         _nx_sntp_client_extract_time_message_from_packet(client_ptr, receive_packet);
2735 
2736         /* No further need for the receive packet. Release back to the client pool.  */
2737         nx_packet_release(receive_packet);
2738 
2739         return NX_SUCCESS;
2740     }
2741 }
2742 
2743 
2744 /**************************************************************************/
2745 /*                                                                        */
2746 /*  FUNCTION                                               RELEASE        */
2747 /*                                                                        */
2748 /*    _nx_sntp_client_extract_time_message_from_packet    PORTABLE C      */
2749 /*                                                           6.1.10       */
2750 /*  AUTHOR                                                                */
2751 /*                                                                        */
2752 /*    Yuxin Zhou, Microsoft Corporation                                   */
2753 /*                                                                        */
2754 /*  DESCRIPTION                                                           */
2755 /*                                                                        */
2756 /*    This function extracts time data from an SNTP  server packet and    */
2757 /*    copies the information into the specified time message buffer.      */
2758 /*                                                                        */
2759 /*   INPUT                                                                */
2760 /*                                                                        */
2761 /*    client_ptr                          Pointer to SNTP Client          */
2762 /*    packet_ptr                          Pointer to server packet        */
2763 /*                                                                        */
2764 /*  OUTPUT                                                                */
2765 /*                                                                        */
2766 /*    NX_SUCCESS                          Successful completion status    */
2767 /*                                                                        */
2768 /*  CALLS                                                                 */
2769 /*                                                                        */
2770 /*    memcpy                              Copy data to area of memory     */
2771 /*                                                                        */
2772 /*  CALLED BY                                                             */
2773 /*                                                                        */
2774 /*    _nx_sntp_client_receive_time_update Process SNTP server packets     */
2775 /*                                                                        */
2776 /*  RELEASE HISTORY                                                       */
2777 /*                                                                        */
2778 /*    DATE              NAME                      DESCRIPTION             */
2779 /*                                                                        */
2780 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2781 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2782 /*                                            verified memcpy use cases,  */
2783 /*                                            resulting in version 6.1    */
2784 /*  01-31-2022     Yuxin Zhou               Modified comment(s), corrected*/
2785 /*                                            the Reference Identifier,  */
2786 /*                                            resulting in version 6.1.10 */
2787 /*                                                                        */
2788 /**************************************************************************/
_nx_sntp_client_extract_time_message_from_packet(NX_SNTP_CLIENT * client_ptr,NX_PACKET * packet_ptr)2789 UINT  _nx_sntp_client_extract_time_message_from_packet(NX_SNTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
2790 {
2791 
2792 ULONG   *ntp_word_0;
2793 NX_SNTP_TIME_MESSAGE *time_message_ptr;
2794 
2795 
2796     time_message_ptr = &(client_ptr -> nx_sntp_current_server_time_message);
2797 
2798     process_timerticks = tx_time_get();
2799 
2800     memset(time_message_ptr, 0, sizeof(NX_SNTP_TIME_MESSAGE));
2801 
2802     /* Pickup the pointer to the head of the UDP packet.  */
2803     ntp_word_0 = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
2804     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2805 
2806     /* Extract fields from the first 32 bits of the time message.  */
2807     time_message_ptr -> flags = (*ntp_word_0 & 0xFF000000UL) >> 24;
2808 
2809     time_message_ptr -> peer_clock_stratum = (*ntp_word_0 & 0x00FF0000UL) >> 16;
2810 
2811     time_message_ptr -> peer_poll_interval = (*ntp_word_0 & 0x0000FF00UL) >> 8;
2812 
2813     time_message_ptr -> peer_clock_precision =  (*ntp_word_0 & 0x00000000FFUL);
2814 
2815     /* Advance to the next 32 bit field and extract the root delay field.  */
2816     ntp_word_0++;
2817     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2818 
2819     time_message_ptr -> root_delay = (ULONG)(*ntp_word_0);
2820 
2821     /* Advance to the next 32 bit field and extract the clock dispersion field.  */
2822     ntp_word_0++;
2823     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2824 
2825     time_message_ptr -> clock_dispersion= *ntp_word_0;
2826 
2827     /* Advance to the next 32 bit field and extract the reference clock ID field.  */
2828     ntp_word_0++;
2829     memcpy(time_message_ptr -> reference_clock_id, ntp_word_0, 4); /* Use case of memcpy is verified. */
2830 
2831     /* Advance to the next field (64 bit field) and extract the reference time stamp field.  */
2832     ntp_word_0++;
2833     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2834     time_message_ptr -> reference_clock_update_time_stamp[0] = *ntp_word_0;
2835 
2836     ntp_word_0++;
2837     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2838     time_message_ptr -> reference_clock_update_time_stamp[1] = *ntp_word_0;
2839 
2840     /* If a non zero reference time was supplied, separate out seconds and fraction.  */
2841     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> reference_clock_update_time_stamp), 8) == NX_FALSE)
2842     {
2843 
2844         time_message_ptr -> reference_clock_update_time.seconds = time_message_ptr -> reference_clock_update_time_stamp[0];
2845 
2846         time_message_ptr -> reference_clock_update_time.fraction = time_message_ptr -> reference_clock_update_time_stamp[1];
2847     }
2848 
2849     /* Copy the first 32 bits into the originate time stamp seconds field. */
2850     ntp_word_0++;
2851     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2852     time_message_ptr -> originate_time_stamp[0] = *ntp_word_0;
2853 
2854     /* Copy the next 32 bits into the originate time stamp fraction field. */
2855     ntp_word_0++;
2856     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2857     time_message_ptr -> originate_time_stamp[1] = *ntp_word_0;
2858 
2859     /* If an originate time was supplied, separate out seconds and fraction.  */
2860     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> originate_time_stamp), 8) == NX_FALSE)
2861     {
2862 
2863         time_message_ptr -> originate_time.seconds = time_message_ptr -> originate_time_stamp[0];
2864 
2865         time_message_ptr -> originate_time.fraction = time_message_ptr -> originate_time_stamp[1];
2866     }
2867 
2868 
2869     /* Copy the first 32 bits into the receive time stamp seconds field. */
2870     ntp_word_0++;
2871     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2872     time_message_ptr -> receive_time_stamp[0] = *ntp_word_0;
2873 
2874     /* Copy the next 32 bits into the receive time stamp fraction field. */
2875     ntp_word_0++;
2876     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2877     time_message_ptr -> receive_time_stamp[1] = *ntp_word_0;
2878 
2879     /* If an receive time was supplied, separate out seconds and fraction.  */
2880     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> receive_time_stamp), 8) == NX_FALSE)
2881     {
2882 
2883         time_message_ptr -> receive_time.seconds = time_message_ptr -> receive_time_stamp[0];
2884         time_message_ptr -> receive_time.fraction = time_message_ptr -> receive_time_stamp[1];
2885     }
2886 
2887     /* Copy the first 32 bits into the transmit time stamp seconds field. */
2888     ntp_word_0++;
2889     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2890     time_message_ptr -> transmit_time_stamp[0] = *ntp_word_0;
2891 
2892     /* Copy the next 32 bits into the transmit time stamp fraction field. */
2893     ntp_word_0++;
2894     NX_CHANGE_ULONG_ENDIAN(*ntp_word_0);
2895     time_message_ptr -> transmit_time_stamp[1] = *ntp_word_0;
2896 
2897     /* If an transmit time was supplied, separate out seconds and fraction.  */
2898     if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(time_message_ptr -> transmit_time_stamp), 8) == NX_FALSE)
2899     {
2900 
2901         time_message_ptr -> transmit_time.seconds = time_message_ptr -> transmit_time_stamp[0];
2902 
2903         time_message_ptr -> transmit_time.fraction = time_message_ptr -> transmit_time_stamp[1];
2904 
2905     }
2906 
2907     /* Return completion status.  */
2908     return NX_SUCCESS;
2909 }
2910 
2911 
2912 /**************************************************************************/
2913 /*                                                                        */
2914 /*  FUNCTION                                               RELEASE        */
2915 /*                                                                        */
2916 /*    _nx_sntp_client_reset_current_time_message          PORTABLE C      */
2917 /*                                                           6.1          */
2918 /*  AUTHOR                                                                */
2919 /*                                                                        */
2920 /*    Yuxin Zhou, Microsoft Corporation                                   */
2921 /*                                                                        */
2922 /*  DESCRIPTION                                                           */
2923 /*                                                                        */
2924 /*    This function saves the current time message from the server to     */
2925 /*    the previous time message field, and clears the current time message*/
2926 /*    field.                                                              */
2927 /*                                                                        */
2928 /*   INPUT                                                                */
2929 /*                                                                        */
2930 /*    client_ptr                          Pointer to Client               */
2931 /*                                                                        */
2932 /*  OUTPUT                                                                */
2933 /*                                                                        */
2934 /*    NX_SUCCESS                          Successful completion status    */
2935 /*                                                                        */
2936 /*  CALLS                                                                 */
2937 /*                                                                        */
2938 /*    memset                              Clear specified area of memory  */
2939 /*    memcpy                              Copy data to area of memory     */
2940 /*                                                                        */
2941 /*  CALLED BY                                                             */
2942 /*                                                                        */
2943 /*    _nx_sntp_client_receive_time_update Process received update packets */
2944 /*                                                                        */
2945 /*  RELEASE HISTORY                                                       */
2946 /*                                                                        */
2947 /*    DATE              NAME                      DESCRIPTION             */
2948 /*                                                                        */
2949 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2950 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2951 /*                                            verified memcpy use cases,  */
2952 /*                                            resulting in version 6.1    */
2953 /*                                                                        */
2954 /**************************************************************************/
_nx_sntp_client_reset_current_time_message(NX_SNTP_CLIENT * client_ptr)2955 UINT  _nx_sntp_client_reset_current_time_message(NX_SNTP_CLIENT *client_ptr)
2956 {
2957 
2958     /* Does the client have a non NULL current server time update?  */
2959     if (client_ptr -> nx_sntp_current_server_time_message.flags)
2960     {
2961 
2962         /* Yes, copy to the previous time update.  */
2963         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. */
2964 
2965         /* Clear the current time update data.  */
2966         memset(&(client_ptr -> nx_sntp_current_server_time_message), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2967 
2968     }
2969 
2970     /* Clear the current time update request.  */
2971     memset(&(client_ptr -> nx_sntp_current_time_message_request), 0, sizeof(NX_SNTP_TIME_MESSAGE));
2972 
2973     return NX_SUCCESS;
2974 }
2975 
2976 
2977 /**************************************************************************/
2978 /*                                                                        */
2979 /*  FUNCTION                                               RELEASE        */
2980 /*                                                                        */
2981 /*    _nx_sntp_client_process_update_packet               PORTABLE C      */
2982 /*                                                           6.1          */
2983 /*  AUTHOR                                                                */
2984 /*                                                                        */
2985 /*    Yuxin Zhou, Microsoft Corporation                                   */
2986 /*                                                                        */
2987 /*  DESCRIPTION                                                           */
2988 /*                                                                        */
2989 /*    This function processes SNTP time data received in a server update  */
2990 /*    packet, applies sanity checks, calculates round trip time, and      */
2991 /*    updates the Client time with the SNTP server time.                  */
2992 /*                                                                        */
2993 /*   INPUT                                                                */
2994 /*                                                                        */
2995 /*    client_ptr                          Pointer to Client               */
2996 /*                                                                        */
2997 /*  OUTPUT                                                                */
2998 /*                                                                        */
2999 /*    NX_SUCCESS                          Successful completion status    */
3000 /*    NX_SNTP_BAD_SERVER_ROOT_DISPERSION  Server dispersion too high      */
3001 /*    receive_status                      Actual packet receive status    */
3002 /*                                                                        */
3003 /*  CALLS                                                                 */
3004 /*                                                                        */
3005 /*    memcmp                              Copy data to area of memory     */
3006 /*    _nx_sntp_client_apply_sanity_checks Apply sanity checks to update   */
3007 /*    _nx_sntp_client_check_server_clock_dispersion                       */
3008 /*                                        Check server clock dispersion   */
3009 /*    _nx_sntp_client_calculate_roundtrip                                 */
3010 /*                                        Compute roundtrip time to server*/
3011 /*   _nx_sntp_client_process_time_data    Apply server time to local time */
3012 /*                                                                        */
3013 /*  CALLED BY                                                             */
3014 /*                                                                        */
3015 /*    _nx_sntp_client_process_unicast     Process unicast SNTP data       */
3016 /*    _nx_sntp_client_process_broadcast   Process broadcast SNTP data     */
3017 /*                                                                        */
3018 /*  RELEASE HISTORY                                                       */
3019 /*                                                                        */
3020 /*    DATE              NAME                      DESCRIPTION             */
3021 /*                                                                        */
3022 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3023 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3024 /*                                            resulting in version 6.1    */
3025 /*                                                                        */
3026 /**************************************************************************/
_nx_sntp_client_process_update_packet(NX_SNTP_CLIENT * client_ptr)3027 UINT  _nx_sntp_client_process_update_packet(NX_SNTP_CLIENT *client_ptr)
3028 {
3029 
3030 UINT    status;
3031 
3032     /* Apply client's set of sanity checks on the data.  */
3033     status = _nx_sntp_client_apply_sanity_checks(client_ptr);
3034 
3035     /* Check for sanity check errors.  */
3036     if (status != NX_SUCCESS)
3037     {
3038 
3039         /* Count these  as bad updates from the server.  */
3040         client_ptr -> nx_sntp_client_invalid_time_updates++;
3041 
3042         /* Ok to continue Client task.  */
3043         return status;
3044     }
3045 
3046     /* Check server clock dispersion (if any reported) in first update
3047        from current server for unicast clients.  */
3048     if ((client_ptr -> nx_sntp_client_first_update_pending == NX_TRUE) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3049     {
3050 
3051         status = _nx_sntp_client_check_server_clock_dispersion(client_ptr);
3052 
3053         /* Is the server clock variance acceptable?  */
3054         if (status != NX_SUCCESS)
3055         {
3056 
3057             /* Return the error status.  */
3058             return status;
3059         }
3060     }
3061 
3062     /* At this point we have received a valid server response.  */
3063 
3064     /* Clear the count of (consecutive) bad time updates received from this server.  */
3065     client_ptr -> nx_sntp_client_invalid_time_updates = 0;
3066 
3067     /* Apply server time to local device time.  */
3068     status = _nx_sntp_client_process_time_data(client_ptr);
3069 
3070     /* Check for error.  */
3071     if (status != NX_SUCCESS)
3072     {
3073 
3074         /* Return the error condition*/
3075         return status;
3076     }
3077 
3078     /* If the Client is configured with a time update callback, call it now. */
3079     if (client_ptr -> nx_sntp_client_time_update_notify)
3080     {
3081 
3082         client_ptr -> nx_sntp_client_time_update_notify(&(client_ptr -> nx_sntp_current_server_time_message),
3083                                                         &(client_ptr -> nx_sntp_client_local_ntp_time));
3084     }
3085 
3086     return status;
3087 }
3088 
3089 
3090 /**************************************************************************/
3091 /*                                                                        */
3092 /*  FUNCTION                                               RELEASE        */
3093 /*                                                                        */
3094 /*    _nx_sntp_client_duplicate_update_check              PORTABLE C      */
3095 /*                                                           6.1          */
3096 /*  AUTHOR                                                                */
3097 /*                                                                        */
3098 /*    Yuxin Zhou, Microsoft Corporation                                   */
3099 /*                                                                        */
3100 /*  DESCRIPTION                                                           */
3101 /*                                                                        */
3102 /*    This function performs a comparison of time values between two      */
3103 /*    time messages to verify they are not duplicates.  Duplicate updates */
3104 /*    can be a form of denial of service/clogging attack on a host.       */
3105 /*                                                                        */
3106 /*   INPUT                                                                */
3107 /*                                                                        */
3108 /*    timeA_msg_ptr                       Pointer to first time update    */
3109 /*    timeB_msg_ptr                       Pointer to second time update   */
3110 /*    is_a_dupe                           Result of comparison            */
3111 /*                                                                        */
3112 /*  OUTPUT                                                                */
3113 /*                                                                        */
3114 /*    NX_SUCCESS                          Successful completion status    */
3115 /*                                                                        */
3116 /*  CALLS                                                                 */
3117 /*                                                                        */
3118 /*    memcmp                              Copy data to area of memory     */
3119 /*                                                                        */
3120 /*  CALLED BY                                                             */
3121 /*                                                                        */
3122 /*    _nx_sntp_client_apply_sanity_checks Verify received SNTP data       */
3123 /*                                                                        */
3124 /*  RELEASE HISTORY                                                       */
3125 /*                                                                        */
3126 /*    DATE              NAME                      DESCRIPTION             */
3127 /*                                                                        */
3128 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3129 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3130 /*                                            resulting in version 6.1    */
3131 /*                                                                        */
3132 /**************************************************************************/
_nx_sntp_client_duplicate_update_check(NX_SNTP_TIME_MESSAGE * timeA_msg_ptr,NX_SNTP_TIME_MESSAGE * timeB_msg_ptr,UINT * is_a_dupe)3133 UINT  _nx_sntp_client_duplicate_update_check(NX_SNTP_TIME_MESSAGE *timeA_msg_ptr,
3134                                             NX_SNTP_TIME_MESSAGE *timeB_msg_ptr,
3135                                             UINT *is_a_dupe)
3136 {
3137 
3138     *is_a_dupe = NX_FALSE;
3139 
3140     if ( (!memcmp(timeA_msg_ptr -> transmit_time_stamp,
3141                   timeB_msg_ptr -> transmit_time_stamp, 8))                               &&
3142          (!memcmp(timeA_msg_ptr -> receive_time_stamp,
3143                   timeB_msg_ptr -> receive_time_stamp, 8))                                &&
3144          (!memcmp(timeA_msg_ptr -> originate_time_stamp,
3145                   timeB_msg_ptr -> originate_time_stamp, 8))                              &&
3146          (!memcmp(timeA_msg_ptr -> reference_clock_update_time_stamp,
3147                   timeB_msg_ptr -> reference_clock_update_time_stamp, 8))                 &&
3148          (!memcmp(timeA_msg_ptr -> reference_clock_id,
3149                   timeB_msg_ptr -> reference_clock_id, 4))                                &&
3150          (timeA_msg_ptr -> root_delay == timeB_msg_ptr -> root_delay)                     &&
3151          (timeA_msg_ptr -> clock_dispersion == timeB_msg_ptr -> clock_dispersion)
3152        )
3153     {
3154 
3155         *is_a_dupe = NX_TRUE;
3156     }
3157 
3158     return NX_SUCCESS;
3159 }
3160 
3161 
3162 /**************************************************************************/
3163 /*                                                                        */
3164 /*  FUNCTION                                               RELEASE        */
3165 /*                                                                        */
3166 /*    _nx_sntp_client_apply_sanity_checks                 PORTABLE C      */
3167 /*                                                           6.1          */
3168 /*  AUTHOR                                                                */
3169 /*                                                                        */
3170 /*    Yuxin Zhou, Microsoft Corporation                                   */
3171 /*                                                                        */
3172 /*  DESCRIPTION                                                           */
3173 /*                                                                        */
3174 /*    This function checks for invalid SNTP data received from server.    */
3175 /*                                                                        */
3176 /*   INPUT                                                                */
3177 /*                                                                        */
3178 /*    client_ptr                       Pointer to Client                  */
3179 /*                                                                        */
3180 /*  OUTPUT                                                                */
3181 /*                                                                        */
3182 /*    NX_SNTP_DUPE_SERVER_PACKET       Duplicate server packet received   */
3183 /*    NX_SNTP_INVALID_SERVER_MODE      Server mode won't work with Client */
3184 /*    NX_SNTP_INVALID_NTP_VERSION      Server NTP version won't work with */
3185 /*                                       Client NTP version.              */
3186 /*    NX_SNTP_SERVER_CLOCK_NOT_SYNC    Server is not ready to send updates*/
3187 /*    NX_SNTP_INVALID_SERVER_STRATUM   Server stratum not acceptable      */
3188 /*    NX_SNTP_NULL_SERVER_TIMESTAMP    Invalid or NULL timestamp in update*/
3189 /*    status                           Actual completion status           */
3190 /*                                                                        */
3191 /*  CALLS                                                                 */
3192 /*                                                                        */
3193 /*    memcmp                           Copy data into area of memory      */
3194 /*    _nx_sntp_client_duplicate_update_check                              */
3195 /*                                     Check for duplicate updates service*/
3196 /*    _nx_sntp_client_utility_get_msec_diff                               */
3197 /*                                     Check for time difference in msecs */
3198 /*                                                                        */
3199 /*  CALLED BY                                                             */
3200 /*                                                                        */
3201 /*    _nx_sntp_client_run_broadcast    Receive broadcast SNTP updates     */
3202 /*    _nx_sntp_client_run_unicast      Send and receive SNTP updates      */
3203 /*                                                                        */
3204 /*  RELEASE HISTORY                                                       */
3205 /*                                                                        */
3206 /*    DATE              NAME                      DESCRIPTION             */
3207 /*                                                                        */
3208 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3209 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3210 /*                                            resulting in version 6.1    */
3211 /*                                                                        */
3212 /**************************************************************************/
_nx_sntp_client_apply_sanity_checks(NX_SNTP_CLIENT * client_ptr)3213 UINT  _nx_sntp_client_apply_sanity_checks(NX_SNTP_CLIENT *client_ptr)
3214 {
3215 
3216 
3217 UINT    status;
3218 UINT    mode;
3219 UINT    leap_second_indicator;
3220 UINT    server_ntp_version;
3221 UINT    is_a_dupe_check;
3222 ULONG   msecs;
3223 NX_SNTP_TIME_MESSAGE *server_time_msg_ptr;
3224 
3225     server_time_msg_ptr = &(client_ptr -> nx_sntp_current_server_time_message);
3226 
3227     /* Was a previous response received from the server?  */
3228     if (client_ptr -> nx_sntp_previous_server_time_message.flags)
3229     {
3230 
3231         /* Yes; perform a duplicate packet check.  */
3232         status = _nx_sntp_client_duplicate_update_check(&(client_ptr -> nx_sntp_current_server_time_message),
3233                                                         &(client_ptr -> nx_sntp_previous_server_time_message),
3234                                                         &is_a_dupe_check);
3235         /* Check for error.  */
3236         if (status != NX_SUCCESS)
3237         {
3238 
3239             /* Return error status.  */
3240             return status;
3241         }
3242 
3243         /* Is this a duplicate packet (e.g. possible 'clogging' attack)?  */
3244         if (is_a_dupe_check)
3245         {
3246 
3247             return NX_SNTP_DUPE_SERVER_PACKET;
3248         }
3249     }
3250 
3251     /* Get the association type from the server.  */
3252     mode = server_time_msg_ptr ->flags & 0x07;
3253 
3254     /* Is the server of the correct association for a unicast client?  */
3255     if ((mode != PROTOCOL_MODE_SERVER_UNICAST) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3256     {
3257 
3258         /* Return error status.  */
3259         return NX_SNTP_INVALID_SERVER_MODE;
3260     }
3261     /* Is the server of the correct association for a broadcast client?  */
3262     else if ((mode != PROTOCOL_MODE_SERVER_BROADCAST) && (client_ptr -> nx_sntp_client_protocol_mode == BROADCAST_MODE))
3263     {
3264 
3265         /* Return error status.  */
3266         return NX_SNTP_INVALID_SERVER_MODE;
3267     }
3268 
3269     /* Extract server's NTP version from the flags field.  */
3270     server_ntp_version = (server_time_msg_ptr -> flags & 0x38) >> 3;
3271 
3272     /* As per NTP protocol, check if the server reply has the same SNTP version that
3273       the Client sent in its unicast request.  */
3274     if ((server_ntp_version != NX_SNTP_CLIENT_NTP_VERSION) && (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE))
3275     {
3276 
3277         /* Return the error condition.  */
3278         return NX_SNTP_INVALID_NTP_VERSION;
3279     }
3280     /* If broadcast, verify the server SNTP version is compatible with the Client.  */
3281     else if ((server_ntp_version < NX_SNTP_CLIENT_MIN_NTP_VERSION) && (client_ptr -> nx_sntp_client_protocol_mode == BROADCAST_MODE))
3282     {
3283 
3284         /* Return the error condition.  */
3285         return NX_SNTP_INVALID_NTP_VERSION;
3286     }
3287 
3288     /* Get the leap second indicator from the flags field.  */
3289     leap_second_indicator = (server_time_msg_ptr -> flags & 0xC0) >> 6;
3290 
3291     /* Is the server clock not yet synchronized?  */
3292     if (leap_second_indicator == 3)
3293     {
3294         /* Return the error condition.  */
3295         return NX_SNTP_SERVER_CLOCK_NOT_SYNC;
3296     }
3297 
3298     /* Has the server sent a 'kiss of death' (stratum = 0) packet?  */
3299     if (server_time_msg_ptr -> peer_clock_stratum == 0)
3300     {
3301 
3302         /* Does the Client have a kiss of death handler?  */
3303         if (client_ptr -> kiss_of_death_handler)
3304         {
3305             UINT code_id;
3306 
3307             /* Convert the message to code.*/
3308             _nx_sntp_client_utility_convert_refID_KOD_code(server_time_msg_ptr -> reference_clock_id, &code_id);
3309 
3310             /* Yes, let the handler deal with this server response.  */
3311             status = (client_ptr -> kiss_of_death_handler)(client_ptr, code_id);
3312 
3313             /* Is it ok to continue with this server?  */
3314             if (status != NX_SUCCESS)
3315             {
3316 
3317                 /* No, it is not. Return the error condition.  */
3318                 return status;
3319             }
3320         }
3321         else
3322         {
3323             /* It is not ok to continue. Return the error condition. */
3324             return NX_SNTP_KOD_SERVER_NOT_AVAILABLE;
3325         }
3326     }
3327 
3328     /* Is the server stratum a valid stratum ?  */
3329     else if (server_time_msg_ptr -> peer_clock_stratum & STRATUM_RESERVED)
3330     {
3331 
3332         /* Return error status.  */
3333         return NX_SNTP_INVALID_SERVER_STRATUM;
3334 
3335     }
3336     /* Does the server stratum acceptable to the Client?  */
3337     else if (server_time_msg_ptr -> peer_clock_stratum > NX_SNTP_CLIENT_MIN_SERVER_STRATUM)
3338     {
3339 
3340         /* Return error status.  */
3341         return NX_SNTP_INVALID_SERVER_STRATUM;
3342     }
3343 
3344     /* Is the Client operating in unicast mode?  */
3345     if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
3346     {
3347     UINT pos_diff = NX_TRUE;
3348 
3349         /* Yes; Are any server time stamps NULL?  */
3350 
3351         /* Special case: the client has not set its local time. Only check server's receive and transmit time. */
3352         if (client_ptr -> nx_sntp_client_local_ntp_time.seconds == 0)
3353         {
3354             if ((_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> receive_time_stamp), 8) == NX_TRUE) ||
3355                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE))
3356             {
3357 
3358                 /* Return error status.  */
3359                 return NX_SNTP_INVALID_TIMESTAMP;
3360             }
3361 
3362         }
3363         else
3364         {
3365             /* Check all server time stamps to be non null.  */
3366             if ((_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> originate_time_stamp), 8) == NX_TRUE) ||
3367                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> receive_time_stamp), 8) == NX_TRUE) ||
3368                 (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE))
3369             {
3370 
3371                 /* Return error status.  */
3372                 return NX_SNTP_INVALID_TIMESTAMP;
3373             }
3374 
3375         }
3376 
3377         /* Get the time difference  server transmit time - server receive time.  */
3378         status = _nx_sntp_client_utility_get_msec_diff(&(server_time_msg_ptr -> receive_time),
3379                                                        &(server_time_msg_ptr -> transmit_time),
3380                                                        &msecs, &pos_diff);
3381 
3382         /* Is the server transmit time <= server receive time [physically not possible]?  */
3383         if (status != NX_SUCCESS)
3384         {
3385 
3386             /* Yes; Return the error condition.  */
3387             return status;
3388         }
3389         else if (pos_diff == NX_FALSE)
3390         {
3391 
3392             /* treat as an error in this case. */
3393             return NX_SNTP_INVALID_TIMESTAMP;
3394         }
3395     }
3396     /* Client is in broadcast mode.  */
3397     else
3398     {
3399 
3400         /* Is the broadcast server transmit time stamp is NULL?  */
3401         if (_nx_sntp_client_utility_is_zero_data((UCHAR *)(server_time_msg_ptr -> transmit_time_stamp), 8) == NX_TRUE)
3402 
3403         {
3404 
3405             /* Return the error status.  */
3406             return NX_SNTP_INVALID_TIMESTAMP;
3407         }
3408     }
3409 
3410     /* Is there an impending leap second adjustment?  */
3411     if ((leap_second_indicator == 1) || (leap_second_indicator == 2))
3412     {
3413 
3414         /* Does the Client have a leap second handler?*/
3415         if (client_ptr -> leap_second_handler)
3416         {
3417 
3418             /* Yes, invoke the leap second handler for impending leap second event.  */
3419             (client_ptr -> leap_second_handler)(client_ptr, leap_second_indicator);
3420         }
3421     }
3422 
3423     /* Return successful completion status.  */
3424     return NX_SUCCESS;
3425 }
3426 
3427 
3428 /**************************************************************************/
3429 /*                                                                        */
3430 /*  FUNCTION                                               RELEASE        */
3431 /*                                                                        */
3432 /*    _nx_sntp_client_check_server_clock_dispersion       PORTABLE C      */
3433 /*                                                           6.1          */
3434 /*  AUTHOR                                                                */
3435 /*                                                                        */
3436 /*    Yuxin Zhou, Microsoft Corporation                                   */
3437 /*                                                                        */
3438 /*  DESCRIPTION                                                           */
3439 /*                                                                        */
3440 /*    This function checks server clock dispersion extracted from server  */
3441 /*    time message in 32 bit representation:                              */
3442 /*        sum of 1/(2 ^ bit) of bits 16-31 in the time message format     */
3443 /*    and compares it against the Client's dispersion tolerance.          */
3444 /*                                                                        */
3445 /*    If NX_SNTP_CLIENT_MAX_ROOT_DISPERSION is set to zero, the function  */
3446 /*    simply returns a successful result but does no calculations.        */
3447 /*                                                                        */
3448 /*   INPUT                                                                */
3449 /*                                                                        */
3450 /*    client_ptr                         Pointer to Client                */
3451 /*                                                                        */
3452 /*  OUTPUT                                                                */
3453 /*                                                                        */
3454 /*    NX_SUCCESS                         dispersion is acceptable         */
3455 /*    NX_SNTP_BAD_SERVER_ROOT_DISPERSION dispersion is too large          */
3456 /*                                                                        */
3457 /*  CALLS                                                                 */
3458 /*                                                                        */
3459 /*    None                                                                */
3460 /*                                                                        */
3461 /*  CALLED BY                                                             */
3462 /*                                                                        */
3463 /*    _nx_sntp_client_process_update_packet                               */
3464 /*                                    Process time data in update packets */
3465 /*                                                                        */
3466 /*  RELEASE HISTORY                                                       */
3467 /*                                                                        */
3468 /*    DATE              NAME                      DESCRIPTION             */
3469 /*                                                                        */
3470 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3471 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3472 /*                                            resulting in version 6.1    */
3473 /*                                                                        */
3474 /**************************************************************************/
3475 
_nx_sntp_client_check_server_clock_dispersion(NX_SNTP_CLIENT * client_ptr)3476 UINT  _nx_sntp_client_check_server_clock_dispersion(NX_SNTP_CLIENT *client_ptr)
3477 {
3478 
3479 #if (NX_SNTP_CLIENT_MAX_ROOT_DISPERSION != 0)
3480 UINT    mask = 0x8000;
3481 UINT    bit = 1;
3482 ULONG   divisor;
3483 ULONG   dispersion_usecs;
3484 
3485     /* Check for zero clock dispersion reported in server update.  */
3486     if (client_ptr -> nx_sntp_current_server_time_message.clock_dispersion == 0)
3487     {
3488 
3489         /* Return successful status.  */
3490         return NX_SUCCESS;
3491     }
3492 
3493     /* Get the most significant 16 bits of dispersion field and convert to microseconds.*/
3494     dispersion_usecs = (client_ptr -> nx_sntp_current_server_time_message.clock_dispersion >> 16) * 1000000;
3495 
3496     /* Compare seconds in the most significant 16 bits against the Client dispersion tolerance.  */
3497     if (dispersion_usecs > NX_SNTP_CLIENT_MAX_ROOT_DISPERSION)
3498     {
3499 
3500         /* Yes, indicate that server clock dispersion exceeds tolerance.  */
3501         return NX_SNTP_BAD_SERVER_ROOT_DISPERSION;
3502     }
3503 
3504     /* Compare fraction from least significant 16 bits; sum of (1 / 2 ^ bit field) of lower 16 bits.  */
3505 
3506     /* Get the lower 16 bits.  */
3507     client_ptr -> nx_sntp_current_server_time_message.clock_dispersion =
3508         client_ptr -> nx_sntp_current_server_time_message.clock_dispersion & 0xFFFF;
3509 
3510     /* Compute the dispersion.  */
3511     while(mask)
3512     {
3513         if (mask & client_ptr -> nx_sntp_current_server_time_message.clock_dispersion)
3514         {
3515             divisor = (ULONG)(1 << bit);
3516             if ((divisor < 1000000) && (divisor > 0))
3517             {
3518                 dispersion_usecs += 1000000/divisor;
3519             }
3520         }
3521         bit++;
3522         mask >>= 1;
3523     }
3524 
3525     /* Is the computed clock dispersion more than the max tolerance?  */
3526     if (dispersion_usecs > NX_SNTP_CLIENT_MAX_ROOT_DISPERSION)
3527     {
3528         /* Yes, indicate that server clock dispersion exceeds tolerance.  */
3529         return NX_SNTP_BAD_SERVER_ROOT_DISPERSION;
3530     }
3531 #else
3532     NX_PARAMETER_NOT_USED(client_ptr);
3533 #endif /* (NX_SNTP_CLIENT_MAX_ROOT_DISPERSION != 0) */
3534 
3535     /* Return successful computation.  */
3536     return NX_SUCCESS;
3537 }
3538 
3539 
3540 /**************************************************************************/
3541 /*                                                                        */
3542 /*  FUNCTION                                               RELEASE        */
3543 /*                                                                        */
3544 /*    _nx_sntp_client_thread_entry                        PORTABLE C      */
3545 /*                                                           6.1          */
3546 /*  AUTHOR                                                                */
3547 /*                                                                        */
3548 /*    Yuxin Zhou, Microsoft Corporation                                   */
3549 /*                                                                        */
3550 /*  DESCRIPTION                                                           */
3551 /*                                                                        */
3552 /*    This function is the processing thread for the SNTP Client. It      */
3553 /*    executes periodic SNTP tasks with SNTP Client mutex protection, then*/
3554 /*    briefly sleeps to allow the host application to call SNTP Client    */
3555 /*    services.                                                           */
3556 /*                                                                        */
3557 /*  INPUT                                                                 */
3558 /*                                                                        */
3559 /*    sntp_instance                         Pointer to SNTP instance      */
3560 /*                                                                        */
3561 /*  OUTPUT                                                                */
3562 /*                                                                        */
3563 /*    None                                                                */
3564 /*                                                                        */
3565 /*  CALLS                                                                 */
3566 /*                                                                        */
3567 /*    _nx_sntp_client_process               Main SNTP processing function */
3568 /*    tx_thread_sleep                       Sleep for specified time      */
3569 /*    tx_mutex_get                          Get the SNTP mutex            */
3570 /*    tx_mutex_put                          Release the SNTP mutex        */
3571 /*    tx_thread_preemption_change           Change thread preemption      */
3572 /*                                                                        */
3573 /*  CALLED BY                                                             */
3574 /*                                                                        */
3575 /*    ThreadX                                                             */
3576 /*                                                                        */
3577 /*  RELEASE HISTORY                                                       */
3578 /*                                                                        */
3579 /*    DATE              NAME                      DESCRIPTION             */
3580 /*                                                                        */
3581 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3582 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3583 /*                                            resulting in version 6.1    */
3584 /*                                                                        */
3585 /**************************************************************************/
_nx_sntp_client_thread_entry(ULONG sntp_instance)3586 VOID  _nx_sntp_client_thread_entry(ULONG sntp_instance)
3587 {
3588 
3589 NX_SNTP_CLIENT *client_ptr;
3590 UINT    status;
3591 UINT    current_preemption;
3592 
3593 
3594     /* Setup the SNTP pointer.  */
3595     client_ptr =    (NX_SNTP_CLIENT *) sntp_instance;
3596 
3597     /* Enter while loop.  */
3598     do
3599     {
3600 
3601         /* Loop for obtaining the SNTP mutex.  */
3602         do
3603         {
3604 
3605             /* Get the SNTP mutex.  */
3606             status =  tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
3607 
3608         } while (status != TX_SUCCESS);
3609 
3610         /* Perform periodic tasks for the SNTP Client.  */
3611         _nx_sntp_client_process(client_ptr);
3612 
3613          /* Release the SNTP mutex.  */
3614         tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
3615 
3616         /* Disable preemption for critical section.  */
3617         tx_thread_preemption_change(tx_thread_identify(), 0, &current_preemption);
3618 
3619         /* Indicate the SNTP Client process is idle. */
3620         client_ptr -> nx_sntp_client_sleep_flag =  NX_TRUE;
3621 
3622         /* Sleep for timer interval.  */
3623         tx_thread_sleep(NX_SNTP_CLIENT_SLEEP_INTERVAL);
3624 
3625         /* Clear flag to indicate SNTP thread is not in a position to be stopped.  */
3626         client_ptr -> nx_sntp_client_sleep_flag =  NX_FALSE;
3627 
3628         /* Restore original preemption.  */
3629         tx_thread_preemption_change(tx_thread_identify(), current_preemption, &current_preemption);
3630 
3631 
3632     } while (1);
3633 }
3634 
3635 
3636 /**************************************************************************/
3637 /*                                                                        */
3638 /*  FUNCTION                                               RELEASE        */
3639 /*                                                                        */
3640 /*    _nx_sntp_client_receive_notify                      PORTABLE C      */
3641 /*                                                           6.1          */
3642 /*  AUTHOR                                                                */
3643 /*                                                                        */
3644 /*    Yuxin Zhou, Microsoft Corporation                                   */
3645 /*                                                                        */
3646 /*  DESCRIPTION                                                           */
3647 /*                                                                        */
3648 /*    This function sets the socket receive callback for the SNTP Client  */
3649 /*    UDP socket.  It sets a flag for the SNTP Client thread to know there*/
3650 /*    is a packet waiting to be processed.                                */
3651 /*                                                                        */
3652 /*  INPUT                                                                 */
3653 /*                                                                        */
3654 /*    socket_ptr                           Pointer to Client UDP socket   */
3655 /*                                                                        */
3656 /*  OUTPUT                                                                */
3657 /*                                                                        */
3658 /*    None                                                                */
3659 /*                                                                        */
3660 /*  CALLS                                                                 */
3661 /*                                                                        */
3662 /*    tx_event_flags_set                    Sets a receive event          */
3663 /*                                                                        */
3664 /*  CALLED BY                                                             */
3665 /*                                                                        */
3666 /*    ThreadX                                                             */
3667 /*                                                                        */
3668 /*  RELEASE HISTORY                                                       */
3669 /*                                                                        */
3670 /*    DATE              NAME                      DESCRIPTION             */
3671 /*                                                                        */
3672 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3673 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3674 /*                                            resulting in version 6.1    */
3675 /*                                                                        */
3676 /**************************************************************************/
_nx_sntp_client_receive_notify(NX_UDP_SOCKET * socket_ptr)3677 VOID  _nx_sntp_client_receive_notify(NX_UDP_SOCKET *socket_ptr)
3678 {
3679     NX_PARAMETER_NOT_USED(socket_ptr);
3680 
3681     /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied.  */
3682     tx_event_flags_set(&nx_sntp_client_events, NX_SNTP_CLIENT_RECEIVE_EVENT, TX_OR);
3683 
3684     receive_timerticks = tx_time_get();
3685 
3686     return;
3687 }
3688 
3689 
3690 /**************************************************************************/
3691 /*                                                                        */
3692 /*  FUNCTION                                               RELEASE        */
3693 /*                                                                        */
3694 /*    _nx_sntp_client_process                             PORTABLE C      */
3695 /*                                                           6.1          */
3696 /*  AUTHOR                                                                */
3697 /*                                                                        */
3698 /*    Yuxin Zhou, Microsoft Corporation                                   */
3699 /*                                                                        */
3700 /*  DESCRIPTION                                                           */
3701 /*                                                                        */
3702 /*    This function is called periodically by the SNTP client thread, and */
3703 /*    depending on the CLient mode (unicast or broadcast) calls the       */
3704 /*    unicast or broadcast process function.                              */
3705 /*                                                                        */
3706 /*  INPUT                                                                 */
3707 /*                                                                        */
3708 /*    client_ptr                            Pointer to the SNTP client    */
3709 /*                                                                        */
3710 /*  OUTPUT                                                                */
3711 /*                                                                        */
3712 /*    None                                                                */
3713 /*                                                                        */
3714 /*  CALLS                                                                 */
3715 /*                                                                        */
3716 /*    _nx_sntp_client_process_unicast       Process unicast tasks         */
3717 /*    _nx_sntp_client_process_broadcast     Process broadcast tasks       */
3718 /*                                                                        */
3719 /*  CALLED BY                                                             */
3720 /*                                                                        */
3721 /*    ThreadX                                                             */
3722 /*                                                                        */
3723 /*  RELEASE HISTORY                                                       */
3724 /*                                                                        */
3725 /*    DATE              NAME                      DESCRIPTION             */
3726 /*                                                                        */
3727 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3728 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3729 /*                                            resulting in version 6.1    */
3730 /*                                                                        */
3731 /**************************************************************************/
_nx_sntp_client_process(NX_SNTP_CLIENT * client_ptr)3732 VOID  _nx_sntp_client_process(NX_SNTP_CLIENT *client_ptr)
3733 {
3734 
3735 
3736     /* Is the client using unicast or unicast to receive updates? */
3737     if (client_ptr -> nx_sntp_client_protocol_mode == UNICAST_MODE)
3738     {
3739         /* Call the unicast process function. */
3740         _nx_sntp_client_process_unicast(client_ptr);
3741     }
3742     else
3743     {
3744 
3745         /* Call the broadcast process function. */
3746         _nx_sntp_client_process_broadcast(client_ptr);
3747     }
3748 
3749     return;
3750 }
3751 
3752 
3753 /**************************************************************************/
3754 /*                                                                        */
3755 /*  FUNCTION                                               RELEASE        */
3756 /*                                                                        */
3757 /*    _nx_sntp_client_process_time_data                   PORTABLE C      */
3758 /*                                                           6.1          */
3759 /*  AUTHOR                                                                */
3760 /*                                                                        */
3761 /*    Yuxin Zhou, Microsoft Corporation                                   */
3762 /*                                                                        */
3763 /*  DESCRIPTION                                                           */
3764 /*                                                                        */
3765 /*  This function applies the server time data to client local time taking*/
3766 /*  into account the round trip time.  Time updates are checked for a max */
3767 /*  time offset set by the Client max_time_adjustment parameter.          */
3768 /*                                                                        */
3769 /*   INPUT                                                                */
3770 /*                                                                        */
3771 /*    client_ptr                        Pointer to Client                 */
3772 /*                                                                        */
3773 /*  OUTPUT                                                                */
3774 /*                                                                        */
3775 /*    NX_SUCCESS                        Successful completion status      */
3776 /*    NX_SNTP_INVALID_SERVER_UPDATE_TIME No time of server update recorded*/
3777 /*    status                            Actual completion status          */
3778 /*                                                                        */
3779 /*  CALLS                                                                 */
3780 /*                                                                        */
3781 /*    memset                           Clear specified area of memory     */
3782 /*    memcpy                           Copy data to area of memory        */
3783 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
3784 /*                                     Add msec to NTP time fraction field*/
3785 /*    _nx_sntp_client_utility_get_msec_diff                               */
3786 /*                                     Compute time difference in msecs   */
3787 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
3788 /*                                     Add time in msecs to an NTP time   */
3789 /*                                                                        */
3790 /*  CALLED BY                                                             */
3791 /*                                                                        */
3792 /*    _nx_sntp_client_run_broadcast   Listen and process broadcast updates*/
3793 /*    _nx_sntp_client_process_update_packet                               */
3794 /*                                    Process update SNTP packets         */
3795 /*                                                                        */
3796 /*  RELEASE HISTORY                                                       */
3797 /*                                                                        */
3798 /*    DATE              NAME                      DESCRIPTION             */
3799 /*                                                                        */
3800 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3801 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
3802 /*                                            verified memcpy use cases,  */
3803 /*                                            resulting in version 6.1    */
3804 /*                                                                        */
3805 /**************************************************************************/
_nx_sntp_client_process_time_data(NX_SNTP_CLIENT * client_ptr)3806 UINT  _nx_sntp_client_process_time_data(NX_SNTP_CLIENT *client_ptr)
3807 {
3808 
3809 UINT            status;
3810 UINT            ignore_max_adjustment_limit;
3811 ULONG           elapsed_msecs_difference;
3812 UINT            adjustment;
3813 NX_SNTP_TIME    local_time;
3814 
3815 
3816     /* Copy the received time update to the update time just received from the server. */
3817     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. */
3818 
3819     /* Check if the client is configured for round trip time calculation.  */
3820     if (NX_SNTP_CLIENT_RTT_REQUIRED == NX_TRUE)
3821     {
3822 
3823         /* Compute roundtrip delay. */
3824         _nx_sntp_client_calculate_roundtrip(&(client_ptr -> nx_sntp_client_roundtrip_time_msec));
3825 
3826         /* Has the client computed a valid round trip time?  */
3827         if (client_ptr -> nx_sntp_client_roundtrip_time_msec)
3828         {
3829 
3830             /* Yes, Add 1/2 round trip to server's reported time.  */
3831             status =_nx_sntp_client_utility_add_msecs_to_ntp_time(&(client_ptr -> nx_sntp_current_server_time_message.transmit_time),
3832                                                                    ((client_ptr -> nx_sntp_client_roundtrip_time_msec) / 2));
3833 
3834             if (status != NX_SUCCESS)
3835             {
3836 
3837                 /* Cannot use this time update. */
3838                 return status;
3839             }
3840         }
3841     }
3842 
3843     /* Is this the first update?  */
3844     if (client_ptr -> nx_sntp_client_first_update_pending == NX_TRUE)
3845     {
3846         /* Check Client configuration if we ignore max adjustment limit on first update.  */
3847         ignore_max_adjustment_limit = NX_SNTP_CLIENT_IGNORE_MAX_ADJUST_STARTUP;
3848     }
3849     else
3850         ignore_max_adjustment_limit = NX_FALSE;
3851 
3852     /* If not ignoring the max adjustment, deal with time difference between client and server. */
3853     if (ignore_max_adjustment_limit == NX_FALSE)
3854     {
3855     UINT pos_diff = NX_TRUE;
3856 
3857         /* Compute difference of server update packet minus the client's local time. It is reasonable
3858            to assume that the Client time is 'behind' the server time because it is updated by the
3859            server time.  */
3860         local_time.seconds = client_ptr -> nx_sntp_client_local_ntp_time.seconds +
3861             client_ptr -> nx_sntp_client_local_ntp_time_elapsed;
3862         local_time.fraction = client_ptr -> nx_sntp_client_local_ntp_time.fraction;
3863         status = _nx_sntp_client_utility_get_msec_diff(&local_time,
3864                                                        &(client_ptr -> nx_sntp_server_update_time),
3865                                                        &elapsed_msecs_difference, &pos_diff);
3866 
3867 
3868         /* Note that a positive difference vs negative difference is not an error. */
3869         if (status != NX_SUCCESS)
3870         {
3871 
3872             /* Cannot use this time update. */
3873             return status;
3874         }
3875 
3876         /* Is the difference less than the client's minimum adjustment?  */
3877         if (elapsed_msecs_difference > NX_SNTP_CLIENT_MIN_TIME_ADJUSTMENT)
3878         {
3879 
3880             /* The adjustment is larger than the Client's minimum adjustment. */
3881 
3882             /* Set the local clock to the server time only if 1)we are ignoring the maximum adjustment on startup,
3883                or 2) the difference is within the Client's max time adjustment.  */
3884             if (elapsed_msecs_difference > NX_SNTP_CLIENT_MAX_TIME_ADJUSTMENT)
3885             {
3886                 /* Cannot use this time update. */
3887                 return NX_SNTP_INVALID_TIME;
3888             }
3889         }
3890     }
3891 
3892     /* Ok to update client local time. */
3893     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. */
3894     client_ptr -> nx_sntp_client_local_ntp_time_elapsed = 0;
3895 
3896      /* Apply a correction to server's time for internal SNTP Client delays e.g. periodic task intervals. */
3897     adjustment = ((process_timerticks - receive_timerticks) * 1000) / NX_IP_PERIODIC_RATE;
3898 
3899     status = _nx_sntp_client_utility_add_msecs_to_ntp_time(&(client_ptr -> nx_sntp_client_local_ntp_time), (LONG)adjustment);
3900 
3901     /* Done processing time update. */
3902     return status;
3903 }
3904 
3905 
3906 /**************************************************************************/
3907 /*                                                                        */
3908 /*  FUNCTION                                               RELEASE        */
3909 /*                                                                        */
3910 /*    _nx_sntp_client_calculate_roundtrip                 PORTABLE C      */
3911 /*                                                           6.1          */
3912 /*  AUTHOR                                                                */
3913 /*                                                                        */
3914 /*    Yuxin Zhou, Microsoft Corporation                                   */
3915 /*                                                                        */
3916 /*  DESCRIPTION                                                           */
3917 /*                                                                        */
3918 /*   This function computes roundtrip based on the elapsed time from      */
3919 /*   sending the unicast request to receiving the SNTP response.          */
3920 /*                                                                        */
3921 /*   INPUT                                                                */
3922 /*                                                                        */
3923 /*    roundtrip_time                    round trip time computation       */
3924 /*                                                                        */
3925 /*  OUTPUT                                                                */
3926 /*                                                                        */
3927 /*    NX_SUCCESS                        Valid time computations result    */
3928 /*                                                                        */
3929 /*  CALLS                                                                 */
3930 /*                                                                        */
3931 /*    None                                                                */
3932 /*                                                                        */
3933 /*  CALLED BY                                                             */
3934 /*                                                                        */
3935 /*    _nx_sntp_client_process_update_packet                               */
3936 /*                                      Process server update packet      */
3937 /*                                                                        */
3938 /*  RELEASE HISTORY                                                       */
3939 /*                                                                        */
3940 /*    DATE              NAME                      DESCRIPTION             */
3941 /*                                                                        */
3942 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3943 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3944 /*                                            resulting in version 6.1    */
3945 /*                                                                        */
3946 /**************************************************************************/
_nx_sntp_client_calculate_roundtrip(LONG * roundtrip_time)3947 UINT  _nx_sntp_client_calculate_roundtrip(LONG *roundtrip_time)
3948 {
3949 
3950 ULONG x;
3951 
3952 
3953     /* Initialize invalid results. */
3954     *roundtrip_time = 0;
3955 
3956     /* Compute the roundtrip as the time the packet left the SNTP Client
3957        to the time it received a response from the SNTP server. */
3958 
3959     /* Check for wrapped timer value. */
3960     if (send_timerticks > receive_timerticks)
3961     {
3962         /* The time has wrapped.  */
3963         x = 0xFFFFFFFF - send_timerticks;
3964         *roundtrip_time = (LONG)(receive_timerticks + x);
3965     }
3966     else
3967     {
3968          *roundtrip_time = (LONG)(receive_timerticks - send_timerticks);
3969     }
3970 
3971     /* Convert to milliseconds. */
3972     *roundtrip_time = (LONG)((ULONG)(*roundtrip_time) * NX_SNTP_MILLISECONDS_PER_TICK);
3973 
3974      /* Return successful completion.  */
3975      return NX_SUCCESS;
3976 }
3977 
3978 
3979 /**************************************************************************/
3980 /*                                                                        */
3981 /*  FUNCTION                                               RELEASE        */
3982 /*                                                                        */
3983 /*    _nxe_sntp_client_get_local_time                      PORTABLE C     */
3984 /*                                                           6.1          */
3985 /*  AUTHOR                                                                */
3986 /*                                                                        */
3987 /*    Yuxin Zhou, Microsoft Corporation                                   */
3988 /*                                                                        */
3989 /*  DESCRIPTION                                                           */
3990 /*                                                                        */
3991 /*   This function performs error checking for the get local time service.*/
3992 /*                                                                        */
3993 /*   INPUT                                                                */
3994 /*                                                                        */
3995 /*    client_ptr                        Pointer to SNTP Client            */
3996 /*    seconds                           Pointer to SNTP seconds           */
3997 /*    fraction                          Local time fraction component     */
3998 /*    buffer                            Pointer for time in string format */
3999 /*                                                                        */
4000 /*  OUTPUT                                                                */
4001 /*                                                                        */
4002 /*    status                            Completion status                 */
4003 /*                                                                        */
4004 /*  CALLS                                                                 */
4005 /*                                                                        */
4006 /*    _nx_sntp_client_get_local_time    Get local time service            */
4007 /*                                                                        */
4008 /*  CALLED BY                                                             */
4009 /*                                                                        */
4010 /*    Application Code                                                    */
4011 /*                                                                        */
4012 /*  RELEASE HISTORY                                                       */
4013 /*                                                                        */
4014 /*    DATE              NAME                      DESCRIPTION             */
4015 /*                                                                        */
4016 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4017 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4018 /*                                            resulting in version 6.1    */
4019 /*                                                                        */
4020 /**************************************************************************/
_nxe_sntp_client_get_local_time(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer)4021 UINT  _nxe_sntp_client_get_local_time(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer)
4022 {
4023 
4024 UINT status;
4025 
4026 
4027     /* Check input pointer parameters.  */
4028     if ((client_ptr == NX_NULL) || (seconds == NX_NULL) || (fraction == NX_NULL))
4029     {
4030 
4031         /* Return pointer error.  */
4032         return NX_PTR_ERROR;
4033     }
4034 
4035     /* Check if this function is called from the appropriate thread.  */
4036     NX_THREADS_ONLY_CALLER_CHECKING
4037 
4038     /* Call the actual service.  */
4039     status = _nx_sntp_client_get_local_time(client_ptr, seconds, fraction, buffer);
4040 
4041     /* Return completion status.  */
4042     return status;
4043 }
4044 
4045 
4046 /**************************************************************************/
4047 /*                                                                        */
4048 /*  FUNCTION                                               RELEASE        */
4049 /*                                                                        */
4050 /*    _nx_sntp_client_get_local_time                      PORTABLE C      */
4051 /*                                                           6.1          */
4052 /*  AUTHOR                                                                */
4053 /*                                                                        */
4054 /*    Yuxin Zhou, Microsoft Corporation                                   */
4055 /*                                                                        */
4056 /*  DESCRIPTION                                                           */
4057 /*                                                                        */
4058 /*   This function retrieves the current SNTP Client local time and       */
4059 /*   returns the data in seconds and fractions, and if a non zero         */
4060 /*   buffer pointer is supplied, a string containing the data in ASCII.   */
4061 /*                                                                        */
4062 /*   INPUT                                                                */
4063 /*                                                                        */
4064 /*    client_ptr                        Pointer to SNTP Client            */
4065 /*    seconds                           Pointer to SNTP seconds           */
4066 /*    fraction                          Local time fraction component     */
4067 /*    buffer                            Pointer for time in string format */
4068 /*                                                                        */
4069 /*  OUTPUT                                                                */
4070 /*                                                                        */
4071 /*    status                                Completion status             */
4072 /*                                                                        */
4073 /*  CALLS                                                                 */
4074 /*                                                                        */
4075 /*    _nx_utility_string_length_check       Check string length           */
4076 /*    _nx_sntp_client_get_local_time_extended                             */
4077 /*                                          Get local time service        */
4078 /*                                                                        */
4079 /*  CALLED BY                                                             */
4080 /*                                                                        */
4081 /*    Application Code                                                    */
4082 /*                                                                        */
4083 /*  RELEASE HISTORY                                                       */
4084 /*                                                                        */
4085 /*    DATE              NAME                      DESCRIPTION             */
4086 /*                                                                        */
4087 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4088 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4089 /*                                            resulting in version 6.1    */
4090 /*                                                                        */
4091 /**************************************************************************/
_nx_sntp_client_get_local_time(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer)4092 UINT  _nx_sntp_client_get_local_time(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer)
4093 {
4094 
4095 UINT  status;
4096 
4097     status = _nx_sntp_client_get_local_time_extended(client_ptr, seconds, fraction, buffer, NX_MAX_STRING_LENGTH);
4098 
4099     return status;
4100 }
4101 
4102 /**************************************************************************/
4103 /*                                                                        */
4104 /*  FUNCTION                                               RELEASE        */
4105 /*                                                                        */
4106 /*    _nxe_sntp_client_get_local_time_extended             PORTABLE C     */
4107 /*                                                           6.1          */
4108 /*  AUTHOR                                                                */
4109 /*                                                                        */
4110 /*    Yuxin Zhou, Microsoft Corporation                                   */
4111 /*                                                                        */
4112 /*  DESCRIPTION                                                           */
4113 /*                                                                        */
4114 /*   This function performs error checking for the get extended local     */
4115 /*   time service.                                                        */
4116 /*                                                                        */
4117 /*   INPUT                                                                */
4118 /*                                                                        */
4119 /*    client_ptr                        Pointer to SNTP Client            */
4120 /*    seconds                           Pointer to SNTP seconds           */
4121 /*    fraction                          Local time fraction component     */
4122 /*    buffer                            Pointer for time in string format */
4123 /*    buffer_size                       Size of buffer                    */
4124 /*                                                                        */
4125 /*  OUTPUT                                                                */
4126 /*                                                                        */
4127 /*    status                            Completion status                 */
4128 /*                                                                        */
4129 /*  CALLS                                                                 */
4130 /*                                                                        */
4131 /*    _nx_sntp_client_get_local_time_extended                             */
4132 /*                                      Get extended local time service   */
4133 /*                                                                        */
4134 /*  CALLED BY                                                             */
4135 /*                                                                        */
4136 /*    Application Code                                                    */
4137 /*                                                                        */
4138 /*  RELEASE HISTORY                                                       */
4139 /*                                                                        */
4140 /*    DATE              NAME                      DESCRIPTION             */
4141 /*                                                                        */
4142 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4143 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4144 /*                                            resulting in version 6.1    */
4145 /*                                                                        */
4146 /**************************************************************************/
_nxe_sntp_client_get_local_time_extended(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer,UINT buffer_size)4147 UINT  _nxe_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size)
4148 {
4149 
4150 UINT status;
4151 
4152 
4153     /* Check input pointer parameters.  */
4154     if ((client_ptr == NX_NULL) || (seconds == NX_NULL) || (fraction == NX_NULL))
4155     {
4156 
4157         /* Return pointer error.  */
4158         return NX_PTR_ERROR;
4159     }
4160 
4161     /* Check if this function is called from the appropriate thread.  */
4162     NX_THREADS_ONLY_CALLER_CHECKING
4163 
4164     /* Call the actual service.  */
4165     status = _nx_sntp_client_get_local_time_extended(client_ptr, seconds, fraction, buffer, buffer_size);
4166 
4167     /* Return completion status.  */
4168     return status;
4169 }
4170 
4171 
4172 /**************************************************************************/
4173 /*                                                                        */
4174 /*  FUNCTION                                               RELEASE        */
4175 /*                                                                        */
4176 /*    _nx_sntp_client_get_local_time_extended             PORTABLE C      */
4177 /*                                                           6.1.8        */
4178 /*  AUTHOR                                                                */
4179 /*                                                                        */
4180 /*    Yuxin Zhou, Microsoft Corporation                                   */
4181 /*                                                                        */
4182 /*  DESCRIPTION                                                           */
4183 /*                                                                        */
4184 /*   This function retrieves the current SNTP Client local time and       */
4185 /*   returns the data in seconds and fractions, and if a non zero         */
4186 /*   buffer pointer is supplied, a string containing the data in ASCII.   */
4187 /*                                                                        */
4188 /*   INPUT                                                                */
4189 /*                                                                        */
4190 /*    client_ptr                        Pointer to SNTP Client            */
4191 /*    seconds                           Pointer to SNTP seconds           */
4192 /*    fraction                          Local time fraction component     */
4193 /*    buffer                            Pointer for time in string format */
4194 /*    buffer_size                       Size of buffer                    */
4195 /*                                                                        */
4196 /*  OUTPUT                                                                */
4197 /*                                                                        */
4198 /*    status                            Completion status                 */
4199 /*                                                                        */
4200 /*  CALLS                                                                 */
4201 /*                                                                        */
4202 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
4203 /*                                      Convert NTP fraction to usecs     */
4204 /*    _nx_utility_uint_to_string        Converts number to ascii text     */
4205 /*                                                                        */
4206 /*  CALLED BY                                                             */
4207 /*                                                                        */
4208 /*    Application Code                                                    */
4209 /*                                                                        */
4210 /*  RELEASE HISTORY                                                       */
4211 /*                                                                        */
4212 /*    DATE              NAME                      DESCRIPTION             */
4213 /*                                                                        */
4214 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4215 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4216 /*                                            verified memmove use cases, */
4217 /*                                            resulting in version 6.1    */
4218 /*  08-02-2021     Yuxin Zhou               Modified comment(s),          */
4219 /*                                            improved the logic of       */
4220 /*                                            converting number to string,*/
4221 /*                                            resulting in version 6.1.8  */
4222 /*                                                                        */
4223 /**************************************************************************/
_nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT * client_ptr,ULONG * seconds,ULONG * fraction,CHAR * buffer,UINT buffer_size)4224 UINT  _nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size)
4225 {
4226 
4227 ULONG usecs;
4228 UINT offset = 0;
4229 UINT length = 0;
4230 
4231     *seconds = client_ptr -> nx_sntp_client_local_ntp_time.seconds;
4232     *fraction = client_ptr -> nx_sntp_client_local_ntp_time.fraction;
4233 
4234     if (buffer != NX_NULL)
4235     {
4236 
4237         /* Convert SNTP fraction component into microseconds.  */
4238         _nx_sntp_client_utility_fraction_to_usecs(client_ptr -> nx_sntp_client_local_ntp_time.fraction, &usecs);
4239 
4240         /* Decrease length for terminal zero. */
4241         buffer_size--;
4242 
4243         /* Create a string with just the time.  */
4244         /* Format: "Time: %lu.%06lu sec.\r\n" */
4245         if (buffer_size < 6)
4246         {
4247             return(NX_SIZE_ERROR);
4248         }
4249         buffer[offset++] = 'T';
4250         buffer[offset++] = 'i';
4251         buffer[offset++] = 'm';
4252         buffer[offset++] = 'e';
4253         buffer[offset++] = ':';
4254         buffer[offset++] = ' ';
4255         length = _nx_utility_uint_to_string(client_ptr -> nx_sntp_client_local_ntp_time.seconds,
4256                                             10, &buffer[offset], buffer_size - offset);
4257         if (length == 0)
4258         {
4259             return(NX_SIZE_ERROR);
4260         }
4261         offset += length;
4262         if ((buffer_size - offset) < 14)
4263         {
4264             return(NX_SIZE_ERROR);
4265         }
4266         buffer[offset++] = '.';
4267         length = _nx_utility_uint_to_string(usecs, 10, &buffer[offset], buffer_size - offset);
4268         if (length == 0)
4269         {
4270             return(NX_SIZE_ERROR);
4271         }
4272 
4273         if (length < 6)
4274         {
4275 
4276             /* Append zeroes. */
4277             memmove(&buffer[offset + (6 - length)], &buffer[offset], length); /* Use case of memmove is verified.  */
4278             memset(&buffer[offset], '0', (6 - length));
4279         }
4280 
4281         offset += 6;
4282         buffer[offset++] = ' ';
4283         buffer[offset++] = 's';
4284         buffer[offset++] = 'e';
4285         buffer[offset++] = 'c';
4286         buffer[offset++] = '.';
4287         buffer[offset++] = '\r';
4288         buffer[offset++] = '\n';
4289         buffer[offset] = '\0';
4290     }
4291 
4292     return NX_SUCCESS;
4293 }
4294 
4295 
4296 /**************************************************************************/
4297 /*                                                                        */
4298 /*  FUNCTION                                               RELEASE        */
4299 /*                                                                        */
4300 /*    _nx_sntp_client_utility_convert_time_to_UCHAR       PORTABLE C      */
4301 /*                                                           6.1          */
4302 /*  AUTHOR                                                                */
4303 /*                                                                        */
4304 /*    Yuxin Zhou, Microsoft Corporation                                   */
4305 /*                                                                        */
4306 /*  DESCRIPTION                                                           */
4307 /*                                                                        */
4308 /*    This function converts time from the ULONG seconds and msecs in the */
4309 /*    NX_SNTP_TIME data to the 32 bit UCHAR seconds and fraction fields in*/
4310 /*    the NTP time message.  The caller specifies which time stamp in the */
4311 /*    NTP time message (transmit,receive, origination, or reference clock)*/
4312 /*    and that field is converted over.                                   */
4313 /*                                                                        */
4314 /*   INPUT                                                                */
4315 /*                                                                        */
4316 /*    time_ptr                        Pointer to NX_SNTP_TIME time        */
4317 /*    time_message_ptr                Pointer to NTP (UCHAR) time         */
4318 /*    which_stamp                     Which time stamp to convert         */
4319 /*                                                                        */
4320 /*  OUTPUT                                                                */
4321 /*                                                                        */
4322 /*    NX_SNTP_PARAM_ERROR             Invalid time stamp requested        */
4323 /*    NX_SUCCESS                      Successful completion status        */
4324 /*                                                                        */
4325 /*  CALLS                                                                 */
4326 /*                                                                        */
4327 /*    memset                         Clear specified area of memory       */
4328 /*                                                                        */
4329 /*  CALLED BY                                                             */
4330 /*                                                                        */
4331 /*    _nx_sntp_client_send_unicast_request                                */
4332 /*                                   Create a time request and transmit it*/
4333 /*                                                                        */
4334 /*  RELEASE HISTORY                                                       */
4335 /*                                                                        */
4336 /*    DATE              NAME                      DESCRIPTION             */
4337 /*                                                                        */
4338 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4339 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4340 /*                                            resulting in version 6.1    */
4341 /*                                                                        */
4342 /**************************************************************************/
_nx_sntp_client_utility_convert_time_to_UCHAR(NX_SNTP_TIME * time_ptr,NX_SNTP_TIME_MESSAGE * time_message_ptr,UINT which_stamp)4343 UINT  _nx_sntp_client_utility_convert_time_to_UCHAR(NX_SNTP_TIME *time_ptr,
4344                                      NX_SNTP_TIME_MESSAGE *time_message_ptr, UINT which_stamp)
4345 {
4346 
4347 ULONG *buffer;
4348 
4349     /* Copy the buffer to the requested time stamp field.  */
4350     switch (which_stamp)
4351     {
4352 
4353         case REFERENCE_TIME:
4354             buffer = time_message_ptr -> reference_clock_update_time_stamp;
4355         break;
4356 
4357         case ORIGINATE_TIME:
4358             buffer = time_message_ptr -> originate_time_stamp;
4359         break;
4360 
4361         case RECEIVE_TIME:
4362             buffer = time_message_ptr -> receive_time_stamp;
4363         break;
4364 
4365         case TRANSMIT_TIME:
4366             buffer = time_message_ptr -> transmit_time_stamp;
4367         break;
4368 
4369         default:
4370             /* Invalid time stamp. Return as error.  */
4371             return NX_SNTP_PARAM_ERROR;
4372     }
4373 
4374     /* Copy NX_SNTP_TIME seconds and fraction to the buffer.  */
4375     *(buffer) = time_ptr -> seconds;
4376     *(buffer + 1) = time_ptr -> fraction;
4377 
4378     /* Return successful completion.  */
4379     return NX_SUCCESS;
4380 }
4381 
4382 /* The conventional civil timescale used in most parts of the world is based on Coordinated Universal Time (UTC),
4383    which replaced Greenwich Mean Time (GMT) many years ago. UTC is based on International Atomic Time (TAI),
4384    which is derived from hundreds of cesium oscillators in the national standards laboratories of many regions.
4385    Deviations of UTC from TAI are implemented in the form of leap seconds, which occur at intervals from a
4386    few months to serveral years. */
4387 
4388 
4389 /**************************************************************************/
4390 /*                                                                        */
4391 /*  FUNCTION                                               RELEASE        */
4392 /*                                                                        */
4393 /*    _nx_sntp_client_utility_convert_seconds_to_date     PORTABLE C      */
4394 /*                                                           6.1          */
4395 /*  AUTHOR                                                                */
4396 /*                                                                        */
4397 /*    Yuxin Zhou, Microsoft Corporation                                   */
4398 /*                                                                        */
4399 /*  DESCRIPTION                                                           */
4400 /*                                                                        */
4401 /*  This function computes the month, day, and time in an NTP time based  */
4402 /*  on the known number of seconds at 1/1/1999 since 1/1/1900 (the NTP    */
4403 /*  time epoch) and the current NTP time.  The caller must indicated the  */
4404 /*  year of the NTP time to convert to simplify the computation.  The data*/
4405 /*  is written to an NX_SNTP_DATE_TIME object from which the call can     */
4406 /*  extract date and time data, or call the NetX SNTP API to display the  */
4407 /*  data/time string.                                                     */
4408 /*                                                                        */
4409 /*   INPUT                                                                */
4410 /*                                                                        */
4411 /*    current_NTP_time_ptr              Pointer to NTP time               */
4412 /*    current_year                      Year in the NTP time data         */
4413 /*    current_date_time_ptr             Pointer to date time object       */
4414 /*                                                                        */
4415 /*  OUTPUT                                                                */
4416 /*                                                                        */
4417 /*    NX_SUCCESS                         Successful completion status     */
4418 /*    NX_SNTP_ERROR_CONVERTING_DATETIME  Internal error converting time   */
4419 /*    NX_SNTP_UNABLE_TO_CONVERT_DATETIME Insufficient data for converting */
4420 /*                                                                        */
4421 /*  CALLS                                                                 */
4422 /*                                                                        */
4423 /*    _nx_sntp_client_utility_convert_fraction_to_msecs                   */
4424 /*                                      Converts the 32 bit fraction field*/
4425 /*                                      in an NTP time to milliseconds    */
4426 /*                                                                        */
4427 /*  CALLED BY                                                             */
4428 /*                                                                        */
4429 /*    Application                                                         */
4430 /*                                                                        */
4431 /*  RELEASE HISTORY                                                       */
4432 /*                                                                        */
4433 /*    DATE              NAME                      DESCRIPTION             */
4434 /*                                                                        */
4435 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4436 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4437 /*                                            fixed leap year calculation,*/
4438 /*                                            resulting in version 6.1    */
4439 /*                                                                        */
4440 /**************************************************************************/
_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)4441 UINT _nx_sntp_client_utility_convert_seconds_to_date(NX_SNTP_TIME *current_NTP_time_ptr, UINT current_year,
4442                                                      NX_SNTP_DATE_TIME *current_date_time_ptr)
4443 {
4444 
4445     /* Check if there is a base number of seconds set. */
4446 #if (NTP_SECONDS_AT_01011999 == 0)
4447 
4448     /* No, so we cannot convert time into months and years. */
4449     return NX_SNTP_UNABLE_TO_CONVERT_DATETIME;
4450 #else
4451 
4452 UINT seconds_diff;
4453 UINT years_diff;
4454 UINT leapyears_diff;
4455 UINT leaps;
4456 UINT seconds_of_year;
4457 UINT seconds_into_currentyear;
4458 UINT seconds_into_currentmonth;
4459 UINT seconds_into_currentday;
4460 UINT seconds_into_currenthour;
4461 
4462     memset(current_date_time_ptr, 0, sizeof(NX_SNTP_DATE_TIME));
4463 
4464     do
4465     {
4466 
4467         current_date_time_ptr -> year = current_year;
4468 
4469         seconds_diff = current_NTP_time_ptr -> seconds - NTP_SECONDS_AT_01011999;
4470 
4471         years_diff = current_year - 1999;
4472 
4473         /* Figure out number of leap years since 1999 not including the current year. */
4474         leapyears_diff = (current_year - 1 - 1996) >> 2;
4475 
4476         /* Determine if this is a leap year. */
4477         leaps = (current_year - 1996) & 3;
4478 
4479         /* Check if this is a leap year. */
4480         if (leaps == 0 )
4481         {
4482             /* It is! */
4483             current_date_time_ptr -> leap_year = NX_TRUE;
4484             seconds_of_year = SECONDS_PER_LEAPYEAR;
4485         }
4486         else
4487         {
4488 
4489             /* Not a leap year. Clear the leap year flag. */
4490             current_date_time_ptr -> leap_year = NX_FALSE;
4491             seconds_of_year = SECONDS_PER_NONLEAPYEAR;
4492         }
4493 
4494         /* Compute number of seconds into the current year e.g. as of 01/01 at midnite by subtracting
4495            the total number of seconds since 1/1/1999 up to the end of the previous year.  Remember to compute
4496            the leapyear seconds at a different rate. */
4497         seconds_into_currentyear = seconds_diff - ((years_diff - leapyears_diff) * SECONDS_PER_NONLEAPYEAR)
4498                                                 - (leapyears_diff * SECONDS_PER_LEAPYEAR);
4499 
4500         current_year++;
4501 
4502     }while(seconds_into_currentyear > seconds_of_year);
4503 
4504     /* Initialize month to January till we find out what the month is. */
4505     current_date_time_ptr -> month = JANUARY;
4506 
4507     while (1)
4508     {
4509 
4510         /* Does the number of seconds goes past January? */
4511         if (seconds_into_currentyear >= SEC_IN_JAN)
4512         {
4513 
4514             /* Yes, reset month to Feb and subtract seconds in January. */
4515             current_date_time_ptr -> month = FEBRUARY;
4516             seconds_into_currentyear -= SEC_IN_JAN;
4517         }
4518         /* No, we're done going month to month. */
4519         else break;
4520 
4521         /* Handle February differently because it is a leap month. */
4522         if (current_date_time_ptr -> leap_year)
4523         {
4524 
4525             /* This is a leap year so Feb has 29 days. */
4526             if (seconds_into_currentyear >= SEC_IN_LEAPFEB)
4527             {
4528                 current_date_time_ptr -> month = MARCH;
4529                 seconds_into_currentyear -= SEC_IN_LEAPFEB;
4530             }
4531             else break;
4532 
4533         }
4534         else
4535         {
4536             /* Not a leap year, Feb has the usual 28 days. */
4537             if (seconds_into_currentyear >= SEC_IN_NONLEAPFEB)
4538             {
4539                 current_date_time_ptr -> month = MARCH;
4540                 seconds_into_currentyear -= SEC_IN_NONLEAPFEB;
4541             }
4542             else break;
4543 
4544         }
4545 
4546         /* Repeat for each month for the rest of the year. */
4547 
4548         if (seconds_into_currentyear >= SEC_IN_MAR)
4549         {
4550             current_date_time_ptr -> month = APRIL;
4551             seconds_into_currentyear -= SEC_IN_MAR;
4552         }
4553         else break;
4554 
4555         if (seconds_into_currentyear >= SEC_IN_APR)
4556         {
4557             current_date_time_ptr -> month = MAY;
4558             seconds_into_currentyear -= SEC_IN_APR;
4559         }
4560         else break;
4561 
4562         if (seconds_into_currentyear >= SEC_IN_MAY)
4563         {
4564             current_date_time_ptr -> month = JUNE;
4565             seconds_into_currentyear -= SEC_IN_MAY;
4566         }
4567         else break;
4568 
4569         if (seconds_into_currentyear >= SEC_IN_JUN)
4570         {
4571             current_date_time_ptr -> month = JULY;
4572             seconds_into_currentyear -= SEC_IN_JUN;
4573         }
4574         else break;
4575 
4576         if (seconds_into_currentyear >= SEC_IN_JUL)
4577         {
4578             current_date_time_ptr -> month = AUGUST;
4579             seconds_into_currentyear -= SEC_IN_JUL;
4580         }
4581         else break;
4582 
4583         if (seconds_into_currentyear >= SEC_IN_AUG)
4584         {
4585             current_date_time_ptr -> month = SEPTEMBER;
4586             seconds_into_currentyear -= SEC_IN_AUG;
4587         }
4588         else break;
4589 
4590         if (seconds_into_currentyear >= SEC_IN_SEP)
4591         {
4592             current_date_time_ptr -> month = OCTOBER;
4593             seconds_into_currentyear -= SEC_IN_SEP;
4594         }
4595         else break;
4596 
4597         if (seconds_into_currentyear >= SEC_IN_OCT)
4598         {
4599             current_date_time_ptr -> month = NOVEMBER;
4600             seconds_into_currentyear -= SEC_IN_OCT;
4601         }
4602         else break;
4603 
4604         if (seconds_into_currentyear >= SEC_IN_NOV)
4605         {
4606             current_date_time_ptr -> month = DECEMBER;
4607             seconds_into_currentyear -= SEC_IN_NOV;
4608         }
4609         else break;
4610 
4611         /* We should not have more than the seconds in december or there is an error. */
4612         if (seconds_into_currentyear > SEC_IN_DEC)
4613         {
4614 
4615             /* Return the error status. */
4616             return NX_SNTP_ERROR_CONVERTING_DATETIME;
4617         }
4618         else break;
4619     }
4620 
4621     /* Time is now in the current month. */
4622     seconds_into_currentmonth = seconds_into_currentyear;
4623 
4624     /* Compute how many complete days the time goes into the current month and
4625        add one for the current day. */
4626     current_date_time_ptr -> day = seconds_into_currentmonth/SECONDS_PER_DAY + 1;
4627 
4628     /* Compute the number of seconds into the current day. */
4629     seconds_into_currentday = seconds_into_currentmonth % SECONDS_PER_DAY;
4630 
4631     /* Compute the number of complete hours into the current day we are. */
4632     current_date_time_ptr -> hour = seconds_into_currentday/SECONDS_PER_HOUR;
4633 
4634     /* Compute the number of seconds into the current hour. */
4635     seconds_into_currenthour = seconds_into_currentday % SECONDS_PER_HOUR;
4636 
4637     /* Break this down into minutes. */
4638     current_date_time_ptr -> minute = seconds_into_currenthour/SECONDS_PER_MINUTE;
4639 
4640     /* Finally the remainder is the seconds. */
4641     current_date_time_ptr -> second = seconds_into_currenthour % SECONDS_PER_MINUTE;
4642 
4643     /* Convert time fraction field into milliseconds.  */
4644     _nx_sntp_client_utility_convert_fraction_to_msecs((ULONG *)(&(current_date_time_ptr -> millisecond)), current_NTP_time_ptr);
4645 
4646     return NX_SUCCESS;
4647 #endif
4648 }
4649 
4650 
4651 /**************************************************************************/
4652 /*                                                                        */
4653 /*  FUNCTION                                               RELEASE        */
4654 /*                                                                        */
4655 /*    _nxe_sntp_client_utility_display_date_time          PORTABLE C      */
4656 /*                                                           6.1          */
4657 /*  AUTHOR                                                                */
4658 /*                                                                        */
4659 /*    Yuxin Zhou, Microsoft Corporation                                   */
4660 /*                                                                        */
4661 /*  DESCRIPTION                                                           */
4662 /*                                                                        */
4663 /*  This function performs error checking services on the display date    */
4664 /*  time service.                                                         */
4665 /*                                                                        */
4666 /*   INPUT                                                                */
4667 /*                                                                        */
4668 /*    client_ptr                        Pointer to SNTP Client            */
4669 /*    buffer                            Pointer to string buffer          */
4670 /*    length                            Size of the string buffer         */
4671 /*                                                                        */
4672 /*  OUTPUT                                                                */
4673 /*                                                                        */
4674 /*    NX_PTR_ERROR                     Invalid pointer input              */
4675 /*    NX_SNTP_PARAM_ERROR              Invalid non pointer input          */
4676 /*    status                           Actual completion status           */
4677 /*                                                                        */
4678 /*  CALLS                                                                 */
4679 /*                                                                        */
4680 /*    _nx_sntp_client_utility_display_date_time                           */
4681 /*                                     Actual display date/time service   */
4682 /*                                                                        */
4683 /*  CALLED BY                                                             */
4684 /*                                                                        */
4685 /*    Application                                                         */
4686 /*                                                                        */
4687 /*  RELEASE HISTORY                                                       */
4688 /*                                                                        */
4689 /*    DATE              NAME                      DESCRIPTION             */
4690 /*                                                                        */
4691 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4692 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4693 /*                                            resulting in version 6.1    */
4694 /*                                                                        */
4695 /**************************************************************************/
_nxe_sntp_client_utility_display_date_time(NX_SNTP_CLIENT * client_ptr,CHAR * buffer,UINT length)4696 UINT _nxe_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length)
4697 {
4698 
4699 UINT status;
4700 
4701 
4702     /* Check for invalid pointer input.  */
4703     if ((client_ptr == NX_NULL) || (buffer == NX_NULL))
4704     {
4705 
4706         /* Return pointer error.  */
4707         return NX_PTR_ERROR;
4708     }
4709 
4710     /* Check for invalid parameter input.  */
4711     if (length == 0)
4712     {
4713 
4714         /* Return parameter error.  */
4715         return NX_SNTP_PARAM_ERROR;
4716     }
4717 
4718     /* Call the actual display time service.  */
4719     status = _nx_sntp_client_utility_display_date_time(client_ptr, buffer, length);
4720 
4721     /* Return completion status.  */
4722     return status;
4723 }
4724 
4725 
4726 
4727 /**************************************************************************/
4728 /*                                                                        */
4729 /*  FUNCTION                                               RELEASE        */
4730 /*                                                                        */
4731 /*    _nxe_sntp_client_request_unicast_time               PORTABLE C      */
4732 /*                                                           6.1          */
4733 /*  AUTHOR                                                                */
4734 /*                                                                        */
4735 /*    Yuxin Zhou, Microsoft Corporation                                   */
4736 /*                                                                        */
4737 /*  DESCRIPTION                                                           */
4738 /*                                                                        */
4739 /*    This function performs error checking for the service that          */
4740 /*    forwards a unicast request from the SNTP Client application.        */
4741 /*                                                                        */
4742 /*   INPUT                                                                */
4743 /*                                                                        */
4744 /*    client_ptr                       Pointer to Client struct           */
4745 /*    wait_option                      Time to wait for response (ticks)  */
4746 /*                                                                        */
4747 /*  OUTPUT                                                                */
4748 /*                                                                        */
4749 /*    NX_PTR_ERROR                      Invalid pointer input             */
4750 /*    status                            Actual completion status          */
4751 /*                                                                        */
4752 /*  CALLED BY                                                             */
4753 /*                                                                        */
4754 /*    Application Code                                                    */
4755 /*                                                                        */
4756 /*  RELEASE HISTORY                                                       */
4757 /*                                                                        */
4758 /*    DATE              NAME                      DESCRIPTION             */
4759 /*                                                                        */
4760 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4761 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4762 /*                                            resulting in version 6.1    */
4763 /*                                                                        */
4764 /**************************************************************************/
_nxe_sntp_client_request_unicast_time(NX_SNTP_CLIENT * client_ptr,UINT wait_option)4765 UINT _nxe_sntp_client_request_unicast_time(NX_SNTP_CLIENT *client_ptr, UINT wait_option)
4766 {
4767 
4768 UINT status;
4769 
4770     /* Check for invalid pointer input. */
4771     if (client_ptr == NX_NULL)
4772     {
4773         return NX_PTR_ERROR;
4774     }
4775 
4776     status = _nx_sntp_client_request_unicast_time(client_ptr, wait_option);
4777 
4778     return status;
4779 }
4780 
4781 
4782 /**************************************************************************/
4783 /*                                                                        */
4784 /*  FUNCTION                                               RELEASE        */
4785 /*                                                                        */
4786 /*    _nx_sntp_client_request_unicast_time                PORTABLE C      */
4787 /*                                                           6.1          */
4788 /*  AUTHOR                                                                */
4789 /*                                                                        */
4790 /*    Yuxin Zhou, Microsoft Corporation                                   */
4791 /*                                                                        */
4792 /*  DESCRIPTION                                                           */
4793 /*                                                                        */
4794 /*    This function sends a unicast request regardless if the SNTP Client */
4795 /*    is configured for unicast or broadcast mode. After sending the      */
4796 /*    request, the function waits for the specified time for a response.  */
4797 /*                                                                        */
4798 /*    If received, the SNTP Server response is processed as it normally is*/
4799 /*    for valid SNTP data, and applied to the SNTP Client's notion of time*/
4800 /*    "local time".                                                       */
4801 /*                                                                        */
4802 /*    This will not interfere with subsequent unicast requests in unicast */
4803 /*    mode, or the processing of periodic updates in broadcast mode.      */
4804 /*                                                                        */
4805 /*   INPUT                                                                */
4806 /*                                                                        */
4807 /*    client_ptr                       Pointer to Client struct           */
4808 /*    wait_option                      Time to wait for response (ticks)  */
4809 /*                                                                        */
4810 /*  OUTPUT                                                                */
4811 /*                                                                        */
4812 /*    NX_PTR_ERROR                      Invalid pointer input             */
4813 /*    status                            Actual completion status          */
4814 /*                                                                        */
4815 /*  CALLED BY                                                             */
4816 /*                                                                        */
4817 /*    Application Code                                                    */
4818 /*                                                                        */
4819 /*  RELEASE HISTORY                                                       */
4820 /*                                                                        */
4821 /*    DATE              NAME                      DESCRIPTION             */
4822 /*                                                                        */
4823 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4824 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4825 /*                                            resulting in version 6.1    */
4826 /*                                                                        */
4827 /**************************************************************************/
_nx_sntp_client_request_unicast_time(NX_SNTP_CLIENT * client_ptr,UINT wait_option)4828 UINT _nx_sntp_client_request_unicast_time(NX_SNTP_CLIENT *client_ptr, UINT wait_option)
4829 {
4830 
4831 UINT status;
4832 
4833 
4834     /* Make sure the client is started. */
4835     if (!client_ptr -> nx_sntp_client_started)
4836     {
4837         return NX_SNTP_CLIENT_NOT_STARTED;
4838     }
4839 
4840     /* Create and send a unicast request.  */
4841     status = _nx_sntp_client_send_unicast_request(client_ptr);
4842 
4843     if (status != NX_SUCCESS)
4844     {
4845         return status;
4846     }
4847 
4848     /* Wait to receive a response. */
4849     status = _nx_sntp_client_receive_time_update(client_ptr, wait_option);
4850 
4851     /* If we got a valid SNTP packet, process the data. */
4852     if (status == NX_SUCCESS)
4853     {
4854 
4855         /* Process the server update packet and apply to local time if valid.  */
4856         status =  _nx_sntp_client_process_update_packet(client_ptr);
4857     }
4858 
4859     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
4860     /* Return completion status.  */
4861     return status;
4862 }
4863 
4864 /**************************************************************************/
4865 /*                                                                        */
4866 /*  FUNCTION                                               RELEASE        */
4867 /*                                                                        */
4868 /*    _nx_sntp_client_utility_display_date_time           PORTABLE C      */
4869 /*                                                           6.2.0        */
4870 /*  AUTHOR                                                                */
4871 /*                                                                        */
4872 /*    Yuxin Zhou, Microsoft Corporation                                   */
4873 /*                                                                        */
4874 /*  DESCRIPTION                                                           */
4875 /*                                                                        */
4876 /*  This function converts an NTP time data into a month-date-year time,  */
4877 /*  including seconds and second fraction string. It is intended as a     */
4878 /*  human readable representation of NTP time.  The caller must supply a  */
4879 /*  pointer to a buffer large enough (40 chars is enough) to hold the     */
4880 /*  string and define the NX_SNTP_CURRENT_YEAR parameter, usually as the  */
4881 /*  current year.                                                         */
4882 /*                                                                        */
4883 /*   INPUT                                                                */
4884 /*                                                                        */
4885 /*    client_ptr                        Pointer to SNTP Client            */
4886 /*    buffer                            Pointer to string buffer          */
4887 /*    length                            Size of the string buffer         */
4888 /*                                                                        */
4889 /*  OUTPUT                                                                */
4890 /*                                                                        */
4891 /*    NX_SUCCESS                        Successful completion status      */
4892 /*    NX_SNTP_INVALID_DATETIME_BUFFER   Buffer not large enough           */
4893 /*    NX_SNTP_ERROR_CONVERTING_DATETIME Internal error converting NTP time*/
4894 /*    status                            Convert seconds completion status */
4895 /*                                                                        */
4896 /*  CALLS                                                                 */
4897 /*    _nx_sntp_client_utility_convert_seconds_to_date                     */
4898 /*                                      Converts seconds to year, month   */
4899 /*    _nx_utility_uint_to_string        Converts number to ascii text     */
4900 /*                                                                        */
4901 /*  CALLED BY                                                             */
4902 /*                                                                        */
4903 /*    Application                                                         */
4904 /*                                                                        */
4905 /*  RELEASE HISTORY                                                       */
4906 /*                                                                        */
4907 /*    DATE              NAME                      DESCRIPTION             */
4908 /*                                                                        */
4909 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4910 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4911 /*                                            resulting in version 6.1    */
4912 /*  08-02-2021     Yuxin Zhou               Modified comment(s),          */
4913 /*                                            improved the logic of       */
4914 /*                                            converting number to string,*/
4915 /*                                            resulting in version 6.1.8  */
4916 /*  10-31-2022     Yuxin Zhou               Modified comment(s), fixed    */
4917 /*                                            the typo of August string,  */
4918 /*                                            resulting in version 6.2.0  */
4919 /*                                                                        */
4920 /**************************************************************************/
_nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT * client_ptr,CHAR * buffer,UINT length)4921 UINT _nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length)
4922 {
4923 
4924 UINT                status;
4925 UINT                offset;
4926 UINT                return_length;
4927 NX_SNTP_DATE_TIME   DisplayTime;
4928 const CHAR         *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
4929                                   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
4930 
4931 
4932 #ifndef  NX_SNTP_CURRENT_YEAR
4933     return NX_SNTP_ERROR_CONVERTING_DATETIME;
4934 #else
4935 
4936     /* Verify the client has set a local time. */
4937     if (client_ptr -> nx_sntp_client_local_ntp_time.seconds == 0)
4938     {
4939        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4940     }
4941 
4942     status = _nx_sntp_client_utility_convert_seconds_to_date(&(client_ptr -> nx_sntp_client_local_ntp_time), NX_SNTP_CURRENT_YEAR, &DisplayTime);
4943     if (status != NX_SUCCESS)
4944     {
4945         return status;
4946     }
4947 
4948     /* Check if we have a long enough buffer. */
4949     if (length < 5)
4950     {
4951 
4952         /* Return the error status. */
4953         return NX_SNTP_INVALID_DATETIME_BUFFER;
4954     }
4955 
4956     /* Decrease length for terminal zero. */
4957     length--;
4958 
4959     /* Substitute numeric month to name of the month. */
4960     if ((DisplayTime.month < JANUARY) || (DisplayTime.month > DECEMBER))
4961     {
4962        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4963     }
4964     buffer[0] = months[DisplayTime.month - JANUARY][0];
4965     buffer[1] = months[DisplayTime.month - JANUARY][1];
4966     buffer[2] = months[DisplayTime.month - JANUARY][2];
4967     buffer[3] = ' ';
4968     offset = 4;
4969 
4970     /* Write in the rest of the data as numeric from the Date Time objext. */
4971     return_length = _nx_utility_uint_to_string(DisplayTime.day, 10, &buffer[offset], length - offset);
4972     offset += return_length;
4973     if ((return_length == 0) || ((length - offset) < 2))
4974     {
4975        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4976     }
4977     buffer[offset++] = ',';
4978     buffer[offset++] = ' ';
4979     return_length = _nx_utility_uint_to_string(DisplayTime.year, 10, &buffer[offset], length - offset);
4980     offset += return_length;
4981     if ((return_length == 0) || ((length - offset) < 1))
4982     {
4983        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4984     }
4985     buffer[offset++] = ' ';
4986     return_length = _nx_utility_uint_to_string(DisplayTime.hour, 10, &buffer[offset], length - offset);
4987     offset += return_length;
4988     if ((return_length == 0) || ((length - offset) < 1))
4989     {
4990        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4991     }
4992     buffer[offset++] = ':';
4993     return_length = _nx_utility_uint_to_string(DisplayTime.minute, 10, &buffer[offset], length - offset);
4994     offset += return_length;
4995     if ((return_length == 0) || ((length - offset) < 1))
4996     {
4997        return NX_SNTP_ERROR_CONVERTING_DATETIME;
4998     }
4999     buffer[offset++] = ':';
5000     return_length = _nx_utility_uint_to_string(DisplayTime.second, 10, &buffer[offset], length - offset);
5001     offset += return_length;
5002     if ((return_length == 0) || ((length - offset) < 1))
5003     {
5004        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5005     }
5006     buffer[offset++] = '.';
5007     return_length = _nx_utility_uint_to_string(DisplayTime.millisecond, 10, &buffer[offset], length - offset);
5008     offset += return_length;
5009     if ((return_length == 0) || ((length - offset) < 5))
5010     {
5011        return NX_SNTP_ERROR_CONVERTING_DATETIME;
5012     }
5013     buffer[offset++] = ' ';
5014     buffer[offset++] = 'U';
5015     buffer[offset++] = 'T';
5016     buffer[offset++] = 'C';
5017     buffer[offset++] = ' ';
5018     buffer[offset] = '\0';
5019 
5020 #endif
5021 
5022     return NX_SUCCESS;
5023 }
5024 
5025 
5026 /**************************************************************************/
5027 /*                                                                        */
5028 /*  FUNCTION                                               RELEASE        */
5029 /*                                                                        */
5030 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time       PORTABLE C      */
5031 /*                                                           6.1          */
5032 /*  AUTHOR                                                                */
5033 /*                                                                        */
5034 /*    Yuxin Zhou, Microsoft Corporation                                   */
5035 /*                                                                        */
5036 /*  DESCRIPTION                                                           */
5037 /*                                                                        */
5038 /*   This function adds msecs (not necessarily a positive value and not   */
5039 /*   limited to less than a second) to an NTP time value. Msecs cannot be */
5040 /*   added directly to the fraction field in the NTP time field because   */
5041 /*   this field is represented in fixed point notation.  Arithmetic       */
5042 /*   overflow and loss of sign errors as a result of adding numbers are   */
5043 /*   handled as errors.                                                   */
5044 /*                                                                        */
5045 /*   INPUT                                                                */
5046 /*                                                                        */
5047 /*    timeA_ptr                        Pointer to NTP time operand        */
5048 /*    msecs_to_add                     Time (msecs) to add                */
5049 /*                                                                        */
5050 /*  OUTPUT                                                                */
5051 /*                                                                        */
5052 /*    NX_SUCCESS                       Successful completion status       */
5053 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result adding numbers     */
5054 /*    NX_SNTP_INVALID_TIME             An invalid result (e.g. negative   */
5055 /*                                        time) from adding numbers       */
5056 /*    status                           Actual completion status           */
5057 /*                                                                        */
5058 /*  CALLS                                                                 */
5059 /*                                                                        */
5060 /*    None                                                                */
5061 /*                                                                        */
5062 /*  CALLED BY                                                             */
5063 /*                                                                        */
5064 /*   _nx_sntp_client_process_time_data  Apply server time to local time   */
5065 /*                                                                        */
5066 /*  RELEASE HISTORY                                                       */
5067 /*                                                                        */
5068 /*    DATE              NAME                      DESCRIPTION             */
5069 /*                                                                        */
5070 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5071 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5072 /*                                            resulting in version 6.1    */
5073 /*                                                                        */
5074 /**************************************************************************/
5075 
_nx_sntp_client_utility_add_msecs_to_ntp_time(NX_SNTP_TIME * timeA_ptr,LONG msecs_to_add)5076 UINT  _nx_sntp_client_utility_add_msecs_to_ntp_time(NX_SNTP_TIME *timeA_ptr, LONG msecs_to_add)
5077 {
5078 
5079 UINT  status;
5080 ULONG timeA_usec;
5081 LONG  seconds;
5082 LONG  usecs;
5083 
5084 
5085     /* Separate msecs_to_add into seconds and milliseconds.  */
5086     seconds = msecs_to_add / 1000;
5087     usecs = (msecs_to_add % 1000) * 1000;
5088 
5089     /* Are we adding a positive number?  */
5090     if (msecs_to_add > 0)
5091     {
5092         /* Yes; check for overflow before trying to add seconds to the TimeA operand.  */
5093         status = _nx_sntp_client_utility_addition_overflow_check(timeA_ptr -> seconds, (ULONG)seconds);
5094 
5095         /* Check for error (overflow).  */
5096         if (status != NX_SUCCESS)
5097         {
5098 
5099             /* Return the error condition.  */
5100             return status;
5101         }
5102     }
5103     /* Check if a negative number larger than the timeA operand is being added (creates negative time!)*/
5104     else if (timeA_ptr -> seconds < (ULONG)abs(seconds))
5105     {
5106 
5107         /* Yes; return the error condition.  */
5108         return NX_SNTP_INVALID_TIME;
5109     }
5110 
5111     /* Ok to add seconds to the NTP time seconds.  */
5112     timeA_ptr -> seconds += (ULONG)seconds;
5113 
5114     /* Next get the usecs from the timeA operand (always positive and < 1000000).  */
5115     _nx_sntp_client_utility_fraction_to_usecs(timeA_ptr -> fraction, &timeA_usec);
5116 
5117     /* In case usecs is < 0, we might have to perform a carry.  */
5118     if ((usecs + (LONG)timeA_usec) < 0)
5119     {
5120         /* Perform a carry by subtracting a second from timeA seconds...*/
5121         timeA_ptr -> seconds--;
5122 
5123         /* And adding it to the usecs of timeA.  */
5124         timeA_usec += 1000000;
5125     }
5126 
5127     /* OK to add the usecs up.  */
5128     usecs += (LONG)timeA_usec;
5129 
5130     /* Check for a positive carry over into seconds.  */
5131     if (usecs >= 1000000)
5132     {
5133         /* Yes there's a carry; check for possibility of overflow
5134            before adding carry (unlikely for another 30 years).  */
5135         if (timeA_ptr -> seconds == 0xFFFFFFFF)
5136         {
5137 
5138             return NX_SNTP_OVERFLOW_ERROR;
5139         }
5140 
5141         /* OK to increment the seconds.  */
5142         timeA_ptr -> seconds++;
5143 
5144         /* Set milliseconds to remainder.  */
5145         usecs = usecs % 1000000;
5146     }
5147 
5148     /* Convert usecs to the fixed point notation fraction and store in TimeA fraction.  */
5149     status = _nx_sntp_client_utility_usecs_to_fraction((ULONG)usecs, &(timeA_ptr ->fraction));
5150 
5151     /* Return completion status.  */
5152     return status;
5153 }
5154 
5155 
5156 /**************************************************************************/
5157 /*                                                                        */
5158 /*  FUNCTION                                               RELEASE        */
5159 /*                                                                        */
5160 /*    _nxe_sntp_client_receiving_updates                  PORTABLE C      */
5161 /*                                                           6.1          */
5162 /*  AUTHOR                                                                */
5163 /*                                                                        */
5164 /*    Yuxin Zhou, Microsoft Corporation                                   */
5165 /*                                                                        */
5166 /*  DESCRIPTION                                                           */
5167 /*                                                                        */
5168 /*   This function performs error checking for the get SNTP get receive   */
5169 /*   status service.                                                      */
5170 /*                                                                        */
5171 /*   INPUT                                                                */
5172 /*                                                                        */
5173 /*    client_ptr                       Pointer to SNTP client instance    */
5174 /*    receive_status                   Pointer to server status           */
5175 /*                                                                        */
5176 /*  OUTPUT                                                                */
5177 /*                                                                        */
5178 /*    NX_PTR_ERROR                     Invalid input status               */
5179 /*    status                           Actual completion status           */
5180 /*                                                                        */
5181 /*  CALLS                                                                 */
5182 /*                                                                        */
5183 /*    _nx_sntp_client_receiving_updates                                   */
5184 /*                                     Actual get server status service   */
5185 /*                                                                        */
5186 /*  CALLED BY                                                             */
5187 /*                                                                        */
5188 /*    Application Code                                                    */
5189 /*                                                                        */
5190 /*  RELEASE HISTORY                                                       */
5191 /*                                                                        */
5192 /*    DATE              NAME                      DESCRIPTION             */
5193 /*                                                                        */
5194 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5195 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5196 /*                                            resulting in version 6.1    */
5197 /*                                                                        */
5198 /**************************************************************************/
_nxe_sntp_client_receiving_updates(NX_SNTP_CLIENT * client_ptr,UINT * receive_status)5199 UINT _nxe_sntp_client_receiving_updates(NX_SNTP_CLIENT *client_ptr, UINT *receive_status)
5200 {
5201 
5202 UINT status;
5203 
5204     /* Check for the validity of input parameter.  */
5205     if ((client_ptr == NX_NULL) || (receive_status == NX_NULL))
5206     {
5207 
5208         /* Return error status.  */
5209         return(NX_PTR_ERROR);
5210     }
5211 
5212     status = _nx_sntp_client_receiving_updates(client_ptr, receive_status);
5213 
5214     return status;
5215 }
5216 
5217 /**************************************************************************/
5218 /*                                                                        */
5219 /*  FUNCTION                                               RELEASE        */
5220 /*                                                                        */
5221 /*    _nx_sntp_client_receiving_updates                   PORTABLE C      */
5222 /*                                                           6.1          */
5223 /*  AUTHOR                                                                */
5224 /*                                                                        */
5225 /*    Yuxin Zhou, Microsoft Corporation                                   */
5226 /*                                                                        */
5227 /*  DESCRIPTION                                                           */
5228 /*                                                                        */
5229 /*   This function returns the status of the Client SNTP server. If the   */
5230 /*   client has not received a valid update within the NX_SNTP_CLIENT_MAX_*/
5231 /*   _TIME_LAPSE interval or if the number of invalid updates received by */
5232 /*   the client exceeds the NX_SNTP_CLIENT_INVALID_UPDATE_LIMIT limit,    */
5233 /*   the status is set to NX_FALSE.  If the Client has not yet received   */
5234 /*   its first valid update from the current SNTP server, status is set to*/
5235 /*   false.                                                               */
5236 /*                                                                        */
5237 /*   INPUT                                                                */
5238 /*                                                                        */
5239 /*    client_ptr                       Pointer to SNTP client instance    */
5240 /*    receive_status                   Pointer to receive_status          */
5241 /*                                     NX_FALSE: not receiving updates    */
5242 /*                                     NX_TRUE: receiving valid updates   */
5243 /*                                                                        */
5244 /*  OUTPUT                                                                */
5245 /*                                                                        */
5246 /*    NX_PTR_ERROR                     Invalid input status               */
5247 /*    status                           Actual completion status           */
5248 /*                                                                        */
5249 /*  CALLS                                                                 */
5250 /*                                                                        */
5251 /*    tx_mutex_get                     Get the SNTP mutex                 */
5252 /*    tx_mutex_put                     Release the SNTP mutex             */
5253 /*                                                                        */
5254 /*  CALLED BY                                                             */
5255 /*                                                                        */
5256 /*    Application Code                                                    */
5257 /*                                                                        */
5258 /*  RELEASE HISTORY                                                       */
5259 /*                                                                        */
5260 /*    DATE              NAME                      DESCRIPTION             */
5261 /*                                                                        */
5262 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5263 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5264 /*                                            resulting in version 6.1    */
5265 /*                                                                        */
5266 /**************************************************************************/
_nx_sntp_client_receiving_updates(NX_SNTP_CLIENT * client_ptr,UINT * receive_status)5267 UINT _nx_sntp_client_receiving_updates(NX_SNTP_CLIENT *client_ptr, UINT *receive_status)
5268 {
5269 
5270 
5271     /* Get the SNTP mutex.  */
5272     tx_mutex_get(&(client_ptr -> nx_sntp_client_mutex), TX_WAIT_FOREVER);
5273 
5274     /* Verify the client's SNTP server is valid, and the Client has received at least one valid udpate from it. */
5275     *receive_status = ((client_ptr -> nx_sntp_valid_server_status == NX_TRUE) && (client_ptr -> nx_sntp_client_first_update_pending == NX_FALSE));
5276 
5277     /* Release the SNTP mutex.  */
5278     tx_mutex_put(&(client_ptr -> nx_sntp_client_mutex));
5279 
5280     /* Return completion status.  */
5281     return(NX_SUCCESS);
5282 
5283 }
5284 
5285 
5286 /**************************************************************************/
5287 /*                                                                        */
5288 /*  FUNCTION                                               RELEASE        */
5289 /*                                                                        */
5290 /*    _nxe_sntp_client_set_local_time                     PORTABLE C      */
5291 /*                                                           6.1          */
5292 /*  AUTHOR                                                                */
5293 /*                                                                        */
5294 /*    Yuxin Zhou, Microsoft Corporation                                   */
5295 /*                                                                        */
5296 /*  DESCRIPTION                                                           */
5297 /*                                                                        */
5298 /*   This function performs error checking for the set client local time  */
5299 /*   service.                                                             */
5300 /*                                                                        */
5301 /*   INPUT                                                                */
5302 /*                                                                        */
5303 /*    client_ptr                       Pointer to SNTP Client             */
5304 /*    seconds                          Local time seconds component       */
5305 /*    fraction                         Local time fraction component      */
5306 /*                                                                        */
5307 /*  OUTPUT                                                                */
5308 /*                                                                        */
5309 /*    status                           Actual completion status           */
5310 /*    NX_PTR_ERROR                     Invalid pointer input              */
5311 /*                                                                        */
5312 /*  CALLS                                                                 */
5313 /*                                                                        */
5314 /*    _nx_sntp_client_set_local_time  Actual set client local time service*/
5315 /*                                                                        */
5316 /*  CALLED BY                                                             */
5317 /*                                                                        */
5318 /*    Application Code                                                    */
5319 /*                                                                        */
5320 /*  RELEASE HISTORY                                                       */
5321 /*                                                                        */
5322 /*    DATE              NAME                      DESCRIPTION             */
5323 /*                                                                        */
5324 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5325 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5326 /*                                            resulting in version 6.1    */
5327 /*                                                                        */
5328 /**************************************************************************/
_nxe_sntp_client_set_local_time(NX_SNTP_CLIENT * client_ptr,ULONG seconds,ULONG fraction)5329 UINT  _nxe_sntp_client_set_local_time(NX_SNTP_CLIENT *client_ptr, ULONG seconds, ULONG fraction)
5330 {
5331 
5332 UINT status;
5333 
5334 
5335     /* Check for invalid input. */
5336    if (client_ptr == NX_NULL)
5337    {
5338        return NX_PTR_ERROR;
5339    }
5340 
5341    /* Call the actual service. */
5342    status = _nx_sntp_client_set_local_time(client_ptr, seconds, fraction);
5343 
5344    /* Return completion status. */
5345    return status;
5346 }
5347 
5348 
5349 /**************************************************************************/
5350 /*                                                                        */
5351 /*  FUNCTION                                               RELEASE        */
5352 /*                                                                        */
5353 /*    _nx_sntp_client_set_local_time                      PORTABLE C      */
5354 /*                                                           6.1          */
5355 /*  AUTHOR                                                                */
5356 /*                                                                        */
5357 /*    Yuxin Zhou, Microsoft Corporation                                   */
5358 /*                                                                        */
5359 /*  DESCRIPTION                                                           */
5360 /*                                                                        */
5361 /*   This function takes the seconds and fraction input from the caller   */
5362 /*   (or more accurately the independent time clock source, and applies it*/
5363 /*   to the SNTP client local time.                                       */
5364 /*                                                                        */
5365 /*   In between SNTP server updates, it is expected that the SNTP Client  */
5366 /*   host application will update the SNTP client local time from the     */
5367 /*   independent time source (e.g. real time clock on board) and then     */
5368 /*   use the SNTP Server time updates to correct the local time for drifts*/
5369 /*   from the correct time.                                               */
5370 /*                                                                        */
5371 /*   It can also set the SNTP Client's base time before starting up the   */
5372 /*   SNTP Client. If the host application cannot obtain a base time, the  */
5373 /*   SNTP Client will take the first SNTP update as the absolute time. If */
5374 /*   the host application does have a real time clock or independent time */
5375 /*   keeper, the SNTP client can set a large enough max adjustment that   */
5376 /*   any Server time udpate will be accepted to the SNTP Client. This     */
5377 /*   leaves the SNTP Client completely dependent on the network and SNTP  */
5378 /*   Server, plus it is vulnerable to rogue SNTP packets.                 */
5379 /*                                                                        */
5380 /*   INPUT                                                                */
5381 /*                                                                        */
5382 /*    client_ptr                       Pointer to SNTP Client             */
5383 /*    seconds                          Local time seconds component       */
5384 /*    fraction                         Local time fraction component      */
5385 /*                                                                        */
5386 /*  OUTPUT                                                                */
5387 /*                                                                        */
5388 /*    NX_SUCCESS                       Successful completion status       */
5389 /*                                                                        */
5390 /*  CALLS                                                                 */
5391 /*                                                                        */
5392 /*    None                                                                */
5393 /*                                                                        */
5394 /*  CALLED BY                                                             */
5395 /*                                                                        */
5396 /*    Application Code                                                    */
5397 /*                                                                        */
5398 /*  RELEASE HISTORY                                                       */
5399 /*                                                                        */
5400 /*    DATE              NAME                      DESCRIPTION             */
5401 /*                                                                        */
5402 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5403 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5404 /*                                            resulting in version 6.1    */
5405 /*                                                                        */
5406 /**************************************************************************/
_nx_sntp_client_set_local_time(NX_SNTP_CLIENT * client_ptr,ULONG seconds,ULONG fraction)5407 UINT  _nx_sntp_client_set_local_time(NX_SNTP_CLIENT *client_ptr, ULONG seconds, ULONG fraction)
5408 {
5409 
5410 
5411     client_ptr -> nx_sntp_client_local_ntp_time.seconds = seconds;
5412     client_ptr -> nx_sntp_client_local_ntp_time.fraction = fraction;
5413     client_ptr -> nx_sntp_client_local_ntp_time_elapsed = 0;
5414 
5415     /* Return completion status.  */
5416     return NX_SUCCESS;
5417 }
5418 
5419 
5420 /**************************************************************************/
5421 /*                                                                        */
5422 /*  FUNCTION                                               RELEASE        */
5423 /*                                                                        */
5424 /*    _nxe_sntp_client_set_time_update_notify             PORTABLE C      */
5425 /*                                                           6.1          */
5426 /*  AUTHOR                                                                */
5427 /*                                                                        */
5428 /*    Yuxin Zhou, Microsoft Corporation                                   */
5429 /*                                                                        */
5430 /*  DESCRIPTION                                                           */
5431 /*                                                                        */
5432 /*    This function performs error checking for the set time update       */
5433 /*    callback service.                                                   */
5434 /*                                                                        */
5435 /*   INPUT                                                                */
5436 /*                                                                        */
5437 /*    client_ptr                        Pointer to Client struct          */
5438 /*    time_update_cb                    Pointer to callback when Client   */
5439 /*                                        receives an SNTP update         */
5440 /*                                                                        */
5441 /*  OUTPUT                                                                */
5442 /*                                                                        */
5443 /*    NX_SUCCESS                        Successful completion status      */
5444 /*    NX_PTR_ERROR                      Invalid pointer input             */
5445 /*                                                                        */
5446 /*  CALLS                                                                 */
5447 /*                                                                        */
5448 /*    _nx_sntp_client_set_time_update_notify                              */
5449 /*                                                                        */
5450 /*  CALLED BY                                                             */
5451 /*                                                                        */
5452 /*    Application                                                         */
5453 /*                                                                        */
5454 /*  RELEASE HISTORY                                                       */
5455 /*                                                                        */
5456 /*    DATE              NAME                      DESCRIPTION             */
5457 /*                                                                        */
5458 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5459 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5460 /*                                            resulting in version 6.1    */
5461 /*                                                                        */
5462 /**************************************************************************/
_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))5463 UINT    _nxe_sntp_client_set_time_update_notify(NX_SNTP_CLIENT *client_ptr,
5464                        VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE *time_update_ptr, NX_SNTP_TIME *local_time))
5465 {
5466 
5467 UINT status;
5468 
5469 
5470     /* Check for valid input. */
5471     if ((client_ptr == NX_NULL) || (time_update_cb == NX_NULL))
5472     {
5473         return NX_PTR_ERROR;
5474     }
5475 
5476     status = _nx_sntp_client_set_time_update_notify(client_ptr, time_update_cb);
5477 
5478     return status;
5479 }
5480 
5481 /**************************************************************************/
5482 /*                                                                        */
5483 /*  FUNCTION                                               RELEASE        */
5484 /*                                                                        */
5485 /*    _nx_sntp_client_set_time_update_notify              PORTABLE C      */
5486 /*                                                           6.1          */
5487 /*  AUTHOR                                                                */
5488 /*                                                                        */
5489 /*    Yuxin Zhou, Microsoft Corporation                                   */
5490 /*                                                                        */
5491 /*  DESCRIPTION                                                           */
5492 /*                                                                        */
5493 /*    This function notifies the application of a valid SNTP time update. */
5494 /*                                                                        */
5495 /*   INPUT                                                                */
5496 /*                                                                        */
5497 /*    client_ptr                        Pointer to Client struct          */
5498 /*    time_update_cb                    Pointer to callback when Client   */
5499 /*                                        receives an SNTP update         */
5500 /*                                                                        */
5501 /*  OUTPUT                                                                */
5502 /*                                                                        */
5503 /*    NX_SUCCESS                        Successful completion status      */
5504 /*                                                                        */
5505 /*  CALLS                                                                 */
5506 /*                                                                        */
5507 /*    None                                                                */
5508 /*                                                                        */
5509 /*  CALLED BY                                                             */
5510 /*                                                                        */
5511 /*    Application                                                         */
5512 /*                                                                        */
5513 /*  RELEASE HISTORY                                                       */
5514 /*                                                                        */
5515 /*    DATE              NAME                      DESCRIPTION             */
5516 /*                                                                        */
5517 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5518 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5519 /*                                            resulting in version 6.1    */
5520 /*                                                                        */
5521 /**************************************************************************/
_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))5522 UINT    _nx_sntp_client_set_time_update_notify(NX_SNTP_CLIENT *client_ptr,
5523                              VOID (time_update_cb)(NX_SNTP_TIME_MESSAGE *time_update_ptr, NX_SNTP_TIME *local_time))
5524 {
5525 
5526 
5527     client_ptr -> nx_sntp_client_time_update_notify = time_update_cb;
5528 
5529     return NX_SUCCESS;
5530 }
5531 
5532 
5533 
5534 
5535 /**************************************************************************/
5536 /*                                                                        */
5537 /*  FUNCTION                                               RELEASE        */
5538 /*                                                                        */
5539 /*    _nx_sntp_client_utility_get_msec_diff               PORTABLE C      */
5540 /*                                                           6.1          */
5541 /*  AUTHOR                                                                */
5542 /*                                                                        */
5543 /*    Yuxin Zhou, Microsoft Corporation                                   */
5544 /*                                                                        */
5545 /*  DESCRIPTION                                                           */
5546 /*                                                                        */
5547 /*    This function computes the difference in milliseconds between two   */
5548 /*    NTP times, receiving an NTP packet, and transmitting it back.       */
5549 /*    The logic calculates the difference in the seconds component and    */
5550 /*    converts it to milliseconds.  It converts the fraction to useconds  */
5551 /*    and calculates that difference. Useconds are rounded to the nearest */
5552 /*    millisecond.  This logic assumes the transmit time occurs after     */
5553 /*    receive time.                                                       */
5554 /*                                                                        */
5555 /*    The net difference is the difference in milliseconds from the       */
5556 /*    fractions added to (or subtracted from) the difference in           */
5557 /*    milliseconds from the seconds component.                            */
5558 /*                                                                        */
5559 /*    Note that the conversion of useconds to milliseconds may result     */
5560 /*    in the two times' difference to be zero, when they are actually     */
5561 /*    different by useconds.                                              */
5562 /*                                                                        */
5563 /*   INPUT                                                                */
5564 /*                                                                        */
5565 /*    timeReceived_ptr                 NTP time of received message       */
5566 /*    timeTransmit_ptr                 NTP time of transmitted message    */
5567 /*    total_difference_msecs           Millseconds of difference in time  */
5568 /*    pos_diff                         True if Transmit Time >=           */
5569 /*                                          Receive Time                  */
5570 /*                                                                        */
5571 /*  OUTPUT                                                                */
5572 /*                                                                        */
5573 /*    NX_SUCCESS                       Valid transmit/receive times       */
5574 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result                    */
5575 /*    NX_SNTP_INVALID_TIME             Transmit time<receive time seconds */
5576 /*                                                                        */
5577 /*  CALLS                                                                 */
5578 /*                                                                        */
5579 /*    _nx_sntp_client_utility_convert_fraction_to_msecs                   */
5580 /*                                      Convert fraction to milliseconds  */
5581 /*                                                                        */
5582 /*  CALLED BY                                                             */
5583 /*                                                                        */
5584 /*    _nx_sntp_client_apply_sanity_checks                                 */
5585 /*                                     Apply sanity checks to time data   */
5586 /*    _nx_sntp_client_process_time_data                                   */
5587 /*                                     Apply server time to local time    */
5588 /*                                                                        */
5589 /*  RELEASE HISTORY                                                       */
5590 /*                                                                        */
5591 /*    DATE              NAME                      DESCRIPTION             */
5592 /*                                                                        */
5593 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5594 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5595 /*                                            resulting in version 6.1    */
5596 /*                                                                        */
5597 /**************************************************************************/
_nx_sntp_client_utility_get_msec_diff(NX_SNTP_TIME * timeReceived_ptr,NX_SNTP_TIME * timeTransmit_ptr,ULONG * total_difference_msecs,UINT * pos_diff)5598 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)
5599 {
5600 
5601 ULONG    usecsReceived, usecsTransmit;
5602 ULONG    msecsReceived, msecsTransmit;
5603 ULONG    seconds_difference_in_msecs;
5604 ULONG    temp;
5605 
5606 
5607     /* Check for overflow with a very large positive difference result.  */
5608     if (timeReceived_ptr -> seconds > timeTransmit_ptr -> seconds)
5609     {
5610 
5611         /* Use a temporary variable to store the difference in the seconds.  */
5612         temp = timeReceived_ptr -> seconds - timeTransmit_ptr -> seconds;
5613         *pos_diff = NX_FALSE;
5614     }
5615     else
5616     {
5617 
5618         /* Reverse the operand to get the absolute difference in the seconds.  */
5619         temp = timeTransmit_ptr -> seconds -timeReceived_ptr -> seconds;
5620         *pos_diff = NX_TRUE;
5621     }
5622 
5623     /* Check for overflow when converting seconds to milliseconds
5624        (0x3E8 = 1000).  */
5625     if (temp > (0xFFFFFFFF / 0x3E8))
5626     {
5627 
5628         /* Return error status.  */
5629         return NX_SNTP_OVERFLOW_ERROR;
5630     }
5631 
5632     /* Convert to msecs.  */
5633     seconds_difference_in_msecs = temp * 1000;
5634 
5635     /* Convert the Received time fraction to usecs and msecs.  */
5636     _nx_sntp_client_utility_fraction_to_usecs(timeReceived_ptr -> fraction, &usecsReceived);
5637 
5638     msecsReceived = usecsReceived / 1000;
5639 
5640     if (usecsReceived % 1000 >= 500)
5641         msecsReceived++;
5642 
5643     /* Convert the Transmit Time fraction to usecs and msecs.  */
5644     _nx_sntp_client_utility_fraction_to_usecs(timeTransmit_ptr -> fraction, &usecsTransmit);
5645 
5646     msecsTransmit = usecsTransmit / 1000;
5647 
5648     if (usecsTransmit % 1000 >= 500)
5649         msecsTransmit++;
5650 
5651     /* Get the difference of the two time stamps' fraction in milliseconds. */
5652     if (timeReceived_ptr -> seconds == timeTransmit_ptr -> seconds)
5653     {
5654 
5655         /* Determine the absolute difference in the millisecond component. */
5656         if (usecsTransmit >= usecsReceived)
5657         {
5658 
5659             *total_difference_msecs = msecsTransmit - msecsReceived;
5660         }
5661         else
5662         {
5663 
5664             /* Transmit time usecs < Received time usecs. */
5665             *pos_diff = NX_FALSE;
5666             *total_difference_msecs = msecsReceived - msecsTransmit;
5667         }
5668     }
5669     else
5670     {
5671 
5672         /* Consider the case where the transmit time seconds is greater. */
5673         if (timeTransmit_ptr -> seconds > timeReceived_ptr -> seconds)
5674         {
5675 
5676             if ( usecsTransmit >= usecsReceived)
5677             {
5678 
5679                 /*  This will add to the total milliseconds' difference. */
5680                *total_difference_msecs = seconds_difference_in_msecs + (msecsTransmit - msecsReceived);
5681             }
5682             else /* (usecsReceived > usecsTransmit) */
5683             {
5684 
5685                 /* This will subtract from the total milliseconds' difference . */
5686                 *total_difference_msecs = seconds_difference_in_msecs - (msecsReceived - msecsTransmit);
5687             }
5688         }
5689 
5690         /* Consider the case where the transmit time seconds is less. */
5691         else
5692         {
5693 
5694             if (usecsReceived >= usecsTransmit)
5695             {
5696 
5697                 /*  This will add to the total milliseconds' difference. */
5698                *total_difference_msecs = seconds_difference_in_msecs + (msecsReceived - msecsTransmit);
5699             }
5700             else /* (usecsTransmit > usecsReceived) */
5701             {
5702 
5703                 /* This will subtract from the total milliseconds' difference . */
5704                 *total_difference_msecs = seconds_difference_in_msecs - (msecsTransmit - msecsReceived);
5705             }
5706         }
5707     }
5708 
5709     /* Return successful completion status.  */
5710     return NX_SUCCESS;
5711 
5712 }
5713 
5714 /**************************************************************************/
5715 /*                                                                        */
5716 /*  FUNCTION                                               RELEASE        */
5717 /*                                                                        */
5718 /*    _nx_sntp_client_utility_is_zero_data                PORTABLE C      */
5719 /*                                                           6.1          */
5720 /*  AUTHOR                                                                */
5721 /*                                                                        */
5722 /*    Yuxin Zhou, Microsoft Corporation                                   */
5723 /*                                                                        */
5724 /*  DESCRIPTION                                                           */
5725 /*                                                                        */
5726 /*   This function tests each byte (UCHAR) of data to be non zero.  The   */
5727 /*   return value indicates if the entire data is zero.                   */
5728 /*                                                                        */
5729 /*   INPUT                                                                */
5730 /*                                                                        */
5731 /*    data                               Pointer to first byte of data    */
5732 /*    size                               Number of bytes in data          */
5733 /*                                                                        */
5734 /*  OUTPUT                                                                */
5735 /*                                                                        */
5736 /*    NX_TRUE                            Each byte of data is zero        */
5737 /*    NX_FALSE                           At least one byte is non zero    */
5738 /*                                                                        */
5739 /*  CALLS                                                                 */
5740 /*                                                                        */
5741 /*    None                                                                */
5742 /*                                                                        */
5743 /*  CALLED BY                                                             */
5744 /*                                                                        */
5745 /*   _nx_sntp_client_apply_sanity_checks Checks SNTP server reply validity*/
5746 /*                                                                        */
5747 /*  RELEASE HISTORY                                                       */
5748 /*                                                                        */
5749 /*    DATE              NAME                      DESCRIPTION             */
5750 /*                                                                        */
5751 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5752 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5753 /*                                            resulting in version 6.1    */
5754 /*                                                                        */
5755 /**************************************************************************/
_nx_sntp_client_utility_is_zero_data(UCHAR * data,UINT size)5756 UINT _nx_sntp_client_utility_is_zero_data(UCHAR *data, UINT size)
5757 {
5758 
5759 UINT i;
5760 UINT is_zero;
5761 
5762 
5763     /* Initialize local variables. */
5764     i = 0;
5765     is_zero = NX_TRUE;
5766 
5767     while(i < size)
5768     {
5769 
5770         if (*data != 0x0)
5771         {
5772 
5773             is_zero = NX_FALSE;
5774             break;
5775         }
5776 
5777         data += sizeof(UCHAR);
5778         i++;
5779     }
5780 
5781     return is_zero;
5782 }
5783 
5784 
5785 /**************************************************************************/
5786 /*                                                                        */
5787 /*  FUNCTION                                               RELEASE        */
5788 /*                                                                        */
5789 /*    _nx_sntp_client_utility_convert_fraction_to_msecs   PORTABLE C      */
5790 /*                                                           6.1          */
5791 /*  AUTHOR                                                                */
5792 /*                                                                        */
5793 /*    Yuxin Zhou, Microsoft Corporation                                   */
5794 /*                                                                        */
5795 /*  DESCRIPTION                                                           */
5796 /*                                                                        */
5797 /*   This function converts the fraction in an NTP time to milliseconds.  */
5798 /*                                                                        */
5799 /*   INPUT                                                                */
5800 /*                                                                        */
5801 /*    milliseconds                     Pointer to milliseconds converted  */
5802 /*    time_ptr                         Pointer to an NTP time             */
5803 /*                                                                        */
5804 /*  OUTPUT                                                                */
5805 /*                                                                        */
5806 /*    NX_SUCCESS                       Successful completion              */
5807 /*                                                                        */
5808 /*  CALLS                                                                 */
5809 /*                                                                        */
5810 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
5811 /*                                     Convert fraction to usecs          */
5812 /*                                                                        */
5813 /*  CALLED BY                                                             */
5814 /*                                                                        */
5815 /*   _nx_sntp_client_utility_display_NTP_time                             */
5816 /*                                     Display NTP time in seconds        */
5817 /*                                                                        */
5818 /*  RELEASE HISTORY                                                       */
5819 /*                                                                        */
5820 /*    DATE              NAME                      DESCRIPTION             */
5821 /*                                                                        */
5822 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5823 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5824 /*                                            resulting in version 6.1    */
5825 /*                                                                        */
5826 /**************************************************************************/
_nx_sntp_client_utility_convert_fraction_to_msecs(ULONG * milliseconds,NX_SNTP_TIME * time_ptr)5827 UINT  _nx_sntp_client_utility_convert_fraction_to_msecs(ULONG *milliseconds, NX_SNTP_TIME *time_ptr)
5828 {
5829 
5830 ULONG usecs;
5831 
5832 
5833     /* Convert to usecs first.  */
5834     _nx_sntp_client_utility_fraction_to_usecs(time_ptr ->fraction, &usecs);
5835 
5836     /* Then convert to milliseconds.  */
5837     *milliseconds = usecs / 1000;
5838 
5839     /* Round up if greater than 500 usecs left over*/
5840     if (usecs % 1000 >= 500)
5841     {
5842 
5843         (*milliseconds)++;
5844     }
5845 
5846     /* Return successful completion.  */
5847     return NX_SUCCESS;
5848 }
5849 
5850 
5851 /**************************************************************************/
5852 /*                                                                        */
5853 /*  FUNCTION                                               RELEASE        */
5854 /*                                                                        */
5855 /*    _nxe_sntp_client_utility_usecs_to_fraction          PORTABLE C      */
5856 /*                                                           6.1          */
5857 /*  AUTHOR                                                                */
5858 /*                                                                        */
5859 /*    Yuxin Zhou, Microsoft Corporation                                   */
5860 /*                                                                        */
5861 /*  DESCRIPTION                                                           */
5862 /*                                                                        */
5863 /*   This function performs error checking on the utility to convert      */
5864 /*   microseconds to fraction.                                            */
5865 /*                                                                        */
5866 /*   INPUT                                                                */
5867 /*                                                                        */
5868 /*    usecs                            Microseconds to convert            */
5869 /*    fraction                         Pointer to converted fraction      */
5870 /*                                                                        */
5871 /*  OUTPUT                                                                */
5872 /*                                                                        */
5873 /*    NX_SNTP_INVALID_TIME             Invalid SNTP data input            */
5874 /*    status                           Actual completion status           */
5875 /*                                                                        */
5876 /*  CALLS                                                                 */
5877 /*                                                                        */
5878 /*    _nx_sntp_client_utility_usecs_to_fraction                           */
5879 /*                                     Actual usecs conversion service    */
5880 /*                                                                        */
5881 /*  CALLED BY                                                             */
5882 /*                                                                        */
5883 /*   Application code                                                     */
5884 /*                                                                        */
5885 /*  RELEASE HISTORY                                                       */
5886 /*                                                                        */
5887 /*    DATE              NAME                      DESCRIPTION             */
5888 /*                                                                        */
5889 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5890 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5891 /*                                            resulting in version 6.1    */
5892 /*                                                                        */
5893 /**************************************************************************/
_nxe_sntp_client_utility_usecs_to_fraction(ULONG usecs,ULONG * fraction)5894 UINT    _nxe_sntp_client_utility_usecs_to_fraction(ULONG usecs, ULONG *fraction)
5895 {
5896 
5897 UINT status;
5898 
5899 
5900     if ((usecs == 0) || (fraction == NX_NULL))
5901     {
5902 
5903         return NX_SNTP_INVALID_TIME;
5904     }
5905 
5906     status = _nx_sntp_client_utility_usecs_to_fraction(usecs, fraction);
5907 
5908     return status;
5909 }
5910 
5911 
5912 /**************************************************************************/
5913 /*                                                                        */
5914 /*  FUNCTION                                               RELEASE        */
5915 /*                                                                        */
5916 /*    _nx_sntp_client_utility_usecs_to_fraction           PORTABLE C      */
5917 /*                                                           6.1          */
5918 /*  AUTHOR                                                                */
5919 /*                                                                        */
5920 /*    Yuxin Zhou, Microsoft Corporation                                   */
5921 /*                                                                        */
5922 /*  DESCRIPTION                                                           */
5923 /*                                                                        */
5924 /*   This function converts microseconds to a time stamp fraction.  It is */
5925 /*   primarily an intermediary function used in the process of converting */
5926 /*   millliseconds to fixed point time fraction data.                     */
5927 /*                                                                        */
5928 /*   This conversion scheme is limited to microseconds less than 1000000. */
5929 /*                                                                        */
5930 /*   INPUT                                                                */
5931 /*                                                                        */
5932 /*    usecs                            Microseconds to convert            */
5933 /*    fraction                         Fraction to converted fraction     */
5934 /*                                                                        */
5935 /*  OUTPUT                                                                */
5936 /*                                                                        */
5937 /*    NX_SUCCESS                       Successful completion status       */
5938 /*    NX_SNTP_OVERFLOW_ERROR           Overflow error status              */
5939 /*                                                                        */
5940 /*  CALLS                                                                 */
5941 /*                                                                        */
5942 /*    None                                                                */
5943 /*                                                                        */
5944 /*  CALLED BY                                                             */
5945 /*                                                                        */
5946 /*   _nx_sntp_client_utility_msecs_to_fraction                            */
5947 /*                                     Convert milliseconds to fixed point*/
5948 /*                                                                        */
5949 /*  RELEASE HISTORY                                                       */
5950 /*                                                                        */
5951 /*    DATE              NAME                      DESCRIPTION             */
5952 /*                                                                        */
5953 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5954 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5955 /*                                            resulting in version 6.1    */
5956 /*                                                                        */
5957 /**************************************************************************/
_nx_sntp_client_utility_usecs_to_fraction(ULONG usecs,ULONG * fraction)5958 UINT  _nx_sntp_client_utility_usecs_to_fraction(ULONG usecs, ULONG *fraction)
5959 {
5960 
5961 ULONG _frac = usecs * 3962;
5962 
5963 
5964     *fraction = (usecs * 4294) + (_frac >> 12);
5965 
5966     if((_frac & 4095) >= 2048)
5967         *fraction = *fraction + 1;
5968 
5969     /* Successful completion.  */
5970     return NX_SUCCESS;
5971 }
5972 
5973 
5974 /**************************************************************************/
5975 /*                                                                        */
5976 /*  FUNCTION                                               RELEASE        */
5977 /*                                                                        */
5978 /*    _nxe_sntp_client_utility_msecs_to_fraction          PORTABLE C      */
5979 /*                                                           6.1          */
5980 /*  AUTHOR                                                                */
5981 /*                                                                        */
5982 /*    Yuxin Zhou, Microsoft Corporation                                   */
5983 /*                                                                        */
5984 /*  DESCRIPTION                                                           */
5985 /*                                                                        */
5986 /*   This function performs error checking on the utility to convert      */
5987 /*   milliseconds to fraction.                                            */
5988 /*                                                                        */
5989 /*   INPUT                                                                */
5990 /*                                                                        */
5991 /*    msecs                            Milliseconds to convert            */
5992 /*    fraction                         Pointer to converted fraction      */
5993 /*                                                                        */
5994 /*  OUTPUT                                                                */
5995 /*                                                                        */
5996 /*    NX_SNTP_INVALID_TIME             Invalid SNTP data input            */
5997 /*    status                           Actual completion status           */
5998 /*                                                                        */
5999 /*  CALLS                                                                 */
6000 /*                                                                        */
6001 /*    _nx_sntp_client_utility_msecs_to_fraction                           */
6002 /*                                     Actual msecs conversion service    */
6003 /*                                                                        */
6004 /*  CALLED BY                                                             */
6005 /*                                                                        */
6006 /*   Application code                                                     */
6007 /*                                                                        */
6008 /*  RELEASE HISTORY                                                       */
6009 /*                                                                        */
6010 /*    DATE              NAME                      DESCRIPTION             */
6011 /*                                                                        */
6012 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6013 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6014 /*                                            resulting in version 6.1    */
6015 /*                                                                        */
6016 /**************************************************************************/
_nxe_sntp_client_utility_msecs_to_fraction(ULONG msecs,ULONG * fraction)6017 UINT    _nxe_sntp_client_utility_msecs_to_fraction(ULONG msecs, ULONG *fraction)
6018 {
6019 
6020 UINT status;
6021 
6022 
6023     if ((msecs == 0) || (fraction == NX_NULL))
6024     {
6025 
6026         return NX_SNTP_INVALID_TIME;
6027     }
6028 
6029     status = _nx_sntp_client_utility_msecs_to_fraction(msecs, fraction);
6030 
6031     return status;
6032 }
6033 
6034 
6035 /**************************************************************************/
6036 /*                                                                        */
6037 /*  FUNCTION                                               RELEASE        */
6038 /*                                                                        */
6039 /*    _nx_sntp_client_utility_msecs_to_fraction           PORTABLE C      */
6040 /*                                                           6.1          */
6041 /*  AUTHOR                                                                */
6042 /*                                                                        */
6043 /*    Yuxin Zhou, Microsoft Corporation                                   */
6044 /*                                                                        */
6045 /*  DESCRIPTION                                                           */
6046 /*                                                                        */
6047 /*   This function converts milliseconds to fixed point notation used in  */
6048 /*   the NTP time fraction field. This will not accept msecs >= 1000      */
6049 /*   because that number cannot be represented in an NTP time fraction.   */
6050 /*                                                                        */
6051 /*   INPUT                                                                */
6052 /*                                                                        */
6053 /*    msecs                            Milliseconds to convert            */
6054 /*    fraction                         Pointer to converted fraction      */
6055 /*                                                                        */
6056 /*  OUTPUT                                                                */
6057 /*                                                                        */
6058 /*    NX_SUCCESS                       Successful completion status       */
6059 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result                    */
6060 /*    status                           Actual completion status           */
6061 /*                                                                        */
6062 /*  CALLS                                                                 */
6063 /*                                                                        */
6064 /*    _nx_sntp_client_utility_usecs_to_fraction                           */
6065 /*                                     Convert usecs to fixed point       */
6066 /*                                                                        */
6067 /*  CALLED BY                                                             */
6068 /*                                                                        */
6069 /*   _nx_sntp_client_utility_add_msecs_to_ntp_time                        */
6070 /*                                     Add msecs to an NTP time data      */
6071 /*   _nx_sntp_client_utility_add_NTPtime                                  */
6072 /*                                     Add two NTP time fields            */
6073 /*                                                                        */
6074 /*  RELEASE HISTORY                                                       */
6075 /*                                                                        */
6076 /*    DATE              NAME                      DESCRIPTION             */
6077 /*                                                                        */
6078 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6079 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6080 /*                                            resulting in version 6.1    */
6081 /*                                                                        */
6082 /**************************************************************************/
_nx_sntp_client_utility_msecs_to_fraction(ULONG msecs,ULONG * fraction)6083 UINT  _nx_sntp_client_utility_msecs_to_fraction(ULONG msecs, ULONG *fraction)
6084 {
6085 
6086 UINT    status;
6087 ULONG   usecs;
6088 
6089 
6090     /* Check for possible overflow.  */
6091     if (msecs > 1000)
6092     {
6093 
6094         /* Return error condition.  */
6095         return NX_SNTP_OVERFLOW_ERROR;
6096     }
6097 
6098     /* Convert msecs to usecs first.  */
6099     usecs = msecs * 1000;
6100 
6101     /* Convert usecs to fraction.  */
6102     status = _nx_sntp_client_utility_usecs_to_fraction(usecs, fraction);
6103 
6104     /* Check for error.  */
6105     if (status != NX_SUCCESS)
6106     {
6107 
6108         /* Return the error status.  */
6109         return status;
6110     }
6111 
6112     /* Successful completion.  */
6113     return NX_SUCCESS;
6114 }
6115 
6116 
6117 /**************************************************************************/
6118 /*                                                                        */
6119 /*  FUNCTION                                               RELEASE        */
6120 /*                                                                        */
6121 /*    _nxe_sntp_client_utility_fraction_to_usecs          PORTABLE C      */
6122 /*                                                           6.1          */
6123 /*  AUTHOR                                                                */
6124 /*                                                                        */
6125 /*    Yuxin Zhou, Microsoft Corporation                                   */
6126 /*                                                                        */
6127 /*  DESCRIPTION                                                           */
6128 /*                                                                        */
6129 /*   This function performs error checking on the utility to convert      */
6130 /*   fraction to microseconds.                                            */
6131 /*                                                                        */
6132 /*   INPUT                                                                */
6133 /*                                                                        */
6134 /*    fraction                         Fraction to convert                */
6135 /*    usecs                            Pointer to converted microseconds  */
6136 /*                                                                        */
6137 /*  OUTPUT                                                                */
6138 /*                                                                        */
6139 /*    status                           Actual completion status           */
6140 /*                                                                        */
6141 /*  CALLS                                                                 */
6142 /*                                                                        */
6143 /*    _nx_sntp_client_utility_fraction_to_usecs                           */
6144 /*                                     Actual usecs conversion service    */
6145 /*                                                                        */
6146 /*  CALLED BY                                                             */
6147 /*                                                                        */
6148 /*   Application code                                                     */
6149 /*                                                                        */
6150 /*  RELEASE HISTORY                                                       */
6151 /*                                                                        */
6152 /*    DATE              NAME                      DESCRIPTION             */
6153 /*                                                                        */
6154 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6155 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6156 /*                                            resulting in version 6.1    */
6157 /*                                                                        */
6158 /**************************************************************************/
_nxe_sntp_client_utility_fraction_to_usecs(ULONG fraction,ULONG * usecs)6159 UINT    _nxe_sntp_client_utility_fraction_to_usecs(ULONG fraction, ULONG *usecs)
6160 {
6161 
6162 UINT status;
6163 
6164 
6165     if (usecs == NX_NULL)
6166     {
6167         return NX_SNTP_INVALID_TIME;
6168     }
6169 
6170     status = _nx_sntp_client_utility_fraction_to_usecs(fraction, usecs);
6171 
6172     return status;
6173 }
6174 
6175 
6176 /**************************************************************************/
6177 /*                                                                        */
6178 /*  FUNCTION                                               RELEASE        */
6179 /*                                                                        */
6180 /*    _nx_sntp_client_utility_fraction_to_usecs           PORTABLE C      */
6181 /*                                                           6.1          */
6182 /*  AUTHOR                                                                */
6183 /*                                                                        */
6184 /*    Yuxin Zhou, Microsoft Corporation                                   */
6185 /*                                                                        */
6186 /*  DESCRIPTION                                                           */
6187 /*                                                                        */
6188 /*   This function converts a time stamp fraction to microseconds.  It is */
6189 /*   primarily an intermediary function used in the process of converting */
6190 /*   fixed point time fraction data to msecs.                             */
6191 /*                                                                        */
6192 /*   INPUT                                                                */
6193 /*                                                                        */
6194 /*    fraction                         Fraction to convert to usecs       */
6195 /*    usecs                            Pointer to ucsecs from fraction    */
6196 /*                                                                        */
6197 /*  OUTPUT                                                                */
6198 /*                                                                        */
6199 /*    None                                                                */
6200 /*                                                                        */
6201 /*  CALLS                                                                 */
6202 /*                                                                        */
6203 /*    None                                                                */
6204 /*                                                                        */
6205 /*  CALLED BY                                                             */
6206 /*                                                                        */
6207 /*   _nx_sntp_client_get_local_time_extended                              */
6208 /*                                     Get extended local time            */
6209 /*   _nx_sntp_client_utility_convert_fraction_to_msecs                    */
6210 /*                                     Convert time fraction to msecs     */
6211 /*                                                                        */
6212 /*  RELEASE HISTORY                                                       */
6213 /*                                                                        */
6214 /*    DATE              NAME                      DESCRIPTION             */
6215 /*                                                                        */
6216 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6217 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6218 /*                                            resulting in version 6.1    */
6219 /*                                                                        */
6220 /**************************************************************************/
_nx_sntp_client_utility_fraction_to_usecs(ULONG fraction,ULONG * usecs)6221 UINT  _nx_sntp_client_utility_fraction_to_usecs(ULONG fraction, ULONG *usecs)
6222 {
6223 
6224 ULONG value, segment;
6225 int i;
6226 
6227     value = 0;
6228 
6229     for(i = 2; i < 32; i+=6)
6230     {
6231         segment = (fraction >> i) & 0x3F;
6232 
6233         if((value & 0x3F) >= 32)
6234             value = (value  >> 6) + segment * 15625 + 1;
6235         else
6236             value = (value  >> 6) + segment * 15625;
6237     }
6238     *usecs = value;
6239 
6240     return(NX_SUCCESS);
6241 }
6242 
6243 
6244 /**************************************************************************/
6245 /*                                                                        */
6246 /*  FUNCTION                                               RELEASE        */
6247 /*                                                                        */
6248 /*    _nx_sntp_client_utility_convert_refID_KOD_code      PORTABLE C      */
6249 /*                                                           6.1          */
6250 /*  AUTHOR                                                                */
6251 /*                                                                        */
6252 /*    Yuxin Zhou, Microsoft Corporation                                   */
6253 /*                                                                        */
6254 /*  DESCRIPTION                                                           */
6255 /*                                                                        */
6256 /*  This function converts the reference ID field in a NTP time message   */
6257 /*  data to a known Kiss of Death reference_id.                           */
6258 /*                                                                        */
6259 /*  Note the Kiss of Death reference_id list is subject to change.  This  */
6260 /*  is current as of 4/01/2007.                                           */
6261 /*                                                                        */
6262 /*  INPUT                                                                 */
6263 /*                                                                        */
6264 /*    reference_id                 Pointer to the reference ID to convert */
6265 /*    code_id                      Pointer to converted code              */
6266 /*                                                                        */
6267 /*  OUTPUT                                                                */
6268 /*                                                                        */
6269 /*    NX_SUCCESS                   Successful completion status           */
6270 /*                                                                        */
6271 /*  CALLS                                                                 */
6272 /*                                                                        */
6273 /*    memcmp                       Copy data to specified area of memory  */
6274 /*                                                                        */
6275 /*  CALLED BY                                                             */
6276 /*                                                                        */
6277 /*    Application Code (e.g. the Client kiss of death handler callback)   */
6278 /*                                                                        */
6279 /*  RELEASE HISTORY                                                       */
6280 /*                                                                        */
6281 /*    DATE              NAME                      DESCRIPTION             */
6282 /*                                                                        */
6283 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6284 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6285 /*                                            resulting in version 6.1    */
6286 /*                                                                        */
6287 /**************************************************************************/
_nx_sntp_client_utility_convert_refID_KOD_code(UCHAR * reference_id,UINT * code_id)6288 UINT  _nx_sntp_client_utility_convert_refID_KOD_code(UCHAR *reference_id, UINT *code_id)
6289 {
6290 
6291 /* This is the internal list of Kiss of Death codes and their meaning.  */
6292 
6293 
6294     /* Compare the reference_id to each known reference_id and if it matches return the reference_id ID.  */
6295     if (!memcmp(reference_id, ANYCAST, 4))
6296     {
6297         *code_id = NX_SNTP_KOD_ANYCAST;
6298     }
6299     else if (!memcmp(reference_id, AUTH_FAIL, 4))
6300     {
6301         *code_id = NX_SNTP_KOD_AUTH_FAIL;
6302     }
6303     else if (!memcmp(reference_id, AUTOKEY_FAIL, 4))
6304     {
6305         *code_id = NX_SNTP_KOD_AUTOKEY_FAIL;
6306     }
6307     else if (!memcmp(reference_id, BROADCAST, 4))
6308     {
6309         *code_id = NX_SNTP_KOD_BROADCAST;
6310     }
6311     else if (!memcmp(reference_id, CRYP_FAIL, 4))
6312     {
6313         *code_id = NX_SNTP_KOD_CRYP_FAIL;
6314     }
6315     else if (!memcmp(reference_id, DENY, 4))
6316     {
6317         *code_id = NX_SNTP_KOD_DENY;
6318     }
6319     else if (!memcmp(reference_id, DROP, 4))
6320     {
6321         *code_id = NX_SNTP_KOD_DROP;
6322     }
6323     else if (!memcmp(reference_id, DENY_POLICY, 4))
6324     {
6325         *code_id = NX_SNTP_KOD_DENY_POLICY;
6326     }
6327     else if (!memcmp(reference_id, NOT_INIT, 4))
6328     {
6329         *code_id = NX_SNTP_KOD_NOT_INIT;
6330     }
6331     else if (!memcmp(reference_id, MANYCAST, 4))
6332     {
6333         *code_id = NX_SNTP_KOD_MANYCAST;
6334     }
6335     else if (!memcmp(reference_id, NO_KEY, 4))
6336     {
6337         *code_id = NX_SNTP_KOD_NO_KEY;
6338     }
6339     else if (!memcmp(reference_id, RATE, 4))
6340     {
6341         *code_id = NX_SNTP_KOD_RATE;
6342     }
6343     else if (!memcmp(reference_id, RMOT, 4))
6344     {
6345         *code_id = NX_SNTP_KOD_RMOT;
6346     }
6347     else if (!memcmp(reference_id, STEP, 4))
6348     {
6349         *code_id = NX_SNTP_KOD_STEP;
6350     }
6351     else
6352     {
6353         /* Set reference_id ID to generic KOD 'other' reference_id.  */
6354         *code_id = NX_SNTP_KISS_OF_DEATH_PACKET;
6355     }
6356 
6357     /* Return successful completion.  */
6358     return NX_SUCCESS;
6359 }
6360 
6361 
6362 /**************************************************************************/
6363 /*                                                                        */
6364 /*  FUNCTION                                               RELEASE        */
6365 /*                                                                        */
6366 /*    _nx_sntp_client_utility_addition_overflow_check     PORTABLE C      */
6367 /*                                                           6.1          */
6368 /*  AUTHOR                                                                */
6369 /*                                                                        */
6370 /*    Yuxin Zhou, Microsoft Corporation                                   */
6371 /*                                                                        */
6372 /*  DESCRIPTION                                                           */
6373 /*                                                                        */
6374 /*   This function performs a simple platform independent check for       */
6375 /*   overflow when adding two operands.                                   */
6376 /*                                                                        */
6377 /*   INPUT                                                                */
6378 /*                                                                        */
6379 /*    temp1                            First addition operand             */
6380 /*    temp2                            Second addition operand            */
6381 /*                                                                        */
6382 /*  OUTPUT                                                                */
6383 /*                                                                        */
6384 /*    NX_SNTP_OVERFLOW_ERROR           Overflow result adding time        */
6385 /*    NX_SUCCESS                       Successful completion status       */
6386 /*                                                                        */
6387 /*  CALLS                                                                 */
6388 /*                                                                        */
6389 /*    None                                                                */
6390 /*                                                                        */
6391 /*  CALLED BY                                                             */
6392 /*                                                                        */
6393 /*    _nx_sntp_client_utility_add_msecs_to_ntp_time                       */
6394 /*                                     Add msecs to an NTP time           */
6395 /*    _nx_sntp_client_utility_add_NTPtime                                 */
6396 /*                                     Add two NTP times                  */
6397 /*                                                                        */
6398 /*  RELEASE HISTORY                                                       */
6399 /*                                                                        */
6400 /*    DATE              NAME                      DESCRIPTION             */
6401 /*                                                                        */
6402 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6403 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6404 /*                                            resulting in version 6.1    */
6405 /*                                                                        */
6406 /**************************************************************************/
_nx_sntp_client_utility_addition_overflow_check(ULONG temp1,ULONG temp2)6407 UINT  _nx_sntp_client_utility_addition_overflow_check(ULONG temp1, ULONG temp2)
6408 {
6409 
6410 ULONG sum_lower_16, sum_upper_16;
6411 UINT  carry;
6412 
6413 
6414     carry = 0;
6415 
6416     /* Add the lower 16 bits.  */
6417     sum_lower_16 = (temp1 & NX_LOWER_16_MASK) + (temp2 & NX_LOWER_16_MASK);
6418 
6419     /* Check for carry.  */
6420     if (sum_lower_16 & NX_CARRY_BIT)
6421     {
6422 
6423         /* Use variable to add the carry to the upper 16 bits.*/
6424         carry = 1;
6425     }
6426 
6427     /* Add the upper 16 bits.  */
6428     sum_upper_16 = (temp1 >> NX_SHIFT_BY_16) + (temp2 >> NX_SHIFT_BY_16) + carry;
6429 
6430     /* Check for carry.  */
6431     if (sum_upper_16 & NX_CARRY_BIT)
6432     {
6433 
6434         /* This indicates an overflow. Return as an error.  */
6435         return NX_SNTP_OVERFLOW_ERROR;
6436     }
6437 
6438     /* Ok to add operands!*/
6439     return NX_SUCCESS;
6440 }