1 /*
2  * Copyright (c) 2017 Linaro Limited
3  * Copyright (c) 2019 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief SNTP (Simple Network Time Protocol)
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_SNTP_H_
14 #define ZEPHYR_INCLUDE_NET_SNTP_H_
15 
16 #include <zephyr/net/socket.h>
17 #include <zephyr/net/socket_service.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * @brief Simple Network Time Protocol API
25  * @defgroup sntp SNTP
26  * @since 1.10
27  * @version 0.8.0
28  * @ingroup networking
29  * @{
30  */
31 
32 /** Time as returned by SNTP API, fractional seconds since 1 Jan 1970 */
33 struct sntp_time {
34 	uint64_t seconds;        /**< Second value */
35 	uint32_t fraction;       /**< Fractional seconds value */
36 #if defined(CONFIG_SNTP_UNCERTAINTY)
37 	uint64_t uptime_us;      /**< Uptime in microseconds */
38 	uint32_t uncertainty_us; /**< Uncertainty in microseconds */
39 #endif
40 };
41 
42 /** SNTP context */
43 struct sntp_ctx {
44 
45 /** @cond INTERNAL_HIDDEN */
46 	struct {
47 		struct zsock_pollfd fds[1];
48 		int nfds;
49 		int fd;
50 	} sock;
51 /** @endcond */
52 
53 	/** Timestamp when the request was sent from client to server.
54 	 *  This is used to check if the originated timestamp in the server
55 	 *  reply matches the one in client request.
56 	 */
57 	struct sntp_time expected_orig_ts;
58 };
59 
60 /**
61  * @brief Initialize SNTP context
62  *
63  * @param ctx Address of sntp context.
64  * @param addr IP address of NTP/SNTP server.
65  * @param addr_len IP address length of NTP/SNTP server.
66  *
67  * @return 0 if ok, <0 if error.
68  */
69 int sntp_init(struct sntp_ctx *ctx, struct sockaddr *addr,
70 	      socklen_t addr_len);
71 
72 /**
73  * @brief Perform SNTP query
74  *
75  * @param ctx Address of sntp context.
76  * @param timeout Timeout of waiting for sntp response (in milliseconds).
77  * @param ts Timestamp including integer and fractional seconds since
78  * 1 Jan 1970 (output).
79  *
80  * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
81  */
82 int sntp_query(struct sntp_ctx *ctx, uint32_t timeout, struct sntp_time *ts);
83 
84 /**
85  * @brief Attempt to receive an SNTP response after issuing a query
86  *
87  * @param ctx Address of sntp context.
88  * @param timeout Timeout of waiting for sntp response (in milliseconds).
89  * @param ts Timestamp including integer and fractional seconds since
90  * 1 Jan 1970 (output).
91  *
92  * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
93  */
94 int sntp_recv_response(struct sntp_ctx *ctx, uint32_t timeout, struct sntp_time *ts);
95 
96 /**
97  * @brief Release SNTP context
98  *
99  * @param ctx Address of sntp context.
100  */
101 void sntp_close(struct sntp_ctx *ctx);
102 
103 /**
104  * @brief Initialise SNTP context for async operation
105  *
106  * Asynchronous operation is powered by @kconfig{CONFIG_NET_SOCKETS_SERVICE}.
107  *
108  * @param ctx Address of sntp context.
109  * @param addr IP address of NTP/SNTP server.
110  * @param addr_len IP address length of NTP/SNTP server.
111  * @param service Socket service defined by @ref NET_SOCKET_SERVICE_SYNC_DEFINE
112  *
113  * @return 0 if ok, <0 if error.
114  */
115 int sntp_init_async(struct sntp_ctx *ctx, struct sockaddr *addr, socklen_t addr_len,
116 		    const struct net_socket_service_desc *service);
117 
118 /**
119  * @brief Send the SNTP query
120  *
121  * @param ctx Address of sntp context.
122  *
123  * @return 0 if ok, <0 if error.
124  */
125 int sntp_send_async(struct sntp_ctx *ctx);
126 
127 /**
128  * @brief Read the result of the SNTP query
129  *
130  * Must be called from the callback attached to the @ref net_socket_service_desc
131  * context.
132  *
133  * @param event Event pointer extracted from the service work callback
134  * @param ts Timestamp including integer and fractional seconds since
135  * 1 Jan 1970 (output).
136  *
137  * @return 0 if ok, <0 if error
138  */
139 int sntp_read_async(struct net_socket_service_event *event, struct sntp_time *ts);
140 
141 /**
142  * @brief Release SNTP context
143  *
144  * @param service Socket service defined by @ref NET_SOCKET_SERVICE_SYNC_DEFINE
145  */
146 void sntp_close_async(const struct net_socket_service_desc *service);
147 
148 /**
149  * @brief Convenience function to query SNTP in one-shot fashion
150  *
151  * Convenience wrapper which calls getaddrinfo(), sntp_init(),
152  * sntp_query(), and sntp_close().
153  *
154  * @param server Address of server in format addr[:port]
155  * @param timeout Query timeout
156  * @param ts Timestamp including integer and fractional seconds since
157  * 1 Jan 1970 (output).
158  *
159  * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
160  */
161 int sntp_simple(const char *server, uint32_t timeout,
162 		struct sntp_time *ts);
163 
164 /**
165  * @brief Convenience function to query SNTP in one-shot fashion
166  * using a pre-initialized address struct
167  *
168  * Convenience wrapper which calls sntp_init(), sntp_query() and
169  * sntp_close().
170  *
171  * @param addr IP address of NTP/SNTP server.
172  * @param addr_len IP address length of NTP/SNTP server.
173  * @param timeout Query timeout
174  * @param ts Timestamp including integer and fractional seconds since
175  * 1 Jan 1970 (output).
176  *
177  * @return 0 if ok, <0 if error (-ETIMEDOUT if timeout).
178  */
179 int sntp_simple_addr(struct sockaddr *addr, socklen_t addr_len, uint32_t timeout,
180 		     struct sntp_time *ts);
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 /**
187  * @}
188  */
189 
190 #endif
191