sntp.c 23 KB

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