Merge "Modified logic to process each VSIE of all vendors." into tizen
[platform/upstream/connman.git] / src / ntp.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2014  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_FLAG_VN_VER3       3
97 #define NTP_FLAG_VN_VER4       4
98
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)))
103
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))
107
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
114
115 static guint channel_watch = 0;
116 static struct timespec mtx_time;
117 static int transmit_fd = 0;
118
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;
124
125 static void send_packet(int fd, const char *server, uint32_t timeout);
126
127 static void next_server(void)
128 {
129         if (timeserver) {
130                 g_free(timeserver);
131                 timeserver = NULL;
132         }
133
134         __connman_timeserver_sync_next();
135 }
136
137 static gboolean send_timeout(gpointer user_data)
138 {
139         uint32_t timeout = GPOINTER_TO_UINT(user_data);
140
141         DBG("send timeout %u (retries %d)", timeout, retries);
142
143         if (retries++ == NTP_SEND_RETRIES)
144                 next_server();
145         else
146                 send_packet(transmit_fd, timeserver, timeout << 1);
147
148         return FALSE;
149 }
150
151 static void send_packet(int fd, const char *server, uint32_t timeout)
152 {
153         struct ntp_msg msg;
154         struct sockaddr_in addr;
155         struct timeval transmit_timeval;
156         ssize_t len;
157
158         /*
159          * At some point, we could specify the actual system precision with:
160          *
161          *   clock_getres(CLOCK_REALTIME, &ts);
162          *   msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
163          */
164         memset(&msg, 0, sizeof(msg));
165         msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
166             NTP_FLAG_MD_CLIENT);
167         msg.poll = 4;   // min
168         msg.poll = 10;  // max
169         msg.precision = NTP_PRECISION_S;
170
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);
175
176         gettimeofday(&transmit_timeval, NULL);
177         clock_gettime(CLOCK_MONOTONIC, &mtx_time);
178
179         msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
180         msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
181
182         len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
183                                                 &addr, sizeof(addr));
184         if (len < 0) {
185                 connman_error("Time request for server %s failed (%d/%s)",
186                         server, errno, strerror(errno));
187
188                 if (errno == ENETUNREACH)
189                         __connman_timeserver_sync_next();
190
191                 return;
192         }
193
194         if (len != sizeof(msg)) {
195                 connman_error("Broken time request for server %s", server);
196                 return;
197         }
198
199         /*
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.
203          */
204
205         timeout_id = g_timeout_add_seconds(timeout, send_timeout,
206                                         GUINT_TO_POINTER(timeout));
207 }
208
209 static gboolean next_poll(gpointer user_data)
210 {
211         poll_id = 0;
212
213         if (!timeserver || transmit_fd == 0)
214                 return FALSE;
215
216         send_packet(transmit_fd, timeserver, NTP_SEND_TIMEOUT);
217
218         return FALSE;
219 }
220
221 static void reset_timeout(void)
222 {
223         if (timeout_id > 0) {
224                 g_source_remove(timeout_id);
225                 timeout_id = 0;
226         }
227
228         retries = 0;
229 }
230
231 static void decode_msg(void *base, size_t len, struct timeval *tv,
232                 struct timespec *mrx_time)
233 {
234         struct ntp_msg *msg = base;
235         double m_delta, org, rec, xmt, dst;
236         double delay, offset;
237         static guint transmit_delay;
238
239         if (len < sizeof(*msg)) {
240                 connman_error("Invalid response from time server");
241                 return;
242         }
243
244         if (!tv) {
245                 connman_error("Invalid packet timestamp from time server");
246                 return;
247         }
248
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);
260
261         if (!msg->stratum) {
262                 /* RFC 4330 ch 8 Kiss-of-Death packet */
263                 uint32_t code = ntohl(msg->refid);
264
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);
268                 next_server();
269                 return;
270         }
271
272         transmit_delay = LOGTOD(msg->poll);
273
274         if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
275                 DBG("ignoring unsynchronized peer");
276                 return;
277         }
278
279
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));
284                 } else {
285                         DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
286                         return;
287                 }
288         }
289
290         if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) {
291                 DBG("unsupported mode %d", NTP_FLAGS_MD_DECODE(msg->flags));
292                 return;
293         }
294
295         m_delta = mrx_time->tv_sec - mtx_time.tv_sec +
296                 1.0e-9 * (mrx_time->tv_nsec - mtx_time.tv_nsec);
297
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;
304
305         DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
306
307         offset = ((rec - org) + (xmt - dst)) / 2;
308         delay = (dst - org) - (xmt - rec);
309
310         DBG("offset=%f delay=%f", offset, delay);
311
312         /* Remove the timeout, as timeserver has responded */
313
314         reset_timeout();
315
316         /*
317          * Now poll the server every transmit_delay seconds
318          * for time correction.
319          */
320         if (poll_id > 0)
321                 g_source_remove(poll_id);
322
323         DBG("Timeserver %s, next sync in %d seconds", timeserver, transmit_delay);
324
325         poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
326
327         connman_info("ntp: time slew %+.6f s", offset);
328
329 #if defined TIZEN_EXT
330         //send the dbus message to alram-manager
331         {
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"
336
337                 struct timespec cur = {0};
338                 struct timespec req = {0};
339                 double dtime;
340
341                 DBusConnection *connection = NULL;
342                 DBusMessage *msg = NULL, *reply = NULL;
343                 DBusError error;
344
345                 dbus_error_init(&error);
346
347                 connection = connman_dbus_get_connection();
348                 if(!connection){
349                         DBG("dbus connection does not exist");
350                         return;
351                 }
352
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;
357
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);
367                 if(reply == NULL){
368                         if(dbus_error_is_set(&error)){
369                                 DBG("%s", error.message);
370                                 dbus_error_free(&error);
371                         }
372                         else{
373                                 DBG("Failed to request set time");
374                         }
375                         dbus_connection_unref(connection);
376                         dbus_message_unref(msg);
377                         return;
378                 }
379
380                 dbus_message_unref(msg);
381                 dbus_message_unref(reply);
382                 dbus_connection_unref(connection);
383
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);
386                 DBG("setting time");
387         }
388 #else
389         if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
390                 struct timeval adj;
391
392                 adj.tv_sec = (long) offset;
393                 adj.tv_usec = (offset - adj.tv_sec) * 1000000;
394
395                 DBG("adjusting time");
396
397                 if (adjtime(&adj, &adj) < 0) {
398                         connman_error("Failed to adjust time");
399                         return;
400                 }
401
402                 DBG("%lu seconds, %lu msecs", adj.tv_sec, adj.tv_usec);
403         } else {
404                 struct timeval cur;
405                 double dtime;
406
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;
411
412                 DBG("setting time");
413
414                 if (settimeofday(&cur, NULL) < 0) {
415                         connman_error("Failed to set time");
416                         return;
417                 }
418
419                 DBG("%lu seconds, %lu msecs", cur.tv_sec, cur.tv_usec);
420         }
421 #endif
422 }
423
424 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
425                                                         gpointer user_data)
426 {
427         unsigned char buf[128];
428         struct sockaddr_in sender_addr;
429         struct msghdr msg;
430         struct iovec iov;
431         struct cmsghdr *cmsg;
432         struct timeval *tv;
433         struct timespec mrx_time;
434         char aux[128];
435         ssize_t len;
436         int fd;
437
438         if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
439                 connman_error("Problem with timer server channel");
440                 channel_watch = 0;
441                 return FALSE;
442         }
443
444         fd = g_io_channel_unix_get_fd(channel);
445
446         iov.iov_base = buf;
447         iov.iov_len = sizeof(buf);
448
449         memset(&msg, 0, sizeof(msg));
450         msg.msg_iov = &iov;
451         msg.msg_iovlen = 1;
452         msg.msg_control = aux;
453         msg.msg_controllen = sizeof(aux);
454         msg.msg_name = &sender_addr;
455         msg.msg_namelen = sizeof(sender_addr);
456
457         len = recvmsg(fd, &msg, MSG_DONTWAIT);
458         if (len < 0)
459                 return TRUE;
460
461         if (timeserver_addr.sin_addr.s_addr != sender_addr.sin_addr.s_addr)
462                 /* only accept messages from the timeserver */
463                 return TRUE;
464
465         tv = NULL;
466         clock_gettime(CLOCK_MONOTONIC, &mrx_time);
467
468         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
469                 if (cmsg->cmsg_level != SOL_SOCKET)
470                         continue;
471
472                 switch (cmsg->cmsg_type) {
473                 case SCM_TIMESTAMP:
474                         tv = (struct timeval *) CMSG_DATA(cmsg);
475                         break;
476                 }
477         }
478
479         decode_msg(iov.iov_base, iov.iov_len, tv, &mrx_time);
480
481         return TRUE;
482 }
483
484 static void start_ntp(char *server)
485 {
486         GIOChannel *channel;
487         struct sockaddr_in addr;
488         int tos = IPTOS_LOWDELAY, timestamp = 1;
489
490         if (!server)
491                 return;
492
493         DBG("server %s", server);
494
495         if (channel_watch > 0)
496                 goto send;
497
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");
501                 return;
502         }
503
504         memset(&addr, 0, sizeof(addr));
505         addr.sin_family = AF_INET;
506
507         if (bind(transmit_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
508                 connman_error("Failed to bind time server socket");
509                 close(transmit_fd);
510                 return;
511         }
512
513         if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
514                 connman_error("Failed to set type of service option");
515                 close(transmit_fd);
516                 return;
517         }
518
519         if (setsockopt(transmit_fd, SOL_SOCKET, SO_TIMESTAMP, &timestamp,
520                                                 sizeof(timestamp)) < 0) {
521                 connman_error("Failed to enable timestamp support");
522                 close(transmit_fd);
523                 return;
524         }
525
526         channel = g_io_channel_unix_new(transmit_fd);
527         if (!channel) {
528                 close(transmit_fd);
529                 return;
530         }
531
532         g_io_channel_set_encoding(channel, NULL, NULL);
533         g_io_channel_set_buffered(channel, FALSE);
534
535         g_io_channel_set_close_on_unref(channel, TRUE);
536
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);
540
541         g_io_channel_unref(channel);
542
543 send:
544         send_packet(transmit_fd, server, NTP_SEND_TIMEOUT);
545 }
546
547 int __connman_ntp_start(char *server)
548 {
549         DBG("%s", server);
550
551         if (!server)
552                 return -EINVAL;
553
554         if (timeserver)
555                 g_free(timeserver);
556
557         timeserver = g_strdup(server);
558         timeserver_addr.sin_addr.s_addr = inet_addr(server);
559
560         start_ntp(timeserver);
561
562         return 0;
563 }
564
565 void __connman_ntp_stop()
566 {
567         DBG("");
568
569         if (poll_id > 0) {
570                 g_source_remove(poll_id);
571                 poll_id = 0;
572         }
573
574         reset_timeout();
575
576         if (channel_watch > 0) {
577                 g_source_remove(channel_watch);
578                 channel_watch = 0;
579                 transmit_fd = 0;
580         }
581
582         if (timeserver) {
583                 g_free(timeserver);
584                 timeserver = NULL;
585         }
586 }