ccea3ea55e55b5ca236165e2656198eeb99dd6cd
[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 #include <errno.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/time.h>
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>
37 #include <netdb.h>
38
39 #include <glib.h>
40
41 #include "connman.h"
42
43 struct ntp_short {
44         uint16_t seconds;
45         uint16_t fraction;
46 } __attribute__ ((packed));
47
48 struct ntp_time {
49         uint32_t seconds;
50         uint32_t fraction;
51 } __attribute__ ((packed));
52
53 struct ntp_msg {
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));
66
67 #define OFFSET_1900_1970  2208988800UL  /* 1970 - 1900 in seconds */
68
69 #define STEPTIME_MIN_OFFSET  0.4
70
71 #define LOGTOD(a)  ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
72 #define NSEC_PER_SEC  ((uint64_t)1000000000ULL)
73 #ifndef ADJ_SETOFFSET
74 #define ADJ_SETOFFSET           0x0100  /* add 'time' to current time */
75 #endif
76
77 #define NTP_SEND_TIMEOUT       2
78 #define NTP_SEND_RETRIES       3
79
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
86
87 #define NTP_FLAG_VN_SHIFT      3
88 #define NTP_FLAG_VN_MASK       0x7
89
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
100
101 #define NTP_FLAG_VN_VER3       3
102 #define NTP_FLAG_VN_VER4       4
103
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)))
108
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))
112
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
119
120 struct ntp_data {
121         char *timeserver;
122         struct sockaddr_in6 timeserver_addr;
123         struct timespec mtx_time;
124         int transmit_fd;
125         gint timeout_id;
126         guint retries;
127         guint channel_watch;
128         gint poll_id;
129         uint32_t timeout;
130         __connman_ntp_cb_t cb;
131         void *user_data;
132 };
133
134 static struct ntp_data *ntp_data;
135
136 static void free_ntp_data(struct ntp_data *nd)
137 {
138         if (nd->poll_id)
139                 g_source_remove(nd->poll_id);
140         if (nd->timeout_id)
141                 g_source_remove(nd->timeout_id);
142         if (nd->channel_watch)
143                 g_source_remove(nd->channel_watch);
144         if (nd->timeserver)
145                 g_free(nd->timeserver);
146         g_free(nd);
147 }
148
149 static void send_packet(struct ntp_data *nd, struct sockaddr *server,
150                         uint32_t timeout);
151
152 static gboolean send_timeout(gpointer user_data)
153 {
154         struct ntp_data *nd = user_data;
155
156         DBG("send timeout %u (retries %d)", nd->timeout, nd->retries);
157
158         if (nd->retries++ == NTP_SEND_RETRIES)
159                 nd->cb(false, nd->user_data);
160         else
161                 send_packet(nd, (struct sockaddr *)&nd->timeserver_addr,
162                         nd->timeout << 1);
163
164         return FALSE;
165 }
166
167 static void send_packet(struct ntp_data *nd, struct sockaddr *server,
168                         uint32_t timeout)
169 {
170         struct ntp_msg msg;
171         struct timeval transmit_timeval;
172         ssize_t len;
173         void * addr;
174         int size;
175         char ipaddrstring[INET6_ADDRSTRLEN + 1];
176
177         /*
178          * At some point, we could specify the actual system precision with:
179          *
180          *   clock_getres(CLOCK_REALTIME, &ts);
181          *   msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
182          */
183         memset(&msg, 0, sizeof(msg));
184         msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
185             NTP_FLAG_MD_CLIENT);
186         msg.poll = 10;
187         msg.precision = NTP_PRECISION_S;
188
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;
195         } else {
196                 DBG("Family is neither ipv4 nor ipv6");
197                 nd->cb(false, nd->user_data);
198                 return;
199         }
200
201         gettimeofday(&transmit_timeval, NULL);
202         clock_gettime(CLOCK_MONOTONIC, &nd->mtx_time);
203
204         msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
205         msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
206
207         len = sendto(nd->transmit_fd, &msg, sizeof(msg), MSG_DONTWAIT,
208                                                 server, size);
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);
213                 return;
214         }
215
216         /*
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.
220          */
221
222         nd->timeout = timeout;
223         nd->timeout_id = g_timeout_add_seconds(timeout, send_timeout, nd);
224 }
225
226 static gboolean next_poll(gpointer user_data)
227 {
228         struct ntp_data *nd = user_data;
229         nd->poll_id = 0;
230
231         if (!nd->timeserver || nd->transmit_fd == 0)
232                 return FALSE;
233
234         send_packet(nd, (struct sockaddr *)&nd->timeserver_addr, NTP_SEND_TIMEOUT);
235
236         return FALSE;
237 }
238
239 static void reset_timeout(struct ntp_data *nd)
240 {
241         if (nd->timeout_id > 0) {
242                 g_source_remove(nd->timeout_id);
243                 nd->timeout_id = 0;
244         }
245
246         nd->retries = 0;
247 }
248
249 static void decode_msg(struct ntp_data *nd, void *base, size_t len,
250                 struct timeval *tv, struct timespec *mrx_time)
251 {
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 = {};
258 #endif
259
260         if (len < sizeof(*msg)) {
261                 connman_error("Invalid response from time server");
262                 return;
263         }
264
265         if (!tv) {
266                 connman_error("Invalid packet timestamp from time server");
267                 return;
268         }
269
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);
281
282         if (!msg->stratum) {
283                 /* RFC 4330 ch 8 Kiss-of-Death packet */
284                 uint32_t code = ntohl(msg->refid);
285
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);
290                 return;
291         }
292
293         transmit_delay = LOGTOD(msg->poll);
294
295         if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
296                 DBG("ignoring unsynchronized peer");
297                 nd->cb(false, nd->user_data);
298                 return;
299         }
300
301
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));
306                 } else {
307                         DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
308                         nd->cb(false, nd->user_data);
309                         return;
310                 }
311         }
312
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);
316                 return;
317         }
318
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);
321
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;
328
329         DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
330
331         offset = ((rec - org) + (xmt - dst)) / 2;
332         delay = (dst - org) - (xmt - rec);
333
334         DBG("offset=%f delay=%f", offset, delay);
335
336         /* Remove the timeout, as timeserver has responded */
337
338         reset_timeout(nd);
339
340         /*
341          * Now poll the server every transmit_delay seconds
342          * for time correction.
343          */
344         if (nd->poll_id > 0)
345                 g_source_remove(nd->poll_id);
346
347         DBG("Timeserver %s, next sync in %d seconds", nd->timeserver,
348                 transmit_delay);
349
350         nd->poll_id = g_timeout_add_seconds(transmit_delay, next_poll, nd);
351
352 #if defined TIZEN_EXT
353         //send the dbus message to alram-manager
354         {
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"
359
360                 struct timespec cur = {0};
361                 struct timespec req = {0};
362                 double dtime;
363
364                 DBusConnection *connection = NULL;
365                 DBusMessage *msg = NULL, *reply = NULL;
366                 DBusError error;
367
368                 dbus_error_init(&error);
369
370                 connection = connman_dbus_get_connection();
371                 if(!connection){
372                         DBG("dbus connection does not exist");
373                         return;
374                 }
375
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;
380
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_INT64, &(cur.tv_sec),
385                         DBUS_TYPE_INT64, &(cur.tv_nsec),
386                         DBUS_TYPE_INT64, &(req.tv_sec),
387                         DBUS_TYPE_INT64, &(req.tv_nsec), DBUS_TYPE_INVALID);
388                 reply = dbus_connection_send_with_reply_and_block(connection, msg,
389                                 DBUS_TIMEOUT_USE_DEFAULT, &error);
390                 if(reply == NULL){
391                         if(dbus_error_is_set(&error)){
392                                 DBG("%s", error.message);
393                                 dbus_error_free(&error);
394                         }
395                         else{
396                                 DBG("Failed to request set time");
397                         }
398                         dbus_connection_unref(connection);
399                         dbus_message_unref(msg);
400                         return;
401                 }
402
403                 dbus_message_unref(msg);
404                 dbus_message_unref(reply);
405                 dbus_connection_unref(connection);
406
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);
409                 DBG("setting time");
410         }
411 #else
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;
417                 tmx.maxerror = 0;
418                 tmx.esterror = 0;
419
420                 connman_info("ntp: adjust (slew): %+.6f sec", offset);
421         } else {
422                 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
423
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;
427                 tmx.maxerror = 0;
428                 tmx.esterror = 0;
429
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;
434                 }
435
436                 connman_info("ntp: adjust (jump): %+.6f sec", offset);
437         }
438
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;
443
444         if (adjtimex(&tmx) < 0) {
445                 connman_error("Failed to adjust time: %s (%d)", strerror(errno), errno);
446                 nd->cb(false, nd->user_data);
447                 return;
448         }
449
450         DBG("interval/delta/delay/drift %fs/%+.3fs/%.3fs/%+ldppm",
451                 LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
452
453         nd->cb(true, nd->user_data);
454 #endif
455 }
456
457 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
458                                                         gpointer user_data)
459 {
460         struct ntp_data *nd = user_data;
461         unsigned char buf[128];
462         struct sockaddr_in6 sender_addr;
463         struct msghdr msg;
464         struct iovec iov;
465         struct cmsghdr *cmsg;
466         struct timeval *tv;
467         struct timespec mrx_time;
468         char aux[128];
469         ssize_t len;
470         int fd;
471         int size;
472         void * addr_ptr;
473         void * src_ptr;
474
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;
478                 return FALSE;
479         }
480
481         fd = g_io_channel_unix_get_fd(channel);
482
483         iov.iov_base = buf;
484         iov.iov_len = sizeof(buf);
485
486         memset(&msg, 0, sizeof(msg));
487         msg.msg_iov = &iov;
488         msg.msg_iovlen = 1;
489         msg.msg_control = aux;
490         msg.msg_controllen = sizeof(aux);
491         msg.msg_name = &sender_addr;
492         msg.msg_namelen = sizeof(sender_addr);
493
494         len = recvmsg(fd, &msg, MSG_DONTWAIT);
495         if (len < 0)
496                 return TRUE;
497
498         if (sender_addr.sin6_family == AF_INET) {
499                 size = 4;
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) {
503                 size = 16;
504                 addr_ptr = &((struct sockaddr_in6 *)&nd->timeserver_addr)->sin6_addr;
505                 src_ptr = &((struct sockaddr_in6 *)&sender_addr)->sin6_addr;
506         } else {
507                 connman_error("Not a valid family type");
508                 return TRUE;
509         }
510
511         if(memcmp(addr_ptr, src_ptr, size) != 0)
512                 return TRUE;
513
514         tv = NULL;
515         clock_gettime(CLOCK_MONOTONIC, &mrx_time);
516
517         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
518                 if (cmsg->cmsg_level != SOL_SOCKET)
519                         continue;
520
521                 switch (cmsg->cmsg_type) {
522                 case SCM_TIMESTAMP:
523                         tv = (struct timeval *) CMSG_DATA(cmsg);
524                         break;
525                 }
526         }
527
528         decode_msg(nd, iov.iov_base, iov.iov_len, tv, &mrx_time);
529
530         return TRUE;
531 }
532
533 static void start_ntp(struct ntp_data *nd)
534 {
535         GIOChannel *channel;
536         struct addrinfo hint;
537         struct addrinfo *info;
538         struct sockaddr * addr;
539         struct sockaddr_in  * in4addr;
540         struct sockaddr_in6 in6addr;
541         int size;
542         int family;
543         int tos = IPTOS_LOWDELAY, timestamp = 1;
544         int ret;
545
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);
551
552         if (ret) {
553                 connman_error("cannot get server info");
554                 return;
555         }
556
557         family = info->ai_family;
558
559         memcpy(&ntp_data->timeserver_addr, info->ai_addr, info->ai_addrlen);
560         freeaddrinfo(info);
561         memset(&in6addr, 0, sizeof(in6addr));
562
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);
574         } else {
575                 connman_error("Family is neither ipv4 nor ipv6");
576                 return;
577         }
578
579         DBG("server %s family %d", nd->timeserver, family);
580
581         if (nd->channel_watch > 0)
582                 goto send;
583
584         nd->transmit_fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
585
586         if (nd->transmit_fd <= 0) {
587                 if (errno != EAFNOSUPPORT)
588                         connman_error("Failed to open time server socket");
589         }
590
591         if (bind(nd->transmit_fd, (struct sockaddr *) addr, size) < 0) {
592                 connman_error("Failed to bind time server socket");
593                 goto err;
594         }
595
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");
599                         goto err;
600                 }
601         }
602
603         if (setsockopt(nd->transmit_fd, SOL_SOCKET, SO_TIMESTAMP, &timestamp,
604                                                 sizeof(timestamp)) < 0) {
605                 connman_error("Failed to enable timestamp support");
606                 goto err;
607         }
608
609         channel = g_io_channel_unix_new(nd->transmit_fd);
610         if (!channel)
611                 goto err;
612
613         g_io_channel_set_encoding(channel, NULL, NULL);
614         g_io_channel_set_buffered(channel, FALSE);
615
616         g_io_channel_set_close_on_unref(channel, TRUE);
617
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);
621
622         g_io_channel_unref(channel);
623
624 send:
625         send_packet(nd, (struct sockaddr*)&ntp_data->timeserver_addr,
626                 NTP_SEND_TIMEOUT);
627         return;
628
629 err:
630         if (nd->transmit_fd > 0)
631                 close(nd->transmit_fd);
632
633         nd->cb(false, nd->user_data);
634 }
635
636 int __connman_ntp_start(char *server, __connman_ntp_cb_t callback,
637                         void *user_data)
638 {
639         if (!server)
640                 return -EINVAL;
641
642         if (ntp_data) {
643                 connman_warn("ntp_data is not NULL (timerserver %s)",
644                         ntp_data->timeserver);
645                 free_ntp_data(ntp_data);
646         }
647
648         ntp_data = g_new0(struct ntp_data, 1);
649
650         ntp_data->timeserver = g_strdup(server);
651         ntp_data->cb = callback;
652         ntp_data->user_data = user_data;
653
654         start_ntp(ntp_data);
655
656         return 0;
657 }
658
659 void __connman_ntp_stop()
660 {
661         if (ntp_data) {
662                 free_ntp_data(ntp_data);
663                 ntp_data = NULL;
664         }
665 }