b588c99c6c2092b974696f42814ef6a56b2bb875
[platform/upstream/connman.git] / src / ntp.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #define _GNU_SOURCE
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <arpa/inet.h>
37
38 #include <glib.h>
39
40 #include "connman.h"
41
42 struct ntp_short {
43         uint16_t seconds;
44         uint16_t fraction;
45 } __attribute__ ((packed));
46
47 struct ntp_time {
48         uint32_t seconds;
49         uint32_t fraction;
50 } __attribute__ ((packed));
51
52 struct ntp_msg {
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));
65
66 #define OFFSET_1900_1970  2208988800UL  /* 1970 - 1900 in seconds */
67
68 #define STEPTIME_MIN_OFFSET  0.128
69
70 #define LOGTOD(a)  ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
71
72 #define NTP_SEND_TIMEOUT       2
73 #define NTP_SEND_RETRIES       3
74
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
81
82 #define NTP_FLAG_VN_SHIFT      3
83 #define NTP_FLAG_VN_MASK       0x7
84
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
95
96 #define NTP_FLAGS_ENCODE(li, vn, md)  ((uint8_t)( \
97                       (((li) & NTP_FLAG_LI_MASK) << NTP_FLAG_LI_SHIFT) | \
98                       (((vn) & NTP_FLAG_VN_MASK) << NTP_FLAG_VN_SHIFT) | \
99                       (((md) & NTP_FLAG_MD_MASK) << NTP_FLAG_MD_SHIFT)))
100
101 #define NTP_FLAGS_LI_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_LI_SHIFT) & NTP_FLAG_LI_MASK))
102 #define NTP_FLAGS_VN_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_VN_SHIFT) & NTP_FLAG_VN_MASK))
103 #define NTP_FLAGS_MD_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_MD_SHIFT) & NTP_FLAG_MD_MASK))
104
105 #define NTP_PRECISION_S    0
106 #define NTP_PRECISION_DS   -3
107 #define NTP_PRECISION_CS   -6
108 #define NTP_PRECISION_MS   -9
109 #define NTP_PRECISION_US   -19
110 #define NTP_PRECISION_NS   -29
111
112 static guint channel_watch = 0;
113 static struct timespec mtx_time;
114 static int transmit_fd = 0;
115
116 static char *timeserver = NULL;
117 static gint poll_id = 0;
118 static gint timeout_id = 0;
119 static guint retries = 0;
120
121 static void send_packet(int fd, const char *server);
122
123 static void next_server(void)
124 {
125         if (timeserver != NULL) {
126                 g_free(timeserver);
127                 timeserver = NULL;
128         }
129
130         __connman_timeserver_sync_next();
131 }
132
133 static gboolean send_timeout(gpointer user_data)
134 {
135         DBG("send timeout (retries %d)", retries);
136
137         if (retries++ == NTP_SEND_RETRIES)
138                 next_server();
139         else
140                 send_packet(transmit_fd, timeserver);
141
142         return FALSE;
143 }
144
145 static void send_packet(int fd, const char *server)
146 {
147         struct ntp_msg msg;
148         struct sockaddr_in addr;
149         struct timeval transmit_timeval;
150         ssize_t len;
151
152         /*
153          * At some point, we could specify the actual system precision with:
154          *
155          *   clock_getres(CLOCK_REALTIME, &ts);
156          *   msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
157          */
158         memset(&msg, 0, sizeof(msg));
159         msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, 4, NTP_FLAG_MD_CLIENT);
160         msg.poll = 4;   // min
161         msg.poll = 10;  // max
162         msg.precision = NTP_PRECISION_S;
163
164         memset(&addr, 0, sizeof(addr));
165         addr.sin_family = AF_INET;
166         addr.sin_port = htons(123);
167         addr.sin_addr.s_addr = inet_addr(server);
168
169         gettimeofday(&transmit_timeval, NULL);
170         clock_gettime(CLOCK_MONOTONIC, &mtx_time);
171
172         msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
173         msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
174
175         len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
176                                                 &addr, sizeof(addr));
177         if (len < 0) {
178                 connman_error("Time request for server %s failed (%d/%s)",
179                         server, errno, strerror(errno));
180
181                 if (errno == ENETUNREACH)
182                         __connman_timeserver_sync_next();
183
184                 return;
185         }
186
187         if (len != sizeof(msg)) {
188                 connman_error("Broken time request for server %s", server);
189                 return;
190         }
191
192         /*
193          * Add a retry timeout of two seconds to retry the existing
194          * request. After a set number of retries, we'll fallback to
195          * trying another server.
196          */
197
198         timeout_id = g_timeout_add_seconds(NTP_SEND_TIMEOUT, send_timeout, NULL);
199 }
200
201 static gboolean next_poll(gpointer user_data)
202 {
203         if (timeserver == NULL || transmit_fd == 0)
204                 return FALSE;
205
206         send_packet(transmit_fd, timeserver);
207
208         return FALSE;
209 }
210
211 static void reset_timeout(void)
212 {
213         if (timeout_id > 0)
214                 g_source_remove(timeout_id);
215
216         retries = 0;
217 }
218
219 static void decode_msg(void *base, size_t len, struct timeval *tv,
220                 struct timespec *mrx_time)
221 {
222         struct ntp_msg *msg = base;
223         double m_delta, org, rec, xmt, dst;
224         double delay, offset;
225         static guint transmit_delay;
226
227         if (len < sizeof(*msg)) {
228                 connman_error("Invalid response from time server");
229                 return;
230         }
231
232         if (tv == NULL) {
233                 connman_error("Invalid packet timestamp from time server");
234                 return;
235         }
236
237         DBG("flags      : 0x%02x", msg->flags);
238         DBG("stratum    : %u", msg->stratum);
239         DBG("poll       : %f seconds (%d)",
240                                 LOGTOD(msg->poll), msg->poll);
241         DBG("precision  : %f seconds (%d)",
242                                 LOGTOD(msg->precision), msg->precision);
243         DBG("root delay : %u seconds (fraction %u)",
244                         msg->rootdelay.seconds, msg->rootdelay.fraction);
245         DBG("root disp. : %u seconds (fraction %u)",
246                         msg->rootdisp.seconds, msg->rootdisp.fraction);
247         DBG("reference  : 0x%04x", msg->refid);
248
249         transmit_delay = LOGTOD(msg->poll);
250
251         if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
252                 DBG("ignoring unsynchronized peer");
253                 return;
254         }
255
256         if (NTP_FLAGS_VN_DECODE(msg->flags) != 4) {
257                 DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
258                 return;
259         }
260
261         if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) {
262                 DBG("unsupported mode %d", NTP_FLAGS_MD_DECODE(msg->flags));
263                 return;
264         }
265
266         m_delta = mrx_time->tv_sec - mtx_time.tv_sec +
267                 1.0e-9 * (mrx_time->tv_nsec - mtx_time.tv_nsec);
268
269         org = tv->tv_sec + (1.0e-6 * tv->tv_usec) - m_delta + OFFSET_1900_1970;
270         rec = ntohl(msg->rectime.seconds) +
271                         ((double) ntohl(msg->rectime.fraction) / UINT_MAX);
272         xmt = ntohl(msg->xmttime.seconds) +
273                         ((double) ntohl(msg->xmttime.fraction) / UINT_MAX);
274         dst = tv->tv_sec + (1.0e-6 * tv->tv_usec) + OFFSET_1900_1970;
275
276         DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
277
278         offset = ((rec - org) + (xmt - dst)) / 2;
279         delay = (dst - org) - (xmt - rec);
280
281         DBG("offset=%f delay=%f", offset, delay);
282
283         /* Remove the timeout, as timeserver has responded */
284
285         reset_timeout();
286
287         /*
288          * Now poll the server every transmit_delay seconds
289          * for time correction.
290          */
291         if (poll_id > 0)
292                 g_source_remove(poll_id);
293
294         DBG("Timeserver %s, next sync in %d seconds", timeserver, transmit_delay);
295
296         poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
297
298         connman_info("ntp: time slew %+.6f s", offset);
299
300         if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
301                 struct timeval adj;
302
303                 adj.tv_sec = (long) offset;
304                 adj.tv_usec = (offset - adj.tv_sec) * 1000000;
305
306                 DBG("adjusting time");
307
308                 if (adjtime(&adj, &adj) < 0) {
309                         connman_error("Failed to adjust time");
310                         return;
311                 }
312
313                 DBG("%lu seconds, %lu msecs", adj.tv_sec, adj.tv_usec);
314         } else {
315                 struct timeval cur;
316                 double dtime;
317
318                 gettimeofday(&cur, NULL);
319                 dtime = offset + cur.tv_sec + 1.0e-6 * cur.tv_usec;
320                 cur.tv_sec = (long) dtime;
321                 cur.tv_usec = (dtime - cur.tv_sec) * 1000000;
322
323                 DBG("setting time");
324
325                 if (settimeofday(&cur, NULL) < 0) {
326                         connman_error("Failed to set time");
327                         return;
328                 }
329
330                 DBG("%lu seconds, %lu msecs", cur.tv_sec, cur.tv_usec);
331         }
332 }
333
334 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
335                                                         gpointer user_data)
336 {
337         unsigned char buf[128];
338         struct msghdr msg;
339         struct iovec iov;
340         struct cmsghdr *cmsg;
341         struct timeval *tv;
342         struct timespec mrx_time;
343         char aux[128];
344         ssize_t len;
345         int fd;
346
347         if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
348                 connman_error("Problem with timer server channel");
349                 channel_watch = 0;
350                 return FALSE;
351         }
352
353         fd = g_io_channel_unix_get_fd(channel);
354
355         iov.iov_base = buf;
356         iov.iov_len = sizeof(buf);
357
358         memset(&msg, 0, sizeof(msg));
359         msg.msg_iov = &iov;
360         msg.msg_iovlen = 1;
361         msg.msg_control = aux;
362         msg.msg_controllen = sizeof(aux);
363
364         len = recvmsg(fd, &msg, MSG_DONTWAIT);
365         if (len < 0)
366                 return TRUE;
367
368         tv = NULL;
369         clock_gettime(CLOCK_MONOTONIC, &mrx_time);
370
371         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
372                 if (cmsg->cmsg_level != SOL_SOCKET)
373                         continue;
374
375                 switch (cmsg->cmsg_type) {
376                 case SCM_TIMESTAMP:
377                         tv = (struct timeval *) CMSG_DATA(cmsg);
378                         break;
379                 }
380         }
381
382         decode_msg(iov.iov_base, iov.iov_len, tv, &mrx_time);
383
384         return TRUE;
385 }
386
387 static void start_ntp(char *server)
388 {
389         GIOChannel *channel;
390         struct sockaddr_in addr;
391         int tos = IPTOS_LOWDELAY, timestamp = 1;
392
393         if (server == NULL)
394                 return;
395
396         DBG("server %s", server);
397
398         if (channel_watch > 0)
399                 goto send;
400
401         transmit_fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
402         if (transmit_fd < 0) {
403                 connman_error("Failed to open time server socket");
404                 return;
405         }
406
407         memset(&addr, 0, sizeof(addr));
408         addr.sin_family = AF_INET;
409
410         if (bind(transmit_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
411                 connman_error("Failed to bind time server socket");
412                 close(transmit_fd);
413                 return;
414         }
415
416         if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
417                 connman_error("Failed to set type of service option");
418                 close(transmit_fd);
419                 return;
420         }
421
422         if (setsockopt(transmit_fd, SOL_SOCKET, SO_TIMESTAMP, &timestamp,
423                                                 sizeof(timestamp)) < 0) {
424                 connman_error("Failed to enable timestamp support");
425                 close(transmit_fd);
426                 return;
427         }
428
429         channel = g_io_channel_unix_new(transmit_fd);
430         if (channel == NULL) {
431                 close(transmit_fd);
432                 return;
433         }
434
435         g_io_channel_set_encoding(channel, NULL, NULL);
436         g_io_channel_set_buffered(channel, FALSE);
437
438         g_io_channel_set_close_on_unref(channel, TRUE);
439
440         channel_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
441                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
442                                 received_data, NULL, NULL);
443
444         g_io_channel_unref(channel);
445
446 send:
447         send_packet(transmit_fd, server);
448 }
449
450 int __connman_ntp_start(char *server)
451 {
452         DBG("%s", server);
453
454         if (server == NULL)
455                 return -EINVAL;
456
457         if (timeserver != NULL)
458                 g_free(timeserver);
459
460         timeserver = g_strdup(server);
461
462         start_ntp(timeserver);
463
464         return 0;
465 }
466
467 void __connman_ntp_stop()
468 {
469         DBG("");
470
471         if (poll_id > 0)
472                 g_source_remove(poll_id);
473
474         reset_timeout();
475
476         if (channel_watch > 0) {
477                 g_source_remove(channel_watch);
478                 channel_watch = 0;
479                 transmit_fd = 0;
480         }
481
482         if (timeserver != NULL) {
483                 g_free(timeserver);
484                 timeserver = NULL;
485         }
486 }