ReactOS 0.4.16-dev-927-g467dec4
sntp.c
Go to the documentation of this file.
1
6/*
7 * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30 * OF SUCH DAMAGE.
31 *
32 * This file is part of the lwIP TCP/IP stack.
33 *
34 * Author: Frédéric Bernon, Simon Goldschmidt
35 */
36
37
54#include "lwip/apps/sntp.h"
55
56#include "lwip/opt.h"
57#include "lwip/timeouts.h"
58#include "lwip/udp.h"
59#include "lwip/dns.h"
60#include "lwip/ip_addr.h"
61#include "lwip/pbuf.h"
62#include "lwip/dhcp.h"
63
64#include <string.h>
65#include <time.h>
66
67#if LWIP_UDP
68
69/* Handle support for more than one server via SNTP_MAX_SERVERS */
70#if SNTP_MAX_SERVERS > 1
71#define SNTP_SUPPORT_MULTIPLE_SERVERS 1
72#else /* NTP_MAX_SERVERS > 1 */
73#define SNTP_SUPPORT_MULTIPLE_SERVERS 0
74#endif /* NTP_MAX_SERVERS > 1 */
75
76#ifndef SNTP_SUPPRESS_DELAY_CHECK
77#if SNTP_UPDATE_DELAY < 15000
78#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!"
79#endif
80#endif
81
82/* the various debug levels for this file */
83#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE)
84#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE)
85#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
86#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
87#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
88
89#define SNTP_ERR_KOD 1
90
91/* SNTP protocol defines */
92#define SNTP_MSG_LEN 48
93
94#define SNTP_OFFSET_LI_VN_MODE 0
95#define SNTP_LI_MASK 0xC0
96#define SNTP_LI_NO_WARNING (0x00 << 6)
97#define SNTP_LI_LAST_MINUTE_61_SEC (0x01 << 6)
98#define SNTP_LI_LAST_MINUTE_59_SEC (0x02 << 6)
99#define SNTP_LI_ALARM_CONDITION (0x03 << 6) /* (clock not synchronized) */
100
101#define SNTP_VERSION_MASK 0x38
102#define SNTP_VERSION (4/* NTP Version 4*/<<3)
103
104#define SNTP_MODE_MASK 0x07
105#define SNTP_MODE_CLIENT 0x03
106#define SNTP_MODE_SERVER 0x04
107#define SNTP_MODE_BROADCAST 0x05
108
109#define SNTP_OFFSET_STRATUM 1
110#define SNTP_STRATUM_KOD 0x00
111
112#define SNTP_OFFSET_ORIGINATE_TIME 24
113#define SNTP_OFFSET_RECEIVE_TIME 32
114#define SNTP_OFFSET_TRANSMIT_TIME 40
115
116/* Number of seconds between 1970 and Feb 7, 2036 06:28:16 UTC (epoch 1) */
117#define DIFF_SEC_1970_2036 ((u32_t)2085978496L)
118
121#ifndef SNTP_FRAC_TO_US
122# if LWIP_HAVE_INT64
123# define SNTP_FRAC_TO_US(f) ((u32_t)(((u64_t)(f) * 1000000UL) >> 32))
124# else
125# define SNTP_FRAC_TO_US(f) ((u32_t)(f) / 4295)
126# endif
127#endif /* !SNTP_FRAC_TO_US */
128
129/* Configure behaviour depending on native, microsecond or second precision.
130 * Treat NTP timestamps as signed two's-complement integers. This way,
131 * timestamps that have the MSB set simply become negative offsets from
132 * the epoch (Feb 7, 2036 06:28:16 UTC). Representable dates range from
133 * 1968 to 2104.
134 */
135#ifndef SNTP_SET_SYSTEM_TIME_NTP
136# ifdef SNTP_SET_SYSTEM_TIME_US
137# define SNTP_SET_SYSTEM_TIME_NTP(s, f) \
138 SNTP_SET_SYSTEM_TIME_US((u32_t)((s) + DIFF_SEC_1970_2036), SNTP_FRAC_TO_US(f))
139# else
140# define SNTP_SET_SYSTEM_TIME_NTP(s, f) \
141 SNTP_SET_SYSTEM_TIME((u32_t)((s) + DIFF_SEC_1970_2036))
142# endif
143#endif /* !SNTP_SET_SYSTEM_TIME_NTP */
144
145/* Get the system time either natively as NTP timestamp or convert from
146 * Unix time in seconds and microseconds. Take care to avoid overflow if the
147 * microsecond value is at the maximum of 999999. Also add 0.5 us fudge to
148 * avoid special values like 0, and to mask round-off errors that would
149 * otherwise break round-trip conversion identity.
150 */
151#ifndef SNTP_GET_SYSTEM_TIME_NTP
152# define SNTP_GET_SYSTEM_TIME_NTP(s, f) do { \
153 u32_t sec_, usec_; \
154 SNTP_GET_SYSTEM_TIME(sec_, usec_); \
155 (s) = (s32_t)(sec_ - DIFF_SEC_1970_2036); \
156 (f) = usec_ * 4295 - ((usec_ * 2143) >> 16) + 2147; \
157 } while (0)
158#endif /* !SNTP_GET_SYSTEM_TIME_NTP */
159
160/* Start offset of the timestamps to extract from the SNTP packet */
161#define SNTP_OFFSET_TIMESTAMPS \
162 (SNTP_OFFSET_TRANSMIT_TIME + 8 - sizeof(struct sntp_timestamps))
163
164/* Round-trip delay arithmetic helpers */
165#if SNTP_COMP_ROUNDTRIP
166# if !LWIP_HAVE_INT64
167# error "SNTP round-trip delay compensation requires 64-bit arithmetic"
168# endif
169# define SNTP_SEC_FRAC_TO_S64(s, f) \
170 ((s64_t)(((u64_t)(s) << 32) | (u32_t)(f)))
171# define SNTP_TIMESTAMP_TO_S64(t) \
172 SNTP_SEC_FRAC_TO_S64(lwip_ntohl((t).sec), lwip_ntohl((t).frac))
173#endif /* SNTP_COMP_ROUNDTRIP */
174
178struct sntp_time {
179 u32_t sec;
180 u32_t frac;
181};
182
186struct sntp_timestamps {
187#if SNTP_COMP_ROUNDTRIP || SNTP_CHECK_RESPONSE >= 2
188 struct sntp_time orig;
189 struct sntp_time recv;
190#endif
191 struct sntp_time xmit;
192};
193
200#ifdef PACK_STRUCT_USE_INCLUDES
201# include "arch/bpstruct.h"
202#endif
204struct sntp_msg {
205 PACK_STRUCT_FLD_8(u8_t li_vn_mode);
206 PACK_STRUCT_FLD_8(u8_t stratum);
209 PACK_STRUCT_FIELD(u32_t root_delay);
210 PACK_STRUCT_FIELD(u32_t root_dispersion);
211 PACK_STRUCT_FIELD(u32_t reference_identifier);
212 PACK_STRUCT_FIELD(u32_t reference_timestamp[2]);
213 PACK_STRUCT_FIELD(u32_t originate_timestamp[2]);
214 PACK_STRUCT_FIELD(u32_t receive_timestamp[2]);
215 PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]);
218#ifdef PACK_STRUCT_USE_INCLUDES
219# include "arch/epstruct.h"
220#endif
221
222/* function prototypes */
223static void sntp_request(void *arg);
224
226static u8_t sntp_opmode;
227
229static struct udp_pcb *sntp_pcb;
231struct sntp_server {
232#if SNTP_SERVER_DNS
233 const char *name;
234#endif /* SNTP_SERVER_DNS */
236#if SNTP_MONITOR_SERVER_REACHABILITY
238 u8_t reachability;
239#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
240#if SNTP_SUPPORT_MULTIPLE_SERVERS
241 u8_t kod_received;
242#endif
243};
244static struct sntp_server sntp_servers[SNTP_MAX_SERVERS];
245
246#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
247static u8_t sntp_set_servers_from_dhcp;
248#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
249#if SNTP_SUPPORT_MULTIPLE_SERVERS
251static u8_t sntp_current_server;
252#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
253#define sntp_current_server 0
254#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
255
256#if SNTP_RETRY_TIMEOUT_EXP
257#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
259static u32_t sntp_retry_timeout;
260#else /* SNTP_RETRY_TIMEOUT_EXP */
261#define SNTP_RESET_RETRY_TIMEOUT()
262#define sntp_retry_timeout SNTP_RETRY_TIMEOUT
263#endif /* SNTP_RETRY_TIMEOUT_EXP */
264
265#if SNTP_CHECK_RESPONSE >= 1
267static ip_addr_t sntp_last_server_address;
268#endif /* SNTP_CHECK_RESPONSE >= 1 */
269
270#if SNTP_CHECK_RESPONSE >= 2
273static struct sntp_time sntp_last_timestamp_sent;
274#endif /* SNTP_CHECK_RESPONSE >= 2 */
275
276#if defined(LWIP_DEBUG) && !defined(sntp_format_time)
277/* Debug print helper. */
278static const char *
279sntp_format_time(s32_t sec)
280{
281 time_t ut;
282 ut = (u32_t)((u32_t)sec + DIFF_SEC_1970_2036);
283 return ctime(&ut);
284}
285#endif /* LWIP_DEBUG && !sntp_format_time */
286
290static void
291sntp_process(const struct sntp_timestamps *timestamps)
292{
293 s32_t sec;
294 u32_t frac;
295
296 sec = (s32_t)lwip_ntohl(timestamps->xmit.sec);
297 frac = lwip_ntohl(timestamps->xmit.frac);
298
299#if SNTP_COMP_ROUNDTRIP
300# if SNTP_CHECK_RESPONSE >= 2
301 if (timestamps->recv.sec != 0 || timestamps->recv.frac != 0)
302# endif
303 {
304 s32_t dest_sec;
305 u32_t dest_frac;
306 u32_t step_sec;
307
308 /* Get the destination time stamp, i.e. the current system time */
309 SNTP_GET_SYSTEM_TIME_NTP(dest_sec, dest_frac);
310
311 step_sec = (dest_sec < sec) ? ((u32_t)sec - (u32_t)dest_sec)
312 : ((u32_t)dest_sec - (u32_t)sec);
313 /* In order to avoid overflows, skip the compensation if the clock step
314 * is larger than about 34 years. */
315 if ((step_sec >> 30) == 0) {
316 s64_t t1, t2, t3, t4;
317
318 t4 = SNTP_SEC_FRAC_TO_S64(dest_sec, dest_frac);
319 t3 = SNTP_SEC_FRAC_TO_S64(sec, frac);
320 t1 = SNTP_TIMESTAMP_TO_S64(timestamps->orig);
321 t2 = SNTP_TIMESTAMP_TO_S64(timestamps->recv);
322 /* Clock offset calculation according to RFC 4330 */
323 t4 += ((t2 - t1) + (t3 - t4)) / 2;
324
325 sec = (s32_t)((u64_t)t4 >> 32);
326 frac = (u32_t)((u64_t)t4);
327 }
328 }
329#endif /* SNTP_COMP_ROUNDTRIP */
330
331 SNTP_SET_SYSTEM_TIME_NTP(sec, frac);
332 LWIP_UNUSED_ARG(frac); /* might be unused if only seconds are set */
333 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %" U32_F " us\n",
334 sntp_format_time(sec), SNTP_FRAC_TO_US(frac)));
335}
336
340static void
341sntp_initialize_request(struct sntp_msg *req)
342{
343 memset(req, 0, SNTP_MSG_LEN);
344 req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
345
346#if SNTP_CHECK_RESPONSE >= 2 || SNTP_COMP_ROUNDTRIP
347 {
348 s32_t secs;
349 u32_t sec, frac;
350 /* Get the transmit timestamp */
351 SNTP_GET_SYSTEM_TIME_NTP(secs, frac);
352 sec = lwip_htonl((u32_t)secs);
354
355# if SNTP_CHECK_RESPONSE >= 2
356 sntp_last_timestamp_sent.sec = sec;
357 sntp_last_timestamp_sent.frac = frac;
358# endif
359 req->transmit_timestamp[0] = sec;
360 req->transmit_timestamp[1] = frac;
361 }
362#endif /* SNTP_CHECK_RESPONSE >= 2 || SNTP_COMP_ROUNDTRIP */
363}
364
370static void
371sntp_retry(void *arg)
372{
374
375 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
376 sntp_retry_timeout));
377
378 /* set up a timer to send a retry and increase the retry delay */
379 sys_untimeout(sntp_request, NULL);
380 sys_timeout(sntp_retry_timeout, sntp_request, NULL);
381
382#if SNTP_RETRY_TIMEOUT_EXP
383 {
384 u32_t new_retry_timeout;
385 /* increase the timeout for next retry */
386 new_retry_timeout = sntp_retry_timeout << 1;
387 /* limit to maximum timeout and prevent overflow */
388 if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
389 (new_retry_timeout > sntp_retry_timeout)) {
390 sntp_retry_timeout = new_retry_timeout;
391 } else {
392 sntp_retry_timeout = SNTP_RETRY_TIMEOUT_MAX;
393 }
394 }
395#endif /* SNTP_RETRY_TIMEOUT_EXP */
396}
397
398#if SNTP_SUPPORT_MULTIPLE_SERVERS
407static void
408sntp_try_next_server(void *arg)
409{
410 u8_t old_server, i;
412
413 old_server = sntp_current_server;
414 for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) {
415 sntp_current_server++;
416 if (sntp_current_server >= SNTP_MAX_SERVERS) {
417 sntp_current_server = 0;
418 }
419 if (sntp_servers[sntp_current_server].kod_received) {
420 /* KOD received, don't use this server */
421 continue;
422 }
423 if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr)
425 || (sntp_servers[sntp_current_server].name != NULL)
426#endif
427 ) {
428 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
429 (u16_t)sntp_current_server));
430 /* new server: reset retry timeout */
431 SNTP_RESET_RETRY_TIMEOUT();
432 /* instantly send a request to the next server */
433 sntp_request(NULL);
434 return;
435 }
436 }
437 /* no other valid server found */
438 sntp_current_server = old_server;
439 sntp_retry(NULL);
440}
441
442static void
443sntp_kod_try_next_server(void *arg)
444{
445 sntp_servers[sntp_current_server].kod_received = 1;
446 sntp_try_next_server(arg);
447}
448
449#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
450/* Always retry on error if only one server is supported */
451#define sntp_try_next_server sntp_retry
452#define sntp_kod_try_next_server sntp_retry
453#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
454
456static void
457sntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
458{
459 struct sntp_timestamps timestamps;
460 u8_t mode;
461 u8_t stratum;
462 err_t err;
463
465 LWIP_UNUSED_ARG(pcb);
466
467 err = ERR_ARG;
468#if SNTP_CHECK_RESPONSE >= 1
469 /* check server address and port */
470 if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_eq(addr, &sntp_last_server_address)) &&
471 (port == SNTP_PORT))
472#else /* SNTP_CHECK_RESPONSE >= 1 */
475#endif /* SNTP_CHECK_RESPONSE >= 1 */
476 {
477 /* process the response */
478 if (p->tot_len == SNTP_MSG_LEN) {
479 mode = pbuf_get_at(p, SNTP_OFFSET_LI_VN_MODE) & SNTP_MODE_MASK;
480 /* if this is a SNTP response... */
481 if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) ||
482 ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) {
483 stratum = pbuf_get_at(p, SNTP_OFFSET_STRATUM);
484
485 if (stratum == SNTP_STRATUM_KOD) {
486 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
487 err = SNTP_ERR_KOD;
488 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
489 } else {
490 pbuf_copy_partial(p, &timestamps, sizeof(timestamps), SNTP_OFFSET_TIMESTAMPS);
491#if SNTP_CHECK_RESPONSE >= 2
492 /* check originate_timetamp against sntp_last_timestamp_sent */
493 if (timestamps.orig.sec != sntp_last_timestamp_sent.sec ||
494 timestamps.orig.frac != sntp_last_timestamp_sent.frac) {
495 LWIP_DEBUGF(SNTP_DEBUG_WARN,
496 ("sntp_recv: Invalid originate timestamp in response\n"));
497 } else
498#endif /* SNTP_CHECK_RESPONSE >= 2 */
499 /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
500 {
501 /* correct answer */
502 err = ERR_OK;
503 }
504 }
505 } else {
506 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
507 /* wait for correct response */
509 }
510 } else {
511 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
512 }
513 }
514#if SNTP_CHECK_RESPONSE >= 1
515 else {
516 /* packet from wrong remote address or port, wait for correct response */
518 }
519#endif /* SNTP_CHECK_RESPONSE >= 1 */
520
521 pbuf_free(p);
522
523 if (err == ERR_OK) {
524 /* correct packet received: process it it */
525 sntp_process(&timestamps);
526
527#if SNTP_MONITOR_SERVER_REACHABILITY
528 /* indicate that server responded */
529 sntp_servers[sntp_current_server].reachability |= 1;
530#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
531 /* Set up timeout for next request (only if poll response was received)*/
532 if (sntp_opmode == SNTP_OPMODE_POLL) {
533 u32_t sntp_update_delay;
534 sys_untimeout(sntp_try_next_server, NULL);
535 sys_untimeout(sntp_request, NULL);
536
537 /* Correct response, reset retry timeout */
538 SNTP_RESET_RETRY_TIMEOUT();
539
540 sntp_update_delay = (u32_t)SNTP_UPDATE_DELAY;
541 sys_timeout(sntp_update_delay, sntp_request, NULL);
542 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
543 sntp_update_delay));
544 }
545 } else if (err == SNTP_ERR_KOD) {
546 /* KOD errors are only processed in case of an explicit poll response */
547 if (sntp_opmode == SNTP_OPMODE_POLL) {
548 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
549 sntp_kod_try_next_server(NULL);
550 }
551 } else {
552 /* ignore any broken packet, poll mode: retry after timeout to avoid flooding */
553 }
554}
555
560static void
561sntp_send_request(const ip_addr_t *server_addr)
562{
563 struct pbuf *p;
564
565 LWIP_ASSERT("server_addr != NULL", server_addr != NULL);
566
567 p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
568 if (p != NULL) {
569 struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
570 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
571 /* initialize request message */
572 sntp_initialize_request(sntpmsg);
573 /* send request */
574 udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
575 /* free the pbuf after sending it */
576 pbuf_free(p);
577#if SNTP_MONITOR_SERVER_REACHABILITY
578 /* indicate new packet has been sent */
579 sntp_servers[sntp_current_server].reachability <<= 1;
580#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
581 /* set up receive timeout: try next server or retry on timeout */
582 sys_untimeout(sntp_try_next_server, NULL);
583 sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
584#if SNTP_CHECK_RESPONSE >= 1
585 /* save server address to verify it in sntp_recv */
586 ip_addr_copy(sntp_last_server_address, *server_addr);
587#endif /* SNTP_CHECK_RESPONSE >= 1 */
588 } else {
589 LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
591 /* out of memory: set up a timer to send a retry */
592 sys_untimeout(sntp_request, NULL);
593 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
594 }
595}
596
597#if SNTP_SERVER_DNS
601static void
602sntp_dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg)
603{
606
607 if (ipaddr != NULL) {
608 /* Address resolved, send request */
609 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
610 sntp_servers[sntp_current_server].addr = *ipaddr;
611 sntp_send_request(ipaddr);
612 } else {
613 /* DNS resolving failed -> try another server */
614 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
615 sntp_try_next_server(NULL);
616 }
617}
618#endif /* SNTP_SERVER_DNS */
619
625static void
626sntp_request(void *arg)
627{
628 ip_addr_t sntp_server_address;
629 err_t err;
630
632
633 /* initialize SNTP server address */
634#if SNTP_SERVER_DNS
635 if (sntp_servers[sntp_current_server].name) {
636 /* always resolve the name and rely on dns-internal caching & timeout */
637 ip_addr_set_zero(&sntp_servers[sntp_current_server].addr);
638 err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address,
639 sntp_dns_found, NULL);
640 if (err == ERR_INPROGRESS) {
641 /* DNS request sent, wait for sntp_dns_found being called */
642 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
643 return;
644 } else if (err == ERR_OK) {
645 sntp_servers[sntp_current_server].addr = sntp_server_address;
646 }
647 } else
648#endif /* SNTP_SERVER_DNS */
649 {
650 sntp_server_address = sntp_servers[sntp_current_server].addr;
651 err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK;
652 }
653
654 if (err == ERR_OK) {
655 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n",
656 ipaddr_ntoa(&sntp_server_address)));
657 sntp_send_request(&sntp_server_address);
658 } else {
659 /* address conversion failed, try another server */
660 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
661 sys_untimeout(sntp_try_next_server, NULL);
662 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
663 }
664}
665
671void
672sntp_init(void)
673{
674 /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
675 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_init: SNTP initialised\n"));
676
677#ifdef SNTP_SERVER_ADDRESS
678#if SNTP_SERVER_DNS
679 sntp_setservername(0, SNTP_SERVER_ADDRESS);
680#else
681#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0
682#endif
683#endif /* SNTP_SERVER_ADDRESS */
684
685 if (sntp_pcb == NULL) {
686 sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
687 LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
688 if (sntp_pcb != NULL) {
689 udp_recv(sntp_pcb, sntp_recv, NULL);
690
691 if (sntp_opmode == SNTP_OPMODE_POLL) {
692 SNTP_RESET_RETRY_TIMEOUT();
693#if SNTP_STARTUP_DELAY
694 sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL);
695#else
696 sntp_request(NULL);
697#endif
698 } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) {
699 ip_set_option(sntp_pcb, SOF_BROADCAST);
700 udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT);
701 }
702 }
703 }
704}
705
710void
711sntp_stop(void)
712{
714 if (sntp_pcb != NULL) {
715#if SNTP_MONITOR_SERVER_REACHABILITY
716 u8_t i;
717 for (i = 0; i < SNTP_MAX_SERVERS; i++) {
718 sntp_servers[i].reachability = 0;
719 }
720#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
721 sys_untimeout(sntp_request, NULL);
722 sys_untimeout(sntp_try_next_server, NULL);
723 udp_remove(sntp_pcb);
724 sntp_pcb = NULL;
725 }
726}
727
732u8_t sntp_enabled(void)
733{
734 return (sntp_pcb != NULL) ? 1 : 0;
735}
736
742void
743sntp_setoperatingmode(u8_t operating_mode)
744{
746 LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY);
747 LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL);
748 sntp_opmode = operating_mode;
749}
750
755u8_t
757{
758 return sntp_opmode;
759}
760
761#if SNTP_MONITOR_SERVER_REACHABILITY
768u8_t
769sntp_getreachability(u8_t idx)
770{
771 if (idx < SNTP_MAX_SERVERS) {
772 return sntp_servers[idx].reachability;
773 }
774 return 0;
775}
776#endif /* SNTP_MONITOR_SERVER_REACHABILITY */
777
778#if SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6
783void
784sntp_servermode_dhcp(int set_servers_from_dhcp)
785{
786 u8_t new_mode = set_servers_from_dhcp ? 1 : 0;
788 if (sntp_set_servers_from_dhcp != new_mode) {
789 sntp_set_servers_from_dhcp = new_mode;
790 }
791}
792#endif /* SNTP_GET_SERVERS_FROM_DHCP || SNTP_GET_SERVERS_FROM_DHCPV6 */
793
801void
803{
805 if (idx < SNTP_MAX_SERVERS) {
806 if (server != NULL) {
807 sntp_servers[idx].addr = (*server);
808#if SNTP_SUPPORT_MULTIPLE_SERVERS
809 sntp_servers[idx].kod_received = 0;
810#endif
811 } else {
812 ip_addr_set_zero(&sntp_servers[idx].addr);
813 }
814#if SNTP_SERVER_DNS
815 sntp_servers[idx].name = NULL;
816#endif
817 }
818}
819
820#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP
827void
828dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server)
829{
830 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n",
831 (sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
832 ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num));
833 if (sntp_set_servers_from_dhcp && num) {
834 u8_t i;
835 for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) {
837 ip_addr_copy_from_ip4(addr, server[i]);
839 }
840 for (i = num; i < SNTP_MAX_SERVERS; i++) {
842 }
843 }
844}
845#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
846
847#if LWIP_IPV6_DHCP6 && SNTP_GET_SERVERS_FROM_DHCPV6
854void
855dhcp6_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs)
856{
857 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u NTP server(s) via DHCPv6\n",
858 (sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
859 num_ntp_servers));
860 if (sntp_set_servers_from_dhcp && num_ntp_servers) {
861 u8_t i;
862 for (i = 0; (i < num_ntp_servers) && (i < SNTP_MAX_SERVERS); i++) {
863 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: NTP server %u: %s\n",
864 i, ipaddr_ntoa(&ntp_server_addrs[i])));
865 sntp_setserver(i, &ntp_server_addrs[i]);
866 }
867 for (i = num_ntp_servers; i < SNTP_MAX_SERVERS; i++) {
869 }
870 }
871}
872#endif /* LWIP_DHCPv6 && SNTP_GET_SERVERS_FROM_DHCPV6 */
873
882const ip_addr_t *
884{
885 if (idx < SNTP_MAX_SERVERS) {
886 return &sntp_servers[idx].addr;
887 }
888 return IP_ADDR_ANY;
889}
890
899u8_t
901{
902#if SNTP_SUPPORT_MULTIPLE_SERVERS
903 if (idx < SNTP_MAX_SERVERS) {
904 return sntp_servers[idx].kod_received;
905 }
906#else
908#endif
909 return 0;
910}
911
912#if SNTP_SERVER_DNS
919void
920sntp_setservername(u8_t idx, const char *server)
921{
923 if (idx < SNTP_MAX_SERVERS) {
924 sntp_servers[idx].name = server;
925#if SNTP_SUPPORT_MULTIPLE_SERVERS
926 sntp_servers[idx].kod_received = 0;
927#endif
928 }
929}
930
938const char *
939sntp_getservername(u8_t idx)
940{
941 if (idx < SNTP_MAX_SERVERS) {
942 return sntp_servers[idx].name;
943 }
944 return NULL;
945}
946#endif /* SNTP_SERVER_DNS */
947
948#endif /* LWIP_UDP */
char * hostname
Definition: ftp.c:88
#define lwip_ntohl(x)
Definition: def.h:89
#define lwip_htonl(x)
Definition: def.h:88
#define NULL
Definition: types.h:112
unsigned int idx
Definition: utils.c:41
#define frac(x)
Definition: texture.c:364
USHORT port
Definition: uri.c:228
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
__kernel_time_t time_t
Definition: linux.h:252
#define PACK_STRUCT_STRUCT
Definition: cc.h:42
#define U16_F
Definition: cc.h:19
#define U32_F
Definition: cc.h:22
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
#define ip_set_option(pcb, opt)
Definition: ip.h:230
#define SOF_BROADCAST
Definition: ip.h:112
GLenum mode
Definition: glext.h:6217
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLint GLint * precision
Definition: glext.h:7539
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int32_t s32_t
Definition: arch.h:130
#define PACK_STRUCT_END
Definition: arch.h:316
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
#define PACK_STRUCT_BEGIN
Definition: arch.h:307
uint16_t u16_t
Definition: arch.h:127
#define PACK_STRUCT_FLD_8(x)
Definition: arch.h:347
#define PACK_STRUCT_FIELD(x)
Definition: arch.h:338
s8_t err_t
Definition: err.h:96
@ ERR_INPROGRESS
Definition: err.h:65
@ ERR_OK
Definition: err.h:55
@ ERR_ARG
Definition: err.h:88
@ ERR_TIMEOUT
Definition: err.h:61
#define IP_ANY_TYPE
Definition: ip_addr.h:461
@ IPADDR_TYPE_ANY
Definition: ip_addr.h:60
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
Definition: pbuf.c:1402
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1058
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_TRANSPORT
Definition: pbuf.h:93
#define SNTP_RECV_TIMEOUT
Definition: sntp_opts.h:164
#define SNTP_MAX_SERVERS
Definition: sntp_opts.h:61
#define SNTP_RETRY_TIMEOUT
Definition: sntp_opts.h:189
#define SNTP_UPDATE_DELAY
Definition: sntp_opts.h:171
#define SNTP_PORT
Definition: sntp_opts.h:93
#define SNTP_STARTUP_DELAY_FUNC
Definition: sntp_opts.h:156
#define SNTP_SERVER_DNS
Definition: sntp_opts.h:81
#define SNTP_RETRY_TIMEOUT_MAX
Definition: sntp_opts.h:194
#define ip_addr_isany(ipaddr)
Definition: ip_addr.h:377
#define ip_addr_eq(addr1, addr2)
Definition: ip_addr.h:374
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:360
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
#define ip_addr_set_zero(ipaddr)
Definition: ip_addr.h:365
#define ip_addr_isany_val(ipaddr)
Definition: ip_addr.h:378
#define ipaddr_ntoa(ipaddr)
Definition: ip_addr.h:385
__u16 ctime
Definition: mkdosfs.c:4
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
#define SNTP_OPMODE_POLL
Definition: sntp.h:49
u8_t sntp_enabled(void)
#define SNTP_OPMODE_LISTENONLY
Definition: sntp.h:50
u8_t sntp_getkodreceived(u8_t idx)
void sntp_stop(void)
void sntp_init(void)
void sntp_setoperatingmode(u8_t operating_mode)
const ip_addr_t * sntp_getserver(u8_t idx)
void sntp_setserver(u8_t idx, const ip_addr_t *addr)
u8_t sntp_getoperatingmode(void)
#define sntp_servermode_dhcp(x)
Definition: sntp.h:74
Definition: name.c:39
Definition: pbuf.h:186
static rfbScreenInfoPtr server
Definition: vnc.c:74
#define poll
Definition: wintirpc.h:59