1 /*
2 * Copyright (c) 2019 Linaro Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
10
11 #include <errno.h>
12 #include <zephyr/net/net_if.h>
13 #include <zephyr/net/sntp.h>
14 #include <zephyr/posix/time.h>
15
16 #ifdef CONFIG_NET_CONFIG_SNTP_INIT_RESYNC
17 static void sntp_resync_handler(struct k_work *work);
18 static K_WORK_DELAYABLE_DEFINE(sntp_resync_work_handle, sntp_resync_handler);
19 #endif
20
sntp_init_helper(struct sntp_time * tm)21 static int sntp_init_helper(struct sntp_time *tm)
22 {
23 #ifdef CONFIG_NET_CONFIG_SNTP_INIT_SERVER_USE_DHCPV4_OPTION
24 struct net_if *iface = net_if_get_default();
25
26 if (!net_ipv4_is_addr_unspecified(&iface->config.dhcpv4.ntp_addr)) {
27 struct sockaddr_in sntp_addr = {0};
28
29 sntp_addr.sin_family = AF_INET;
30 sntp_addr.sin_addr.s_addr = iface->config.dhcpv4.ntp_addr.s_addr;
31 return sntp_simple_addr((struct sockaddr *)&sntp_addr, sizeof(sntp_addr),
32 CONFIG_NET_CONFIG_SNTP_INIT_TIMEOUT, tm);
33 }
34 LOG_INF("SNTP address not set by DHCPv4, using Kconfig defaults");
35 #endif /* NET_CONFIG_SNTP_INIT_SERVER_USE_DHCPV4_OPTION */
36 return sntp_simple(CONFIG_NET_CONFIG_SNTP_INIT_SERVER,
37 CONFIG_NET_CONFIG_SNTP_INIT_TIMEOUT, tm);
38 }
39
net_init_clock_via_sntp(void)40 int net_init_clock_via_sntp(void)
41 {
42 struct sntp_time ts;
43 struct timespec tspec;
44 int res = sntp_init_helper(&ts);
45
46 if (res < 0) {
47 LOG_ERR("Cannot set time using SNTP");
48 goto end;
49 }
50
51 tspec.tv_sec = ts.seconds;
52 tspec.tv_nsec = ((uint64_t)ts.fraction * (1000 * 1000 * 1000)) >> 32;
53 res = clock_settime(CLOCK_REALTIME, &tspec);
54
55 end:
56 #ifdef CONFIG_NET_CONFIG_SNTP_INIT_RESYNC
57 k_work_reschedule(&sntp_resync_work_handle,
58 K_SECONDS(CONFIG_NET_CONFIG_SNTP_INIT_RESYNC_INTERVAL));
59 #endif
60 return res;
61 }
62
63 #ifdef CONFIG_NET_CONFIG_SNTP_INIT_RESYNC
sntp_resync_handler(struct k_work * work)64 static void sntp_resync_handler(struct k_work *work)
65 {
66 int res;
67
68 ARG_UNUSED(work);
69
70 res = net_init_clock_via_sntp();
71 if (res < 0) {
72 LOG_ERR("Cannot resync time using SNTP");
73 return;
74 }
75 LOG_DBG("Time resynced using SNTP");
76 }
77 #endif /* CONFIG_NET_CONFIG_SNTP_INIT_RESYNC */
78