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
32 #include <sys/timex.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <arpa/inet.h>
46 } __attribute__ ((packed));
51 } __attribute__ ((packed));
54 uint8_t flags; /* Mode, version and leap indicator */
55 uint8_t stratum; /* Stratum details */
56 int8_t poll; /* Maximum interval in log2 seconds */
57 int8_t precision; /* Clock precision in log2 seconds */
58 struct ntp_short rootdelay; /* Root delay */
59 struct ntp_short rootdisp; /* Root dispersion */
60 uint32_t refid; /* Reference ID */
61 struct ntp_time reftime; /* Reference timestamp */
62 struct ntp_time orgtime; /* Origin timestamp */
63 struct ntp_time rectime; /* Receive timestamp */
64 struct ntp_time xmttime; /* Transmit timestamp */
65 } __attribute__ ((packed));
67 #define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
69 #define STEPTIME_MIN_OFFSET 0.4
71 #define LOGTOD(a) ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
72 #define NSEC_PER_SEC ((uint64_t)1000000000ULL)
74 #define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
77 #define NTP_SEND_TIMEOUT 2
78 #define NTP_SEND_RETRIES 3
80 #define NTP_FLAG_LI_SHIFT 6
81 #define NTP_FLAG_LI_MASK 0x3
82 #define NTP_FLAG_LI_NOWARNING 0x0
83 #define NTP_FLAG_LI_ADDSECOND 0x1
84 #define NTP_FLAG_LI_DELSECOND 0x2
85 #define NTP_FLAG_LI_NOTINSYNC 0x3
87 #define NTP_FLAG_VN_SHIFT 3
88 #define NTP_FLAG_VN_MASK 0x7
90 #define NTP_FLAG_MD_SHIFT 0
91 #define NTP_FLAG_MD_MASK 0x7
92 #define NTP_FLAG_MD_UNSPEC 0
93 #define NTP_FLAG_MD_ACTIVE 1
94 #define NTP_FLAG_MD_PASSIVE 2
95 #define NTP_FLAG_MD_CLIENT 3
96 #define NTP_FLAG_MD_SERVER 4
97 #define NTP_FLAG_MD_BROADCAST 5
98 #define NTP_FLAG_MD_CONTROL 6
99 #define NTP_FLAG_MD_PRIVATE 7
101 #define NTP_FLAG_VN_VER3 3
102 #define NTP_FLAG_VN_VER4 4
104 #define NTP_FLAGS_ENCODE(li, vn, md) ((uint8_t)( \
105 (((li) & NTP_FLAG_LI_MASK) << NTP_FLAG_LI_SHIFT) | \
106 (((vn) & NTP_FLAG_VN_MASK) << NTP_FLAG_VN_SHIFT) | \
107 (((md) & NTP_FLAG_MD_MASK) << NTP_FLAG_MD_SHIFT)))
109 #define NTP_FLAGS_LI_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_LI_SHIFT) & NTP_FLAG_LI_MASK))
110 #define NTP_FLAGS_VN_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_VN_SHIFT) & NTP_FLAG_VN_MASK))
111 #define NTP_FLAGS_MD_DECODE(flags) ((uint8_t)(((flags) >> NTP_FLAG_MD_SHIFT) & NTP_FLAG_MD_MASK))
113 #define NTP_PRECISION_S 0
114 #define NTP_PRECISION_DS -3
115 #define NTP_PRECISION_CS -6
116 #define NTP_PRECISION_MS -9
117 #define NTP_PRECISION_US -19
118 #define NTP_PRECISION_NS -29
122 struct sockaddr_in6 timeserver_addr;
123 struct timespec mtx_time;
130 __connman_ntp_cb_t cb;
134 static struct ntp_data *ntp_data;
136 static void free_ntp_data(struct ntp_data *nd)
139 g_source_remove(nd->poll_id);
141 g_source_remove(nd->timeout_id);
142 if (nd->channel_watch)
143 g_source_remove(nd->channel_watch);
145 g_free(nd->timeserver);
149 static void send_packet(struct ntp_data *nd, struct sockaddr *server,
152 static gboolean send_timeout(gpointer user_data)
154 struct ntp_data *nd = user_data;
156 DBG("send timeout %u (retries %d)", nd->timeout, nd->retries);
158 if (nd->retries++ == NTP_SEND_RETRIES)
159 nd->cb(false, nd->user_data);
161 send_packet(nd, (struct sockaddr *)&nd->timeserver_addr,
167 static void send_packet(struct ntp_data *nd, struct sockaddr *server,
171 struct timeval transmit_timeval;
175 char ipaddrstring[INET6_ADDRSTRLEN + 1];
178 * At some point, we could specify the actual system precision with:
180 * clock_getres(CLOCK_REALTIME, &ts);
181 * msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
183 memset(&msg, 0, sizeof(msg));
184 msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
187 msg.precision = NTP_PRECISION_S;
189 if (server->sa_family == AF_INET) {
190 size = sizeof(struct sockaddr_in);
191 addr = (void *)&(((struct sockaddr_in *)&nd->timeserver_addr)->sin_addr);
192 } else if (server->sa_family == AF_INET6) {
193 size = sizeof(struct sockaddr_in6);
194 addr = (void *)&nd->timeserver_addr.sin6_addr;
196 DBG("Family is neither ipv4 nor ipv6");
197 nd->cb(false, nd->user_data);
201 gettimeofday(&transmit_timeval, NULL);
202 clock_gettime(CLOCK_MONOTONIC, &nd->mtx_time);
204 msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
205 msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
207 len = sendto(nd->transmit_fd, &msg, sizeof(msg), MSG_DONTWAIT,
209 if (len < 0 || len != sizeof(msg)) {
210 DBG("Time request for server %s failed",
211 inet_ntop(server->sa_family, addr, ipaddrstring, sizeof(ipaddrstring)));
212 nd->cb(false, nd->user_data);
217 * Add an exponential retry timeout to retry the existing
218 * request. After a set number of retries, we'll fallback to
219 * trying another server.
222 nd->timeout = timeout;
223 nd->timeout_id = g_timeout_add_seconds(timeout, send_timeout, nd);
226 static gboolean next_poll(gpointer user_data)
228 struct ntp_data *nd = user_data;
231 if (!nd->timeserver || nd->transmit_fd == 0)
234 send_packet(nd, (struct sockaddr *)&nd->timeserver_addr, NTP_SEND_TIMEOUT);
239 static void reset_timeout(struct ntp_data *nd)
241 if (nd->timeout_id > 0) {
242 g_source_remove(nd->timeout_id);
249 static void decode_msg(struct ntp_data *nd, void *base, size_t len,
250 struct timeval *tv, struct timespec *mrx_time)
252 struct ntp_msg *msg = base;
253 double m_delta, org, rec, xmt, dst;
254 double delay, offset;
255 static guint transmit_delay;
256 #if !defined TIZEN_EXT
257 struct timex tmx = {};
260 if (len < sizeof(*msg)) {
261 connman_error("Invalid response from time server");
266 connman_error("Invalid packet timestamp from time server");
270 DBG("flags : 0x%02x", msg->flags);
271 DBG("stratum : %u", msg->stratum);
272 DBG("poll : %f seconds (%d)",
273 LOGTOD(msg->poll), msg->poll);
274 DBG("precision : %f seconds (%d)",
275 LOGTOD(msg->precision), msg->precision);
276 DBG("root delay : %u seconds (fraction %u)",
277 msg->rootdelay.seconds, msg->rootdelay.fraction);
278 DBG("root disp. : %u seconds (fraction %u)",
279 msg->rootdisp.seconds, msg->rootdisp.fraction);
280 DBG("reference : 0x%04x", msg->refid);
283 /* RFC 4330 ch 8 Kiss-of-Death packet */
284 uint32_t code = ntohl(msg->refid);
286 connman_info("Skipping server %s KoD code %c%c%c%c",
287 nd->timeserver, code >> 24, code >> 16 & 0xff,
288 code >> 8 & 0xff, code & 0xff);
289 nd->cb(false, nd->user_data);
293 transmit_delay = LOGTOD(msg->poll);
295 if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
296 DBG("ignoring unsynchronized peer");
297 nd->cb(false, nd->user_data);
302 if (NTP_FLAGS_VN_DECODE(msg->flags) != NTP_FLAG_VN_VER4) {
303 if (NTP_FLAGS_VN_DECODE(msg->flags) == NTP_FLAG_VN_VER3) {
304 DBG("requested version %d, accepting version %d",
305 NTP_FLAG_VN_VER4, NTP_FLAGS_VN_DECODE(msg->flags));
307 DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
308 nd->cb(false, nd->user_data);
313 if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) {
314 DBG("unsupported mode %d", NTP_FLAGS_MD_DECODE(msg->flags));
315 nd->cb(false, nd->user_data);
319 m_delta = mrx_time->tv_sec - nd->mtx_time.tv_sec +
320 1.0e-9 * (mrx_time->tv_nsec - nd->mtx_time.tv_nsec);
322 org = tv->tv_sec + (1.0e-6 * tv->tv_usec) - m_delta + OFFSET_1900_1970;
323 rec = ntohl(msg->rectime.seconds) +
324 ((double) ntohl(msg->rectime.fraction) / UINT_MAX);
325 xmt = ntohl(msg->xmttime.seconds) +
326 ((double) ntohl(msg->xmttime.fraction) / UINT_MAX);
327 dst = tv->tv_sec + (1.0e-6 * tv->tv_usec) + OFFSET_1900_1970;
329 DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
331 offset = ((rec - org) + (xmt - dst)) / 2;
332 delay = (dst - org) - (xmt - rec);
334 DBG("offset=%f delay=%f", offset, delay);
336 /* Remove the timeout, as timeserver has responded */
341 * Now poll the server every transmit_delay seconds
342 * for time correction.
345 g_source_remove(nd->poll_id);
347 DBG("Timeserver %s, next sync in %d seconds", nd->timeserver,
350 nd->poll_id = g_timeout_add_seconds(transmit_delay, next_poll, nd);
352 #if defined TIZEN_EXT
353 //send the dbus message to alram-manager
355 #define TIME_BUS_NAME "org.tizen.alarm.manager"
356 #define TIME_INTERFACE "org.tizen.alarm.manager"
357 #define TIME_PATH "/org/tizen/alarm/manager"
358 #define TIME_METHOD "alarm_set_time_with_propagation_delay"
360 struct timespec cur = {0};
361 struct timespec req = {0};
364 DBusConnection *connection = NULL;
365 DBusMessage *msg = NULL, *reply = NULL;
368 dbus_error_init(&error);
370 connection = connman_dbus_get_connection();
372 DBG("dbus connection does not exist");
376 clock_gettime(CLOCK_REALTIME, &cur);
377 dtime = offset + cur.tv_sec + 1.0e-9 * cur.tv_nsec;
378 cur.tv_sec = (long) dtime;
379 cur.tv_nsec = (dtime - cur.tv_sec) * 1000000000;
381 clock_gettime(CLOCK_REALTIME, &req);
382 msg = dbus_message_new_method_call(TIME_BUS_NAME, TIME_PATH,
383 TIME_INTERFACE, TIME_METHOD);
384 dbus_message_append_args(msg, DBUS_TYPE_UINT32, &(cur.tv_sec),
385 DBUS_TYPE_UINT32, &(cur.tv_nsec),
386 DBUS_TYPE_UINT32, &(req.tv_sec),
387 DBUS_TYPE_UINT32, &(req.tv_nsec), DBUS_TYPE_INVALID);
388 reply = dbus_connection_send_with_reply_and_block(connection, msg,
389 DBUS_TIMEOUT_USE_DEFAULT, &error);
391 if(dbus_error_is_set(&error)){
392 DBG("%s", error.message);
393 dbus_error_free(&error);
396 DBG("Failed to request set time");
398 dbus_connection_unref(connection);
399 dbus_message_unref(msg);
403 dbus_message_unref(msg);
404 dbus_message_unref(reply);
405 dbus_connection_unref(connection);
407 DBG("%lu cur seconds, %lu cur nsecs, %lu req seconds, %lu req nsecs",
408 cur.tv_sec, cur.tv_nsec, req.tv_sec, req.tv_nsec);
412 if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
413 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
414 tmx.status = STA_PLL;
415 tmx.offset = offset * NSEC_PER_SEC;
416 tmx.constant = msg->poll - 4;
420 connman_info("ntp: adjust (slew): %+.6f sec", offset);
422 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
424 /* ADJ_NANO uses nanoseconds in the microseconds field */
425 tmx.time.tv_sec = (long)offset;
426 tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
430 /* the kernel expects -0.3s as {-1, 7000.000.000} */
431 if (tmx.time.tv_usec < 0) {
432 tmx.time.tv_sec -= 1;
433 tmx.time.tv_usec += NSEC_PER_SEC;
436 connman_info("ntp: adjust (jump): %+.6f sec", offset);
439 if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_ADDSECOND)
440 tmx.status |= STA_INS;
441 else if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_DELSECOND)
442 tmx.status |= STA_DEL;
444 if (adjtimex(&tmx) < 0) {
445 connman_error("Failed to adjust time: %s (%d)", strerror(errno), errno);
446 nd->cb(false, nd->user_data);
450 DBG("interval/delta/delay/drift %fs/%+.3fs/%.3fs/%+ldppm",
451 LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
453 nd->cb(true, nd->user_data);
457 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
460 struct ntp_data *nd = user_data;
461 unsigned char buf[128];
462 struct sockaddr_in6 sender_addr;
465 struct cmsghdr *cmsg;
467 struct timespec mrx_time;
475 if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
476 connman_error("Problem with timer server channel");
477 nd->channel_watch = 0;
481 fd = g_io_channel_unix_get_fd(channel);
484 iov.iov_len = sizeof(buf);
486 memset(&msg, 0, sizeof(msg));
489 msg.msg_control = aux;
490 msg.msg_controllen = sizeof(aux);
491 msg.msg_name = &sender_addr;
492 msg.msg_namelen = sizeof(sender_addr);
494 len = recvmsg(fd, &msg, MSG_DONTWAIT);
498 if (sender_addr.sin6_family == AF_INET) {
500 addr_ptr = &((struct sockaddr_in *)&nd->timeserver_addr)->sin_addr;
501 src_ptr = &((struct sockaddr_in *)&sender_addr)->sin_addr;
502 } else if (sender_addr.sin6_family == AF_INET6) {
504 addr_ptr = &((struct sockaddr_in6 *)&nd->timeserver_addr)->sin6_addr;
505 src_ptr = &((struct sockaddr_in6 *)&sender_addr)->sin6_addr;
507 connman_error("Not a valid family type");
511 if(memcmp(addr_ptr, src_ptr, size) != 0)
515 clock_gettime(CLOCK_MONOTONIC, &mrx_time);
517 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
518 if (cmsg->cmsg_level != SOL_SOCKET)
521 switch (cmsg->cmsg_type) {
523 tv = (struct timeval *) CMSG_DATA(cmsg);
528 decode_msg(nd, iov.iov_base, iov.iov_len, tv, &mrx_time);
533 static void start_ntp(struct ntp_data *nd)
536 struct addrinfo hint;
537 struct addrinfo *info;
538 struct sockaddr * addr;
539 struct sockaddr_in * in4addr;
540 struct sockaddr_in6 in6addr;
543 int tos = IPTOS_LOWDELAY, timestamp = 1;
546 memset(&hint, 0, sizeof(hint));
547 hint.ai_family = AF_UNSPEC;
548 hint.ai_socktype = SOCK_DGRAM;
549 hint.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
550 ret = getaddrinfo(nd->timeserver, NULL, &hint, &info);
553 connman_error("cannot get server info");
557 family = info->ai_family;
559 memcpy(&ntp_data->timeserver_addr, info->ai_addr, info->ai_addrlen);
561 memset(&in6addr, 0, sizeof(in6addr));
563 if (family == AF_INET) {
564 ((struct sockaddr_in *)&ntp_data->timeserver_addr)->sin_port = htons(123);
565 in4addr = (struct sockaddr_in *)&in6addr;
566 in4addr->sin_family = family;
567 addr = (struct sockaddr *)in4addr;
568 size = sizeof(struct sockaddr_in);
569 } else if (family == AF_INET6) {
570 ntp_data->timeserver_addr.sin6_port = htons(123);
571 in6addr.sin6_family = family;
572 addr = (struct sockaddr *)&in6addr;
573 size = sizeof(in6addr);
575 connman_error("Family is neither ipv4 nor ipv6");
579 DBG("server %s family %d", nd->timeserver, family);
581 if (nd->channel_watch > 0)
584 nd->transmit_fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
586 if (nd->transmit_fd <= 0) {
587 if (errno != EAFNOSUPPORT)
588 connman_error("Failed to open time server socket");
591 if (bind(nd->transmit_fd, (struct sockaddr *) addr, size) < 0) {
592 connman_error("Failed to bind time server socket");
596 if (family == AF_INET) {
597 if (setsockopt(nd->transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
598 connman_error("Failed to set type of service option");
603 if (setsockopt(nd->transmit_fd, SOL_SOCKET, SO_TIMESTAMP, ×tamp,
604 sizeof(timestamp)) < 0) {
605 connman_error("Failed to enable timestamp support");
609 channel = g_io_channel_unix_new(nd->transmit_fd);
613 g_io_channel_set_encoding(channel, NULL, NULL);
614 g_io_channel_set_buffered(channel, FALSE);
616 g_io_channel_set_close_on_unref(channel, TRUE);
618 nd->channel_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
619 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
620 received_data, nd, NULL);
622 g_io_channel_unref(channel);
625 send_packet(nd, (struct sockaddr*)&ntp_data->timeserver_addr,
630 if (nd->transmit_fd > 0)
631 close(nd->transmit_fd);
633 nd->cb(false, nd->user_data);
636 int __connman_ntp_start(char *server, __connman_ntp_cb_t callback,
643 connman_warn("ntp_data is not NULL (timerserver %s)",
644 ntp_data->timeserver);
645 free_ntp_data(ntp_data);
648 ntp_data = g_new0(struct ntp_data, 1);
650 ntp_data->timeserver = g_strdup(server);
651 ntp_data->cb = callback;
652 ntp_data->user_data = user_data;
659 void __connman_ntp_stop()
662 free_ntp_data(ntp_data);