5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <arpa/inet.h>
45 } __attribute__ ((packed));
50 } __attribute__ ((packed));
53 uint8_t flags; /* Mode, version and leap indicator */
54 uint8_t stratum; /* Stratum details */
55 int8_t poll; /* Maximum interval in log2 seconds */
56 int8_t precision; /* Clock precision in log2 seconds */
57 struct ntp_short rootdelay; /* Root delay */
58 struct ntp_short rootdisp; /* Root dispersion */
59 uint32_t refid; /* Reference ID */
60 struct ntp_time reftime; /* Reference timestamp */
61 struct ntp_time orgtime; /* Origin timestamp */
62 struct ntp_time rectime; /* Receive timestamp */
63 struct ntp_time xmttime; /* Transmit timestamp */
64 } __attribute__ ((packed));
66 #define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
68 #define STEPTIME_MIN_OFFSET 0.128
70 #define LOGTOD(a) ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
72 #define NTP_SEND_TIMEOUT 2
73 #define NTP_SEND_RETRIES 3
75 #define NTP_FLAG_LI_SHIFT 6
76 #define NTP_FLAG_LI_MASK 0x3
77 #define NTP_FLAG_LI_NOWARNING 0x0
78 #define NTP_FLAG_LI_ADDSECOND 0x1
79 #define NTP_FLAG_LI_DELSECOND 0x2
80 #define NTP_FLAG_LI_NOTINSYNC 0x3
82 #define NTP_FLAG_VN_SHIFT 3
83 #define NTP_FLAG_VN_MASK 0x7
85 #define NTP_FLAG_MD_SHIFT 0
86 #define NTP_FLAG_MD_MASK 0x7
87 #define NTP_FLAG_MD_UNSPEC 0
88 #define NTP_FLAG_MD_ACTIVE 1
89 #define NTP_FLAG_MD_PASSIVE 2
90 #define NTP_FLAG_MD_CLIENT 3
91 #define NTP_FLAG_MD_SERVER 4
92 #define NTP_FLAG_MD_BROADCAST 5
93 #define NTP_FLAG_MD_CONTROL 6
94 #define NTP_FLAG_MD_PRIVATE 7
96 #define NTP_FLAG_VN_VER3 3
97 #define NTP_FLAG_VN_VER4 4
99 #define NTP_FLAGS_ENCODE(li, vn, md) ((uint8_t)( \
100 (((li) & NTP_FLAG_LI_MASK) << NTP_FLAG_LI_SHIFT) | \
101 (((vn) & NTP_FLAG_VN_MASK) << NTP_FLAG_VN_SHIFT) | \
102 (((md) & NTP_FLAG_MD_MASK) << NTP_FLAG_MD_SHIFT)))
104 #define NTP_FLAGS_LI_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_LI_SHIFT) & NTP_FLAG_LI_MASK))
105 #define NTP_FLAGS_VN_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_VN_SHIFT) & NTP_FLAG_VN_MASK))
106 #define NTP_FLAGS_MD_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_MD_SHIFT) & NTP_FLAG_MD_MASK))
108 #define NTP_PRECISION_S 0
109 #define NTP_PRECISION_DS -3
110 #define NTP_PRECISION_CS -6
111 #define NTP_PRECISION_MS -9
112 #define NTP_PRECISION_US -19
113 #define NTP_PRECISION_NS -29
115 static guint channel_watch = 0;
116 static struct timespec mtx_time;
117 static int transmit_fd = 0;
119 static char *timeserver = NULL;
120 static struct sockaddr_in timeserver_addr;
121 static gint poll_id = 0;
122 static gint timeout_id = 0;
123 static guint retries = 0;
125 static void send_packet(int fd, const char *server, uint32_t timeout);
127 static void next_server(void)
134 __connman_timeserver_sync_next();
137 static gboolean send_timeout(gpointer user_data)
139 uint32_t timeout = GPOINTER_TO_UINT(user_data);
141 DBG("send timeout %u (retries %d)", timeout, retries);
143 if (retries++ == NTP_SEND_RETRIES)
146 send_packet(transmit_fd, timeserver, timeout << 1);
151 static void send_packet(int fd, const char *server, uint32_t timeout)
154 struct sockaddr_in addr;
155 struct timeval transmit_timeval;
159 * At some point, we could specify the actual system precision with:
161 * clock_getres(CLOCK_REALTIME, &ts);
162 * msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
164 memset(&msg, 0, sizeof(msg));
165 msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
168 msg.poll = 10; // max
169 msg.precision = NTP_PRECISION_S;
171 memset(&addr, 0, sizeof(addr));
172 addr.sin_family = AF_INET;
173 addr.sin_port = htons(123);
174 addr.sin_addr.s_addr = inet_addr(server);
176 gettimeofday(&transmit_timeval, NULL);
177 clock_gettime(CLOCK_MONOTONIC, &mtx_time);
179 msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
180 msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
182 len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
183 &addr, sizeof(addr));
185 connman_error("Time request for server %s failed (%d/%s)",
186 server, errno, strerror(errno));
188 if (errno == ENETUNREACH)
189 __connman_timeserver_sync_next();
194 if (len != sizeof(msg)) {
195 connman_error("Broken time request for server %s", server);
200 * Add an exponential retry timeout to retry the existing
201 * request. After a set number of retries, we'll fallback to
202 * trying another server.
205 timeout_id = g_timeout_add_seconds(timeout, send_timeout,
206 GUINT_TO_POINTER(timeout));
209 static gboolean next_poll(gpointer user_data)
213 if (!timeserver || transmit_fd == 0)
216 send_packet(transmit_fd, timeserver, NTP_SEND_TIMEOUT);
221 static void reset_timeout(void)
223 if (timeout_id > 0) {
224 g_source_remove(timeout_id);
231 static void decode_msg(void *base, size_t len, struct timeval *tv,
232 struct timespec *mrx_time)
234 struct ntp_msg *msg = base;
235 double m_delta, org, rec, xmt, dst;
236 double delay, offset;
237 static guint transmit_delay;
239 if (len < sizeof(*msg)) {
240 connman_error("Invalid response from time server");
245 connman_error("Invalid packet timestamp from time server");
249 DBG("flags : 0x%02x", msg->flags);
250 DBG("stratum : %u", msg->stratum);
251 DBG("poll : %f seconds (%d)",
252 LOGTOD(msg->poll), msg->poll);
253 DBG("precision : %f seconds (%d)",
254 LOGTOD(msg->precision), msg->precision);
255 DBG("root delay : %u seconds (fraction %u)",
256 msg->rootdelay.seconds, msg->rootdelay.fraction);
257 DBG("root disp. : %u seconds (fraction %u)",
258 msg->rootdisp.seconds, msg->rootdisp.fraction);
259 DBG("reference : 0x%04x", msg->refid);
262 /* RFC 4330 ch 8 Kiss-of-Death packet */
263 uint32_t code = ntohl(msg->refid);
265 connman_info("Skipping server %s KoD code %c%c%c%c",
266 timeserver, code >> 24, code >> 16 & 0xff,
267 code >> 8 & 0xff, code & 0xff);
272 transmit_delay = LOGTOD(msg->poll);
274 if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
275 DBG("ignoring unsynchronized peer");
280 if (NTP_FLAGS_VN_DECODE(msg->flags) != NTP_FLAG_VN_VER4) {
281 if (NTP_FLAGS_VN_DECODE(msg->flags) == NTP_FLAG_VN_VER3) {
282 DBG("requested version %d, accepting version %d",
283 NTP_FLAG_VN_VER4, NTP_FLAGS_VN_DECODE(msg->flags));
285 DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
290 if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) {
291 DBG("unsupported mode %d", NTP_FLAGS_MD_DECODE(msg->flags));
295 m_delta = mrx_time->tv_sec - mtx_time.tv_sec +
296 1.0e-9 * (mrx_time->tv_nsec - mtx_time.tv_nsec);
298 org = tv->tv_sec + (1.0e-6 * tv->tv_usec) - m_delta + OFFSET_1900_1970;
299 rec = ntohl(msg->rectime.seconds) +
300 ((double) ntohl(msg->rectime.fraction) / UINT_MAX);
301 xmt = ntohl(msg->xmttime.seconds) +
302 ((double) ntohl(msg->xmttime.fraction) / UINT_MAX);
303 dst = tv->tv_sec + (1.0e-6 * tv->tv_usec) + OFFSET_1900_1970;
305 DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
307 offset = ((rec - org) + (xmt - dst)) / 2;
308 delay = (dst - org) - (xmt - rec);
310 DBG("offset=%f delay=%f", offset, delay);
312 /* Remove the timeout, as timeserver has responded */
317 * Now poll the server every transmit_delay seconds
318 * for time correction.
321 g_source_remove(poll_id);
323 DBG("Timeserver %s, next sync in %d seconds", timeserver, transmit_delay);
325 poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
327 connman_info("ntp: time slew %+.6f s", offset);
329 #if defined TIZEN_EXT
330 //send the dbus message to alram-manager
332 #define TIME_BUS_NAME "org.tizen.alarm.manager"
333 #define TIME_INTERFACE "org.tizen.alarm.manager"
334 #define TIME_PATH "/org/tizen/alarm/manager"
335 #define TIME_METHOD "alarm_set_time_with_propagation_delay"
337 struct timespec cur = {0};
338 struct timespec req = {0};
341 DBusConnection *connection = NULL;
342 DBusMessage *msg = NULL, *reply = NULL;
345 dbus_error_init(&error);
347 connection = connman_dbus_get_connection();
349 DBG("dbus connection does not exist");
353 clock_gettime(CLOCK_REALTIME, &cur);
354 dtime = offset + cur.tv_sec + 1.0e-9 * cur.tv_nsec;
355 cur.tv_sec = (long) dtime;
356 cur.tv_nsec = (dtime - cur.tv_sec) * 1000000000;
358 clock_gettime(CLOCK_REALTIME, &req);
359 msg = dbus_message_new_method_call(TIME_BUS_NAME, TIME_PATH,
360 TIME_INTERFACE, TIME_METHOD);
361 dbus_message_append_args(msg, DBUS_TYPE_UINT32, &(cur.tv_sec),
362 DBUS_TYPE_UINT32, &(cur.tv_nsec),
363 DBUS_TYPE_UINT32, &(req.tv_sec),
364 DBUS_TYPE_UINT32, &(req.tv_nsec), DBUS_TYPE_INVALID);
365 reply = dbus_connection_send_with_reply_and_block(connection, msg,
366 DBUS_TIMEOUT_USE_DEFAULT, &error);
368 if(dbus_error_is_set(&error)){
369 DBG("%s", error.message);
370 dbus_error_free(&error);
373 DBG("Failed to request set time");
375 dbus_connection_unref(connection);
376 dbus_message_unref(msg);
380 dbus_message_unref(msg);
381 dbus_message_unref(reply);
382 dbus_connection_unref(connection);
384 DBG("%lu cur seconds, %lu cur nsecs, %lu req seconds, %lu req nsecs",
385 cur.tv_sec, cur.tv_nsec, req.tv_sec, req.tv_nsec);
389 if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
392 adj.tv_sec = (long) offset;
393 adj.tv_usec = (offset - adj.tv_sec) * 1000000;
395 DBG("adjusting time");
397 if (adjtime(&adj, &adj) < 0) {
398 connman_error("Failed to adjust time");
402 DBG("%lu seconds, %lu msecs", adj.tv_sec, adj.tv_usec);
407 gettimeofday(&cur, NULL);
408 dtime = offset + cur.tv_sec + 1.0e-6 * cur.tv_usec;
409 cur.tv_sec = (long) dtime;
410 cur.tv_usec = (dtime - cur.tv_sec) * 1000000;
414 if (settimeofday(&cur, NULL) < 0) {
415 connman_error("Failed to set time");
419 DBG("%lu seconds, %lu msecs", cur.tv_sec, cur.tv_usec);
424 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
427 unsigned char buf[128];
428 struct sockaddr_in sender_addr;
431 struct cmsghdr *cmsg;
433 struct timespec mrx_time;
438 if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
439 connman_error("Problem with timer server channel");
444 fd = g_io_channel_unix_get_fd(channel);
447 iov.iov_len = sizeof(buf);
449 memset(&msg, 0, sizeof(msg));
452 msg.msg_control = aux;
453 msg.msg_controllen = sizeof(aux);
454 msg.msg_name = &sender_addr;
455 msg.msg_namelen = sizeof(sender_addr);
457 len = recvmsg(fd, &msg, MSG_DONTWAIT);
461 if (timeserver_addr.sin_addr.s_addr != sender_addr.sin_addr.s_addr)
462 /* only accept messages from the timeserver */
466 clock_gettime(CLOCK_MONOTONIC, &mrx_time);
468 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
469 if (cmsg->cmsg_level != SOL_SOCKET)
472 switch (cmsg->cmsg_type) {
474 tv = (struct timeval *) CMSG_DATA(cmsg);
479 decode_msg(iov.iov_base, iov.iov_len, tv, &mrx_time);
484 static void start_ntp(char *server)
487 struct sockaddr_in addr;
488 int tos = IPTOS_LOWDELAY, timestamp = 1;
493 DBG("server %s", server);
495 if (channel_watch > 0)
498 transmit_fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
499 if (transmit_fd < 0) {
500 connman_error("Failed to open time server socket");
504 memset(&addr, 0, sizeof(addr));
505 addr.sin_family = AF_INET;
507 if (bind(transmit_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
508 connman_error("Failed to bind time server socket");
513 if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
514 connman_error("Failed to set type of service option");
519 if (setsockopt(transmit_fd, SOL_SOCKET, SO_TIMESTAMP, ×tamp,
520 sizeof(timestamp)) < 0) {
521 connman_error("Failed to enable timestamp support");
526 channel = g_io_channel_unix_new(transmit_fd);
532 g_io_channel_set_encoding(channel, NULL, NULL);
533 g_io_channel_set_buffered(channel, FALSE);
535 g_io_channel_set_close_on_unref(channel, TRUE);
537 channel_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
538 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
539 received_data, NULL, NULL);
541 g_io_channel_unref(channel);
544 send_packet(transmit_fd, server, NTP_SEND_TIMEOUT);
547 int __connman_ntp_start(char *server)
557 timeserver = g_strdup(server);
558 timeserver_addr.sin_addr.s_addr = inet_addr(server);
560 start_ntp(timeserver);
565 void __connman_ntp_stop()
570 g_source_remove(poll_id);
576 if (channel_watch > 0) {
577 g_source_remove(channel_watch);