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