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 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 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 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 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 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 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 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 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 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 572 sntp_stop(void) 573 { 574 if (sntp_pcb != NULL) { 575 sys_untimeout(sntp_request, NULL); 576 sys_untimeout(sntp_try_next_server, NULL); 577 udp_remove(sntp_pcb); 578 sntp_pcb = NULL; 579 } 580 } 581 582 /** 583 * @ingroup sntp 584 * Get enabled state. 585 */ 586 u8_t sntp_enabled(void) 587 { 588 return (sntp_pcb != NULL)? 1 : 0; 589 } 590 591 /** 592 * @ingroup sntp 593 * Sets the operating mode. 594 * @param operating_mode one of the available operating modes 595 */ 596 void 597 sntp_setoperatingmode(u8_t operating_mode) 598 { 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; 602 } 603 604 /** 605 * @ingroup sntp 606 * Gets the operating mode. 607 */ 608 u8_t 609 sntp_getoperatingmode(void) 610 { 611 return sntp_opmode; 612 } 613 614 #if SNTP_GET_SERVERS_FROM_DHCP 615 /** 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 618 */ 619 void 620 sntp_servermode_dhcp(int set_servers_from_dhcp) 621 { 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; 625 } 626 } 627 #endif /* SNTP_GET_SERVERS_FROM_DHCP */ 628 629 /** 630 * @ingroup sntp 631 * Initialize one of the NTP servers by IP address 632 * 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 635 */ 636 void 637 sntp_setserver(u8_t idx, const ip_addr_t *server) 638 { 639 if (idx < SNTP_MAX_SERVERS) { 640 if (server != NULL) { 641 sntp_servers[idx].addr = (*server); 642 } else { 643 ip_addr_set_zero(&sntp_servers[idx].addr); 644 } 645 #if SNTP_SERVER_DNS 646 sntp_servers[idx].name = NULL; 647 #endif 648 } 649 } 650 651 #if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP 652 /** 653 * Initialize one of the NTP servers by IP address, required by DHCP 654 * 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 657 */ 658 void 659 dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) 660 { 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) { 665 u8_t i; 666 for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { 667 ip_addr_t addr; 668 ip_addr_copy_from_ip4(addr, server[i]); 669 sntp_setserver(i, &addr); 670 } 671 for (i = num; i < SNTP_MAX_SERVERS; i++) { 672 sntp_setserver(i, NULL); 673 } 674 } 675 } 676 #endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ 677 678 /** 679 * @ingroup sntp 680 * Obtain one of the currently configured by IP address (or DHCP) NTP servers 681 * 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). 685 */ 686 const ip_addr_t* 687 sntp_getserver(u8_t idx) 688 { 689 if (idx < SNTP_MAX_SERVERS) { 690 return &sntp_servers[idx].addr; 691 } 692 return IP_ADDR_ANY; 693 } 694 695 #if SNTP_SERVER_DNS 696 /** 697 * Initialize one of the NTP servers by name 698 * 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 701 */ 702 void 703 sntp_setservername(u8_t idx, char *server) 704 { 705 if (idx < SNTP_MAX_SERVERS) { 706 sntp_servers[idx].name = server; 707 } 708 } 709 710 /** 711 * Obtain one of the currently configured by name NTP servers. 712 * 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) 716 */ 717 char * 718 sntp_getservername(u8_t idx) 719 { 720 if (idx < SNTP_MAX_SERVERS) { 721 return sntp_servers[idx].name; 722 } 723 return NULL; 724 } 725 #endif /* SNTP_SERVER_DNS */ 726 727 #endif /* LWIP_UDP */ 728