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