1 /**
2 * @file
3 * SNTP client module
4 */
5
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
38 /**
39 * @defgroup sntp SNTP
40 * @ingroup apps
41 *
42 * This is simple "SNTP" client for the lwIP raw API.
43 * It is a minimal implementation of SNTPv4 as specified in RFC 4330.
44 *
45 * For a list of some public NTP servers, see this link :
46 * http://support.ntp.org/bin/view/Servers/NTPPoolServers
47 *
48 * @todo:
49 * - set/change servers at runtime
50 * - complete SNTP_CHECK_RESPONSE checks 3 and 4
51 */
52
53 #include "lwip/apps/sntp.h"
54
55 #include "lwip/opt.h"
56 #include "lwip/timeouts.h"
57 #include "lwip/udp.h"
58 #include "lwip/dns.h"
59 #include "lwip/ip_addr.h"
60 #include "lwip/pbuf.h"
61 #include "lwip/dhcp.h"
62
63 #include <string.h>
64 #include <time.h>
65
66 #if LWIP_UDP
67
68 /* Handle support for more than one server via SNTP_MAX_SERVERS */
69 #if SNTP_MAX_SERVERS > 1
70 #define SNTP_SUPPORT_MULTIPLE_SERVERS 1
71 #else /* NTP_MAX_SERVERS > 1 */
72 #define SNTP_SUPPORT_MULTIPLE_SERVERS 0
73 #endif /* NTP_MAX_SERVERS > 1 */
74
75 #if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK)
76 #error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!"
77 #endif
78
79 /* Configure behaviour depending on microsecond or second precision */
80 #ifdef SNTP_SET_SYSTEM_TIME_US
81 #define SNTP_CALC_TIME_US 1
82 #define SNTP_RECEIVE_TIME_SIZE 2
83 #else
84 #define SNTP_SET_SYSTEM_TIME_US(sec, us)
85 #define SNTP_CALC_TIME_US 0
86 #define SNTP_RECEIVE_TIME_SIZE 1
87 #endif
88
89
90 /* the various debug levels for this file */
91 #define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE)
92 #define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE)
93 #define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
94 #define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
95 #define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
96
97 #define SNTP_ERR_KOD 1
98
99 /* SNTP protocol defines */
100 #define SNTP_MSG_LEN 48
101
102 #define SNTP_OFFSET_LI_VN_MODE 0
103 #define SNTP_LI_MASK 0xC0
104 #define SNTP_LI_NO_WARNING 0x00
105 #define SNTP_LI_LAST_MINUTE_61_SEC 0x01
106 #define SNTP_LI_LAST_MINUTE_59_SEC 0x02
107 #define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */
108
109 #define SNTP_VERSION_MASK 0x38
110 #define SNTP_VERSION (4/* NTP Version 4*/<<3)
111
112 #define SNTP_MODE_MASK 0x07
113 #define SNTP_MODE_CLIENT 0x03
114 #define SNTP_MODE_SERVER 0x04
115 #define SNTP_MODE_BROADCAST 0x05
116
117 #define SNTP_OFFSET_STRATUM 1
118 #define SNTP_STRATUM_KOD 0x00
119
120 #define SNTP_OFFSET_ORIGINATE_TIME 24
121 #define SNTP_OFFSET_RECEIVE_TIME 32
122 #define SNTP_OFFSET_TRANSMIT_TIME 40
123
124 /* number of seconds between 1900 and 1970 (MSB=1)*/
125 #define DIFF_SEC_1900_1970 (2208988800UL)
126 /* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */
127 #define DIFF_SEC_1970_2036 (2085978496UL)
128
129 /**
130 * SNTP packet format (without optional fields)
131 * Timestamps are coded as 64 bits:
132 * - 32 bits seconds since Jan 01, 1970, 00:00
133 * - 32 bits seconds fraction (0-padded)
134 * For future use, if the MSB in the seconds part is set, seconds are based
135 * on Feb 07, 2036, 06:28:16.
136 */
137 #ifdef PACK_STRUCT_USE_INCLUDES
138 # include "arch/bpstruct.h"
139 #endif
140 PACK_STRUCT_BEGIN
141 struct sntp_msg {
142 PACK_STRUCT_FLD_8(u8_t li_vn_mode);
143 PACK_STRUCT_FLD_8(u8_t stratum);
144 PACK_STRUCT_FLD_8(u8_t poll);
145 PACK_STRUCT_FLD_8(u8_t precision);
146 PACK_STRUCT_FIELD(u32_t root_delay);
147 PACK_STRUCT_FIELD(u32_t root_dispersion);
148 PACK_STRUCT_FIELD(u32_t reference_identifier);
149 PACK_STRUCT_FIELD(u32_t reference_timestamp[2]);
150 PACK_STRUCT_FIELD(u32_t originate_timestamp[2]);
151 PACK_STRUCT_FIELD(u32_t receive_timestamp[2]);
152 PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]);
153 } PACK_STRUCT_STRUCT;
154 PACK_STRUCT_END
155 #ifdef PACK_STRUCT_USE_INCLUDES
156 # include "arch/epstruct.h"
157 #endif
158
159 /* function prototypes */
160 static void sntp_request(void *arg);
161
162 /** The operating mode */
163 static u8_t sntp_opmode;
164
165 /** The UDP pcb used by the SNTP client */
166 static struct udp_pcb* sntp_pcb;
167 /** Names/Addresses of servers */
168 struct sntp_server {
169 #if SNTP_SERVER_DNS
170 char* name;
171 #endif /* SNTP_SERVER_DNS */
172 ip_addr_t addr;
173 };
174 static struct sntp_server sntp_servers[SNTP_MAX_SERVERS];
175
176 #if SNTP_GET_SERVERS_FROM_DHCP
177 static u8_t sntp_set_servers_from_dhcp;
178 #endif /* SNTP_GET_SERVERS_FROM_DHCP */
179 #if SNTP_SUPPORT_MULTIPLE_SERVERS
180 /** The currently used server (initialized to 0) */
181 static u8_t sntp_current_server;
182 #else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
183 #define sntp_current_server 0
184 #endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
185
186 #if SNTP_RETRY_TIMEOUT_EXP
187 #define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
188 /** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */
189 static u32_t sntp_retry_timeout;
190 #else /* SNTP_RETRY_TIMEOUT_EXP */
191 #define SNTP_RESET_RETRY_TIMEOUT()
192 #define sntp_retry_timeout SNTP_RETRY_TIMEOUT
193 #endif /* SNTP_RETRY_TIMEOUT_EXP */
194
195 #if SNTP_CHECK_RESPONSE >= 1
196 /** Saves the last server address to compare with response */
197 static ip_addr_t sntp_last_server_address;
198 #endif /* SNTP_CHECK_RESPONSE >= 1 */
199
200 #if SNTP_CHECK_RESPONSE >= 2
201 /** Saves the last timestamp sent (which is sent back by the server)
202 * to compare against in response */
203 static u32_t sntp_last_timestamp_sent[2];
204 #endif /* SNTP_CHECK_RESPONSE >= 2 */
205
206 /**
207 * SNTP processing of received timestamp
208 */
209 static void
sntp_process(u32_t * receive_timestamp)210 sntp_process(u32_t *receive_timestamp)
211 {
212 /* convert SNTP time (1900-based) to unix GMT time (1970-based)
213 * if MSB is 0, SNTP time is 2036-based!
214 */
215 u32_t rx_secs = lwip_ntohl(receive_timestamp[0]);
216 int is_1900_based = ((rx_secs & 0x80000000) != 0);
217 u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036);
218 time_t tim = t;
219
220 #if SNTP_CALC_TIME_US
221 u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295;
222 SNTP_SET_SYSTEM_TIME_US(t, us);
223 /* display local time from GMT time */
224 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us));
225
226 #else /* SNTP_CALC_TIME_US */
227
228 /* change system time and/or the update the RTC clock */
229 SNTP_SET_SYSTEM_TIME(t);
230 /* display local time from GMT time */
231 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim)));
232 #endif /* SNTP_CALC_TIME_US */
233 LWIP_UNUSED_ARG(tim);
234 }
235
236 /**
237 * Initialize request struct to be sent to server.
238 */
239 static void
sntp_initialize_request(struct sntp_msg * req)240 sntp_initialize_request(struct sntp_msg *req)
241 {
242 memset(req, 0, SNTP_MSG_LEN);
243 req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
244
245 #if SNTP_CHECK_RESPONSE >= 2
246 {
247 u32_t sntp_time_sec, sntp_time_us;
248 /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
249 SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
250 sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970);
251 req->transmit_timestamp[0] = sntp_last_timestamp_sent[0];
252 /* we send/save us instead of fraction to be faster... */
253 sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us);
254 req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
255 }
256 #endif /* SNTP_CHECK_RESPONSE >= 2 */
257 }
258
259 /**
260 * Retry: send a new request (and increase retry timeout).
261 *
262 * @param arg is unused (only necessary to conform to sys_timeout)
263 */
264 static void
sntp_retry(void * arg)265 sntp_retry(void* arg)
266 {
267 LWIP_UNUSED_ARG(arg);
268
269 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
270 sntp_retry_timeout));
271
272 /* set up a timer to send a retry and increase the retry delay */
273 sys_timeout(sntp_retry_timeout, sntp_request, NULL);
274
275 #if SNTP_RETRY_TIMEOUT_EXP
276 {
277 u32_t new_retry_timeout;
278 /* increase the timeout for next retry */
279 new_retry_timeout = sntp_retry_timeout << 1;
280 /* limit to maximum timeout and prevent overflow */
281 if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
282 (new_retry_timeout > sntp_retry_timeout)) {
283 sntp_retry_timeout = new_retry_timeout;
284 }
285 }
286 #endif /* SNTP_RETRY_TIMEOUT_EXP */
287 }
288
289 #if SNTP_SUPPORT_MULTIPLE_SERVERS
290 /**
291 * If Kiss-of-Death is received (or another packet parsing error),
292 * try the next server or retry the current server and increase the retry
293 * timeout if only one server is available.
294 * (implicitly, SNTP_MAX_SERVERS > 1)
295 *
296 * @param arg is unused (only necessary to conform to sys_timeout)
297 */
298 static void
sntp_try_next_server(void * arg)299 sntp_try_next_server(void* arg)
300 {
301 u8_t old_server, i;
302 LWIP_UNUSED_ARG(arg);
303
304 old_server = sntp_current_server;
305 for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) {
306 sntp_current_server++;
307 if (sntp_current_server >= SNTP_MAX_SERVERS) {
308 sntp_current_server = 0;
309 }
310 if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr)
311 #if SNTP_SERVER_DNS
312 || (sntp_servers[sntp_current_server].name != NULL)
313 #endif
314 ) {
315 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
316 (u16_t)sntp_current_server));
317 /* new server: reset retry timeout */
318 SNTP_RESET_RETRY_TIMEOUT();
319 /* instantly send a request to the next server */
320 sntp_request(NULL);
321 return;
322 }
323 }
324 /* no other valid server found */
325 sntp_current_server = old_server;
326 sntp_retry(NULL);
327 }
328 #else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
329 /* Always retry on error if only one server is supported */
330 #define sntp_try_next_server sntp_retry
331 #endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
332
333 /** UDP recv callback for the sntp pcb */
334 static void
sntp_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)335 sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
336 {
337 u8_t mode;
338 u8_t stratum;
339 u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
340 err_t err;
341
342 LWIP_UNUSED_ARG(arg);
343 LWIP_UNUSED_ARG(pcb);
344
345 /* packet received: stop retry timeout */
346 sys_untimeout(sntp_try_next_server, NULL);
347 sys_untimeout(sntp_request, NULL);
348
349 err = ERR_ARG;
350 #if SNTP_CHECK_RESPONSE >= 1
351 /* check server address and port */
352 if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) &&
353 (port == SNTP_PORT))
354 #else /* SNTP_CHECK_RESPONSE >= 1 */
355 LWIP_UNUSED_ARG(addr);
356 LWIP_UNUSED_ARG(port);
357 #endif /* SNTP_CHECK_RESPONSE >= 1 */
358 {
359 /* process the response */
360 if (p->tot_len == SNTP_MSG_LEN) {
361 pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
362 mode &= SNTP_MODE_MASK;
363 /* if this is a SNTP response... */
364 if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) ||
365 ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) {
366 pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
367 if (stratum == SNTP_STRATUM_KOD) {
368 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
369 err = SNTP_ERR_KOD;
370 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
371 } else {
372 #if SNTP_CHECK_RESPONSE >= 2
373 /* check originate_timetamp against sntp_last_timestamp_sent */
374 u32_t originate_timestamp[2];
375 pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
376 if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
377 (originate_timestamp[1] != sntp_last_timestamp_sent[1]))
378 {
379 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
380 } else
381 #endif /* SNTP_CHECK_RESPONSE >= 2 */
382 /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
383 {
384 /* correct answer */
385 err = ERR_OK;
386 pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME);
387 }
388 }
389 } else {
390 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
391 /* wait for correct response */
392 err = ERR_TIMEOUT;
393 }
394 } else {
395 LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
396 }
397 }
398 #if SNTP_CHECK_RESPONSE >= 1
399 else {
400 /* packet from wrong remote address or port, wait for correct response */
401 err = ERR_TIMEOUT;
402 }
403 #endif /* SNTP_CHECK_RESPONSE >= 1 */
404 pbuf_free(p);
405 if (err == ERR_OK) {
406 sntp_process(receive_timestamp);
407
408 /* Set up timeout for next request (only if poll response was received)*/
409 if (sntp_opmode == SNTP_OPMODE_POLL) {
410 /* Correct response, reset retry timeout */
411 SNTP_RESET_RETRY_TIMEOUT();
412
413 sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
414 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
415 (u32_t)SNTP_UPDATE_DELAY));
416 }
417 } else if (err != ERR_TIMEOUT) {
418 /* Errors are only processed in case of an explicit poll response */
419 if (sntp_opmode == SNTP_OPMODE_POLL) {
420 if (err == SNTP_ERR_KOD) {
421 /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
422 sntp_try_next_server(NULL);
423 } else {
424 /* another error, try the same server again */
425 sntp_retry(NULL);
426 }
427 }
428 }
429 }
430
431 /** Actually send an sntp request to a server.
432 *
433 * @param server_addr resolved IP address of the SNTP server
434 */
435 static void
sntp_send_request(const ip_addr_t * server_addr)436 sntp_send_request(const ip_addr_t *server_addr)
437 {
438 struct pbuf* p;
439 p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
440 if (p != NULL) {
441 struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
442 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
443 /* initialize request message */
444 sntp_initialize_request(sntpmsg);
445 /* send request */
446 udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
447 /* free the pbuf after sending it */
448 pbuf_free(p);
449 /* set up receive timeout: try next server or retry on timeout */
450 sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
451 #if SNTP_CHECK_RESPONSE >= 1
452 /* save server address to verify it in sntp_recv */
453 ip_addr_set(&sntp_last_server_address, server_addr);
454 #endif /* SNTP_CHECK_RESPONSE >= 1 */
455 } else {
456 LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
457 (u32_t)SNTP_RETRY_TIMEOUT));
458 /* out of memory: set up a timer to send a retry */
459 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
460 }
461 }
462
463 #if SNTP_SERVER_DNS
464 /**
465 * DNS found callback when using DNS names as server address.
466 */
467 static void
sntp_dns_found(const char * hostname,const ip_addr_t * ipaddr,void * arg)468 sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
469 {
470 LWIP_UNUSED_ARG(hostname);
471 LWIP_UNUSED_ARG(arg);
472
473 if (ipaddr != NULL) {
474 /* Address resolved, send request */
475 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
476 sntp_send_request(ipaddr);
477 } else {
478 /* DNS resolving failed -> try another server */
479 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
480 sntp_try_next_server(NULL);
481 }
482 }
483 #endif /* SNTP_SERVER_DNS */
484
485 /**
486 * Send out an sntp request.
487 *
488 * @param arg is unused (only necessary to conform to sys_timeout)
489 */
490 static void
sntp_request(void * arg)491 sntp_request(void *arg)
492 {
493 ip_addr_t sntp_server_address;
494 err_t err;
495
496 LWIP_UNUSED_ARG(arg);
497
498 /* initialize SNTP server address */
499 #if SNTP_SERVER_DNS
500 if (sntp_servers[sntp_current_server].name) {
501 /* always resolve the name and rely on dns-internal caching & timeout */
502 ip_addr_set_zero(&sntp_servers[sntp_current_server].addr);
503 err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address,
504 sntp_dns_found, NULL);
505 if (err == ERR_INPROGRESS) {
506 /* DNS request sent, wait for sntp_dns_found being called */
507 LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
508 return;
509 } else if (err == ERR_OK) {
510 sntp_servers[sntp_current_server].addr = sntp_server_address;
511 }
512 } else
513 #endif /* SNTP_SERVER_DNS */
514 {
515 sntp_server_address = sntp_servers[sntp_current_server].addr;
516 err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK;
517 }
518
519 if (err == ERR_OK) {
520 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n",
521 ipaddr_ntoa(&sntp_server_address)));
522 sntp_send_request(&sntp_server_address);
523 } else {
524 /* address conversion failed, try another server */
525 LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
526 sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
527 }
528 }
529
530 /**
531 * @ingroup sntp
532 * Initialize this module.
533 * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC).
534 */
535 void
sntp_init(void)536 sntp_init(void)
537 {
538 #ifdef SNTP_SERVER_ADDRESS
539 #if SNTP_SERVER_DNS
540 sntp_setservername(0, SNTP_SERVER_ADDRESS);
541 #else
542 #error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0
543 #endif
544 #endif /* SNTP_SERVER_ADDRESS */
545
546 if (sntp_pcb == NULL) {
547 sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
548 LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
549 if (sntp_pcb != NULL) {
550 udp_recv(sntp_pcb, sntp_recv, NULL);
551
552 if (sntp_opmode == SNTP_OPMODE_POLL) {
553 SNTP_RESET_RETRY_TIMEOUT();
554 #if SNTP_STARTUP_DELAY
555 sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL);
556 #else
557 sntp_request(NULL);
558 #endif
559 } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) {
560 ip_set_option(sntp_pcb, SOF_BROADCAST);
561 udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT);
562 }
563 }
564 }
565 }
566
567 /**
568 * @ingroup sntp
569 * Stop this module.
570 */
571 void
sntp_stop(void)572 sntp_stop(void)
573 {
574 if (sntp_pcb != NULL) {
575 sys_untimeout(sntp_request, NULL);
576 udp_remove(sntp_pcb);
577 sntp_pcb = NULL;
578 }
579 }
580
581 /**
582 * @ingroup sntp
583 * Get enabled state.
584 */
sntp_enabled(void)585 u8_t sntp_enabled(void)
586 {
587 return (sntp_pcb != NULL)? 1 : 0;
588 }
589
590 /**
591 * @ingroup sntp
592 * Sets the operating mode.
593 * @param operating_mode one of the available operating modes
594 */
595 void
sntp_setoperatingmode(u8_t operating_mode)596 sntp_setoperatingmode(u8_t operating_mode)
597 {
598 LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY);
599 LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL);
600 sntp_opmode = operating_mode;
601 }
602
603 /**
604 * @ingroup sntp
605 * Gets the operating mode.
606 */
607 u8_t
sntp_getoperatingmode(void)608 sntp_getoperatingmode(void)
609 {
610 return sntp_opmode;
611 }
612
613 #if SNTP_GET_SERVERS_FROM_DHCP
614 /**
615 * Config SNTP server handling by IP address, name, or DHCP; clear table
616 * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp
617 */
618 void
sntp_servermode_dhcp(int set_servers_from_dhcp)619 sntp_servermode_dhcp(int set_servers_from_dhcp)
620 {
621 u8_t new_mode = set_servers_from_dhcp ? 1 : 0;
622 if (sntp_set_servers_from_dhcp != new_mode) {
623 sntp_set_servers_from_dhcp = new_mode;
624 }
625 }
626 #endif /* SNTP_GET_SERVERS_FROM_DHCP */
627
628 /**
629 * @ingroup sntp
630 * Initialize one of the NTP servers by IP address
631 *
632 * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS
633 * @param server IP address of the NTP server to set
634 */
635 void
sntp_setserver(u8_t idx,const ip_addr_t * server)636 sntp_setserver(u8_t idx, const ip_addr_t *server)
637 {
638 if (idx < SNTP_MAX_SERVERS) {
639 if (server != NULL) {
640 sntp_servers[idx].addr = (*server);
641 } else {
642 ip_addr_set_zero(&sntp_servers[idx].addr);
643 }
644 #if SNTP_SERVER_DNS
645 sntp_servers[idx].name = NULL;
646 #endif
647 }
648 }
649
650 #if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP
651 /**
652 * Initialize one of the NTP servers by IP address, required by DHCP
653 *
654 * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
655 * @param dnsserver IP address of the NTP server to set
656 */
657 void
dhcp_set_ntp_servers(u8_t num,const ip4_addr_t * server)658 dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server)
659 {
660 LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n",
661 (sntp_set_servers_from_dhcp ? "Got" : "Rejected"),
662 ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num));
663 if (sntp_set_servers_from_dhcp && num) {
664 u8_t i;
665 for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) {
666 ip_addr_t addr;
667 ip_addr_copy_from_ip4(addr, server[i]);
668 sntp_setserver(i, &addr);
669 }
670 for (i = num; i < SNTP_MAX_SERVERS; i++) {
671 sntp_setserver(i, NULL);
672 }
673 }
674 }
675 #endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
676
677 /**
678 * @ingroup sntp
679 * Obtain one of the currently configured by IP address (or DHCP) NTP servers
680 *
681 * @param idx the index of the NTP server
682 * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP
683 * server has not been configured by address (or at all).
684 */
685 const ip_addr_t*
sntp_getserver(u8_t idx)686 sntp_getserver(u8_t idx)
687 {
688 if (idx < SNTP_MAX_SERVERS) {
689 return &sntp_servers[idx].addr;
690 }
691 return IP4_ADDR_ANY;
692 }
693
694 #if SNTP_SERVER_DNS
695 /**
696 * Initialize one of the NTP servers by name
697 *
698 * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
699 * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time
700 */
701 void
sntp_setservername(u8_t idx,char * server)702 sntp_setservername(u8_t idx, char *server)
703 {
704 if (idx < SNTP_MAX_SERVERS) {
705 sntp_servers[idx].name = server;
706 }
707 }
708
709 /**
710 * Obtain one of the currently configured by name NTP servers.
711 *
712 * @param numdns the index of the NTP server
713 * @return IP address of the indexed NTP server or NULL if the NTP
714 * server has not been configured by name (or at all)
715 */
716 char *
sntp_getservername(u8_t idx)717 sntp_getservername(u8_t idx)
718 {
719 if (idx < SNTP_MAX_SERVERS) {
720 return sntp_servers[idx].name;
721 }
722 return NULL;
723 }
724 #endif /* SNTP_SERVER_DNS */
725
726 #endif /* LWIP_UDP */
727