7 * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
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.
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
32 * This file is part of the lwIP TCP/IP stack.
34 * Author: Frédéric Bernon, Simon Goldschmidt
42 * This is simple "SNTP" client for the lwIP raw API.
43 * It is a minimal implementation of SNTPv4 as specified in RFC 4330.
45 * For a list of some public NTP servers, see this link :
46 * http://support.ntp.org/bin/view/Servers/NTPPoolServers
49 * - set/change servers at runtime
50 * - complete SNTP_CHECK_RESPONSE checks 3 and 4
53 #include "lwip/apps/sntp.h"
56 #include "lwip/timeouts.h"
59 #include "lwip/ip_addr.h"
60 #include "lwip/pbuf.h"
61 #include "lwip/dhcp.h"
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 */
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)!"
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
84 #define SNTP_SET_SYSTEM_TIME_US(sec, us)
85 #define SNTP_CALC_TIME_US 0
86 #define SNTP_RECEIVE_TIME_SIZE 1
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)
97 #define SNTP_ERR_KOD 1
99 /* SNTP protocol defines */
100 #define SNTP_MSG_LEN 48
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) */
109 #define SNTP_VERSION_MASK 0x38
110 #define SNTP_VERSION (4/* NTP Version 4*/<<3)
112 #define SNTP_MODE_MASK 0x07
113 #define SNTP_MODE_CLIENT 0x03
114 #define SNTP_MODE_SERVER 0x04
115 #define SNTP_MODE_BROADCAST 0x05
117 #define SNTP_OFFSET_STRATUM 1
118 #define SNTP_STRATUM_KOD 0x00
120 #define SNTP_OFFSET_ORIGINATE_TIME 24
121 #define SNTP_OFFSET_RECEIVE_TIME 32
122 #define SNTP_OFFSET_TRANSMIT_TIME 40
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)
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.
137 #ifdef PACK_STRUCT_USE_INCLUDES
138 # include "arch/bpstruct.h"
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
;
155 #ifdef PACK_STRUCT_USE_INCLUDES
156 # include "arch/epstruct.h"
159 /* function prototypes */
160 static void sntp_request(void *arg
);
162 /** The operating mode */
163 static u8_t sntp_opmode
;
165 /** The UDP pcb used by the SNTP client */
166 static struct udp_pcb
* sntp_pcb
;
167 /** Names/Addresses of servers */
171 #endif /* SNTP_SERVER_DNS */
174 static struct sntp_server sntp_servers
[SNTP_MAX_SERVERS
];
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 */
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 */
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 */
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 */
207 * SNTP processing of received timestamp
210 sntp_process(u32_t
*receive_timestamp
)
212 /* convert SNTP time (1900-based) to unix GMT time (1970-based)
213 * if MSB is 0, SNTP time is 2036-based!
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
);
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
));
226 #else /* SNTP_CALC_TIME_US */
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
);
237 * Initialize request struct to be sent to server.
240 sntp_initialize_request(struct sntp_msg
*req
)
242 memset(req
, 0, SNTP_MSG_LEN
);
243 req
->li_vn_mode
= SNTP_LI_NO_WARNING
| SNTP_VERSION
| SNTP_MODE_CLIENT
;
245 #if SNTP_CHECK_RESPONSE >= 2
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];
256 #endif /* SNTP_CHECK_RESPONSE >= 2 */
260 * Retry: send a new request (and increase retry timeout).
262 * @param arg is unused (only necessary to conform to sys_timeout)
265 sntp_retry(void* arg
)
267 LWIP_UNUSED_ARG(arg
);
269 LWIP_DEBUGF(SNTP_DEBUG_STATE
, ("sntp_retry: Next request will be sent in %"U32_F
" ms\n",
270 sntp_retry_timeout
));
272 /* set up a timer to send a retry and increase the retry delay */
273 sys_timeout(sntp_retry_timeout
, sntp_request
, NULL
);
275 #if SNTP_RETRY_TIMEOUT_EXP
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
;
286 #endif /* SNTP_RETRY_TIMEOUT_EXP */
289 #if SNTP_SUPPORT_MULTIPLE_SERVERS
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)
296 * @param arg is unused (only necessary to conform to sys_timeout)
299 sntp_try_next_server(void* arg
)
302 LWIP_UNUSED_ARG(arg
);
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;
310 if (!ip_addr_isany(&sntp_servers
[sntp_current_server
].addr
)
312 || (sntp_servers
[sntp_current_server
].name
!= NULL
)
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 */
324 /* no other valid server found */
325 sntp_current_server
= old_server
;
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 */
333 /** UDP recv callback for the sntp pcb */
335 sntp_recv(void *arg
, struct udp_pcb
* pcb
, struct pbuf
*p
, const ip_addr_t
*addr
, u16_t port
)
339 u32_t receive_timestamp
[SNTP_RECEIVE_TIME_SIZE
];
342 LWIP_UNUSED_ARG(arg
);
343 LWIP_UNUSED_ARG(pcb
);
345 /* packet received: stop retry timeout */
346 sys_untimeout(sntp_try_next_server
, NULL
);
347 sys_untimeout(sntp_request
, NULL
);
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
)) &&
354 #else /* SNTP_CHECK_RESPONSE >= 1 */
355 LWIP_UNUSED_ARG(addr
);
356 LWIP_UNUSED_ARG(port
);
357 #endif /* SNTP_CHECK_RESPONSE >= 1 */
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. */
370 LWIP_DEBUGF(SNTP_DEBUG_STATE
, ("sntp_recv: Received Kiss-of-Death\n"));
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]))
379 LWIP_DEBUGF(SNTP_DEBUG_WARN
, ("sntp_recv: Invalid originate timestamp in response\n"));
381 #endif /* SNTP_CHECK_RESPONSE >= 2 */
382 /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
386 pbuf_copy_partial(p
, &receive_timestamp
, SNTP_RECEIVE_TIME_SIZE
* 4, SNTP_OFFSET_TRANSMIT_TIME
);
390 LWIP_DEBUGF(SNTP_DEBUG_WARN
, ("sntp_recv: Invalid mode in response: %"U16_F
"\n", (u16_t
)mode
));
391 /* wait for correct response */
395 LWIP_DEBUGF(SNTP_DEBUG_WARN
, ("sntp_recv: Invalid packet length: %"U16_F
"\n", p
->tot_len
));
398 #if SNTP_CHECK_RESPONSE >= 1
400 /* packet from wrong remote address or port, wait for correct response */
403 #endif /* SNTP_CHECK_RESPONSE >= 1 */
406 sntp_process(receive_timestamp
);
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();
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
));
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
);
424 /* another error, try the same server again */
431 /** Actually send an sntp request to a server.
433 * @param server_addr resolved IP address of the SNTP server
436 sntp_send_request(const ip_addr_t
*server_addr
)
439 p
= pbuf_alloc(PBUF_TRANSPORT
, SNTP_MSG_LEN
, PBUF_RAM
);
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
);
446 udp_sendto(sntp_pcb
, p
, server_addr
, SNTP_PORT
);
447 /* free the pbuf after sending it */
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 */
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
);
465 * DNS found callback when using DNS names as server address.
468 sntp_dns_found(const char* hostname
, const ip_addr_t
*ipaddr
, void *arg
)
470 LWIP_UNUSED_ARG(hostname
);
471 LWIP_UNUSED_ARG(arg
);
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
);
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
);
483 #endif /* SNTP_SERVER_DNS */
486 * Send out an sntp request.
488 * @param arg is unused (only necessary to conform to sys_timeout)
491 sntp_request(void *arg
)
493 ip_addr_t sntp_server_address
;
496 LWIP_UNUSED_ARG(arg
);
498 /* initialize SNTP server address */
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"));
509 } else if (err
== ERR_OK
) {
510 sntp_servers
[sntp_current_server
].addr
= sntp_server_address
;
513 #endif /* SNTP_SERVER_DNS */
515 sntp_server_address
= sntp_servers
[sntp_current_server
].addr
;
516 err
= (ip_addr_isany_val(sntp_server_address
)) ? ERR_ARG
: 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
);
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
);
532 * Initialize this module.
533 * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC).
538 #ifdef SNTP_SERVER_ADDRESS
540 sntp_setservername(0, SNTP_SERVER_ADDRESS
);
542 #error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0
544 #endif /* SNTP_SERVER_ADDRESS */
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
);
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
);
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
);
574 if (sntp_pcb
!= NULL
) {
575 sys_untimeout(sntp_request
, NULL
);
576 sys_untimeout(sntp_try_next_server
, NULL
);
577 udp_remove(sntp_pcb
);
586 u8_t
sntp_enabled(void)
588 return (sntp_pcb
!= NULL
)? 1 : 0;
593 * Sets the operating mode.
594 * @param operating_mode one of the available operating modes
597 sntp_setoperatingmode(u8_t operating_mode
)
599 LWIP_ASSERT("Invalid operating mode", operating_mode
<= SNTP_OPMODE_LISTENONLY
);
600 LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb
== NULL
);
601 sntp_opmode
= operating_mode
;
606 * Gets the operating mode.
609 sntp_getoperatingmode(void)
614 #if SNTP_GET_SERVERS_FROM_DHCP
616 * Config SNTP server handling by IP address, name, or DHCP; clear table
617 * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp
620 sntp_servermode_dhcp(int set_servers_from_dhcp
)
622 u8_t new_mode
= set_servers_from_dhcp
? 1 : 0;
623 if (sntp_set_servers_from_dhcp
!= new_mode
) {
624 sntp_set_servers_from_dhcp
= new_mode
;
627 #endif /* SNTP_GET_SERVERS_FROM_DHCP */
631 * Initialize one of the NTP servers by IP address
633 * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS
634 * @param server IP address of the NTP server to set
637 sntp_setserver(u8_t idx
, const ip_addr_t
*server
)
639 if (idx
< SNTP_MAX_SERVERS
) {
640 if (server
!= NULL
) {
641 sntp_servers
[idx
].addr
= (*server
);
643 ip_addr_set_zero(&sntp_servers
[idx
].addr
);
646 sntp_servers
[idx
].name
= NULL
;
651 #if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP
653 * Initialize one of the NTP servers by IP address, required by DHCP
655 * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
656 * @param dnsserver IP address of the NTP server to set
659 dhcp_set_ntp_servers(u8_t num
, const ip4_addr_t
*server
)
661 LWIP_DEBUGF(SNTP_DEBUG_TRACE
, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n",
662 (sntp_set_servers_from_dhcp
? "Got" : "Rejected"),
663 ip4_addr1(server
), ip4_addr2(server
), ip4_addr3(server
), ip4_addr4(server
), num
));
664 if (sntp_set_servers_from_dhcp
&& num
) {
666 for (i
= 0; (i
< num
) && (i
< SNTP_MAX_SERVERS
); i
++) {
668 ip_addr_copy_from_ip4(addr
, server
[i
]);
669 sntp_setserver(i
, &addr
);
671 for (i
= num
; i
< SNTP_MAX_SERVERS
; i
++) {
672 sntp_setserver(i
, NULL
);
676 #endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */
680 * Obtain one of the currently configured by IP address (or DHCP) NTP servers
682 * @param idx the index of the NTP server
683 * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP
684 * server has not been configured by address (or at all).
687 sntp_getserver(u8_t idx
)
689 if (idx
< SNTP_MAX_SERVERS
) {
690 return &sntp_servers
[idx
].addr
;
697 * Initialize one of the NTP servers by name
699 * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS
700 * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time
703 sntp_setservername(u8_t idx
, char *server
)
705 if (idx
< SNTP_MAX_SERVERS
) {
706 sntp_servers
[idx
].name
= server
;
711 * Obtain one of the currently configured by name NTP servers.
713 * @param numdns the index of the NTP server
714 * @return IP address of the indexed NTP server or NULL if the NTP
715 * server has not been configured by name (or at all)
718 sntp_getservername(u8_t idx
)
720 if (idx
< SNTP_MAX_SERVERS
) {
721 return sntp_servers
[idx
].name
;
725 #endif /* SNTP_SERVER_DNS */
727 #endif /* LWIP_UDP */