Updated connman to version 1.35
[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/timex.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39
40 #include <glib.h>
41
42 #include "connman.h"
43
44 struct ntp_short {
45         uint16_t seconds;
46         uint16_t fraction;
47 } __attribute__ ((packed));
48
49 struct ntp_time {
50         uint32_t seconds;
51         uint32_t fraction;
52 } __attribute__ ((packed));
53
54 struct ntp_msg {
55         uint8_t flags;                  /* Mode, version and leap indicator */
56         uint8_t stratum;                /* Stratum details */
57         int8_t poll;                    /* Maximum interval in log2 seconds */
58         int8_t precision;               /* Clock precision in log2 seconds */
59         struct ntp_short rootdelay;     /* Root delay */
60         struct ntp_short rootdisp;      /* Root dispersion */
61         uint32_t refid;                 /* Reference ID */
62         struct ntp_time reftime;        /* Reference timestamp */
63         struct ntp_time orgtime;        /* Origin timestamp */
64         struct ntp_time rectime;        /* Receive timestamp */
65         struct ntp_time xmttime;        /* Transmit timestamp */
66 } __attribute__ ((packed));
67
68 #define OFFSET_1900_1970  2208988800UL  /* 1970 - 1900 in seconds */
69
70 #define STEPTIME_MIN_OFFSET  0.4
71
72 #define LOGTOD(a)  ((a) < 0 ? 1. / (1L << -(a)) : 1L << (int)(a))
73 #define NSEC_PER_SEC  ((uint64_t)1000000000ULL)
74 #ifndef ADJ_SETOFFSET
75 #define ADJ_SETOFFSET           0x0100  /* add 'time' to current time */
76 #endif
77
78 #define NTP_SEND_TIMEOUT       2
79 #define NTP_SEND_RETRIES       3
80
81 #define NTP_FLAG_LI_SHIFT      6
82 #define NTP_FLAG_LI_MASK       0x3
83 #define NTP_FLAG_LI_NOWARNING  0x0
84 #define NTP_FLAG_LI_ADDSECOND  0x1
85 #define NTP_FLAG_LI_DELSECOND  0x2
86 #define NTP_FLAG_LI_NOTINSYNC  0x3
87
88 #define NTP_FLAG_VN_SHIFT      3
89 #define NTP_FLAG_VN_MASK       0x7
90
91 #define NTP_FLAG_MD_SHIFT      0
92 #define NTP_FLAG_MD_MASK       0x7
93 #define NTP_FLAG_MD_UNSPEC     0
94 #define NTP_FLAG_MD_ACTIVE     1
95 #define NTP_FLAG_MD_PASSIVE    2
96 #define NTP_FLAG_MD_CLIENT     3
97 #define NTP_FLAG_MD_SERVER     4
98 #define NTP_FLAG_MD_BROADCAST  5
99 #define NTP_FLAG_MD_CONTROL    6
100 #define NTP_FLAG_MD_PRIVATE    7
101
102 #define NTP_FLAG_VN_VER3       3
103 #define NTP_FLAG_VN_VER4       4
104
105 #define NTP_FLAGS_ENCODE(li, vn, md)  ((uint8_t)( \
106                       (((li) & NTP_FLAG_LI_MASK) << NTP_FLAG_LI_SHIFT) | \
107                       (((vn) & NTP_FLAG_VN_MASK) << NTP_FLAG_VN_SHIFT) | \
108                       (((md) & NTP_FLAG_MD_MASK) << NTP_FLAG_MD_SHIFT)))
109
110 #define NTP_FLAGS_LI_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_LI_SHIFT) & NTP_FLAG_LI_MASK))
111 #define NTP_FLAGS_VN_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_VN_SHIFT) & NTP_FLAG_VN_MASK))
112 #define NTP_FLAGS_MD_DECODE(flags)    ((uint8_t)(((flags) >> NTP_FLAG_MD_SHIFT) & NTP_FLAG_MD_MASK))
113
114 #define NTP_PRECISION_S    0
115 #define NTP_PRECISION_DS   -3
116 #define NTP_PRECISION_CS   -6
117 #define NTP_PRECISION_MS   -9
118 #define NTP_PRECISION_US   -19
119 #define NTP_PRECISION_NS   -29
120
121 static guint channel_watch = 0;
122 static struct timespec mtx_time;
123 static int transmit_fd = 0;
124
125 static char *timeserver = NULL;
126 static struct sockaddr_in6 timeserver_addr;
127 static gint poll_id = 0;
128 static gint timeout_id = 0;
129 static guint retries = 0;
130
131 static void send_packet(int fd, struct sockaddr *server, uint32_t timeout);
132
133 static void next_server(void)
134 {
135         if (timeserver) {
136                 g_free(timeserver);
137                 timeserver = NULL;
138         }
139
140         __connman_timeserver_sync_next();
141 }
142
143 static gboolean send_timeout(gpointer user_data)
144 {
145         uint32_t timeout = GPOINTER_TO_UINT(user_data);
146
147         DBG("send timeout %u (retries %d)", timeout, retries);
148
149         if (retries++ == NTP_SEND_RETRIES)
150                 next_server();
151         else
152                 send_packet(transmit_fd, (struct sockaddr *)&timeserver_addr, timeout << 1);
153
154         return FALSE;
155 }
156
157 static void send_packet(int fd, struct sockaddr *server, uint32_t timeout)
158 {
159         struct ntp_msg msg;
160         struct timeval transmit_timeval;
161         ssize_t len;
162         void * addr;
163         int size;
164         char ipaddrstring[INET6_ADDRSTRLEN + 1];
165
166         /*
167          * At some point, we could specify the actual system precision with:
168          *
169          *   clock_getres(CLOCK_REALTIME, &ts);
170          *   msg.precision = (int)log2(ts.tv_sec + (ts.tv_nsec * 1.0e-9));
171          */
172         memset(&msg, 0, sizeof(msg));
173         msg.flags = NTP_FLAGS_ENCODE(NTP_FLAG_LI_NOTINSYNC, NTP_FLAG_VN_VER4,
174             NTP_FLAG_MD_CLIENT);
175         msg.poll = 10;
176         msg.precision = NTP_PRECISION_S;
177
178         if (server->sa_family == AF_INET) {
179                 size = sizeof(struct sockaddr_in);
180                 addr = (void *)&(((struct sockaddr_in *)&timeserver_addr)->sin_addr);
181         } else if (server->sa_family == AF_INET6) {
182                 size = sizeof(struct sockaddr_in6);
183                 addr = (void *)&timeserver_addr.sin6_addr;
184         } else {
185                 connman_error("Family is neither ipv4 nor ipv6");
186                 return;
187         }
188
189         gettimeofday(&transmit_timeval, NULL);
190         clock_gettime(CLOCK_MONOTONIC, &mtx_time);
191
192         msg.xmttime.seconds = htonl(transmit_timeval.tv_sec + OFFSET_1900_1970);
193         msg.xmttime.fraction = htonl(transmit_timeval.tv_usec * 1000);
194
195         len = sendto(fd, &msg, sizeof(msg), MSG_DONTWAIT,
196                                                 server, size);
197
198         if (len < 0) {
199                 connman_error("Time request for server %s failed (%d/%s)",
200                         inet_ntop(server->sa_family, addr, ipaddrstring, sizeof(ipaddrstring)),
201                         errno, strerror(errno));
202
203                 if (errno == ENETUNREACH)
204                         __connman_timeserver_sync_next();
205
206                 return;
207         }
208
209         if (len != sizeof(msg)) {
210                 connman_error("Broken time request for server %s",
211                         inet_ntop(server->sa_family, addr, ipaddrstring, sizeof(ipaddrstring)));
212                 return;
213         }
214
215         /*
216          * Add an exponential retry timeout to retry the existing
217          * request. After a set number of retries, we'll fallback to
218          * trying another server.
219          */
220
221         timeout_id = g_timeout_add_seconds(timeout, send_timeout,
222                                         GUINT_TO_POINTER(timeout));
223 }
224
225 static gboolean next_poll(gpointer user_data)
226 {
227         poll_id = 0;
228
229         if (!timeserver || transmit_fd == 0)
230                 return FALSE;
231
232         send_packet(transmit_fd, (struct sockaddr *)&timeserver_addr, NTP_SEND_TIMEOUT);
233
234         return FALSE;
235 }
236
237 static void reset_timeout(void)
238 {
239         if (timeout_id > 0) {
240                 g_source_remove(timeout_id);
241                 timeout_id = 0;
242         }
243
244         retries = 0;
245 }
246
247 static void decode_msg(void *base, size_t len, struct timeval *tv,
248                 struct timespec *mrx_time)
249 {
250         struct ntp_msg *msg = base;
251         double m_delta, org, rec, xmt, dst;
252         double delay, offset;
253         static guint transmit_delay;
254 #if !defined TIZEN_EXT
255         struct timex tmx = {};
256 #endif
257         if (len < sizeof(*msg)) {
258                 connman_error("Invalid response from time server");
259                 return;
260         }
261
262         if (!tv) {
263                 connman_error("Invalid packet timestamp from time server");
264                 return;
265         }
266
267         DBG("flags      : 0x%02x", msg->flags);
268         DBG("stratum    : %u", msg->stratum);
269         DBG("poll       : %f seconds (%d)",
270                                 LOGTOD(msg->poll), msg->poll);
271         DBG("precision  : %f seconds (%d)",
272                                 LOGTOD(msg->precision), msg->precision);
273         DBG("root delay : %u seconds (fraction %u)",
274                         msg->rootdelay.seconds, msg->rootdelay.fraction);
275         DBG("root disp. : %u seconds (fraction %u)",
276                         msg->rootdisp.seconds, msg->rootdisp.fraction);
277         DBG("reference  : 0x%04x", msg->refid);
278
279         if (!msg->stratum) {
280                 /* RFC 4330 ch 8 Kiss-of-Death packet */
281                 uint32_t code = ntohl(msg->refid);
282
283                 connman_info("Skipping server %s KoD code %c%c%c%c",
284                         timeserver, code >> 24, code >> 16 & 0xff,
285                         code >> 8 & 0xff, code & 0xff);
286                 next_server();
287                 return;
288         }
289
290         transmit_delay = LOGTOD(msg->poll);
291
292         if (NTP_FLAGS_LI_DECODE(msg->flags) == NTP_FLAG_LI_NOTINSYNC) {
293                 DBG("ignoring unsynchronized peer");
294                 return;
295         }
296
297
298         if (NTP_FLAGS_VN_DECODE(msg->flags) != NTP_FLAG_VN_VER4) {
299                 if (NTP_FLAGS_VN_DECODE(msg->flags) == NTP_FLAG_VN_VER3) {
300                         DBG("requested version %d, accepting version %d",
301                                 NTP_FLAG_VN_VER4, NTP_FLAGS_VN_DECODE(msg->flags));
302                 } else {
303                         DBG("unsupported version %d", NTP_FLAGS_VN_DECODE(msg->flags));
304                         return;
305                 }
306         }
307
308         if (NTP_FLAGS_MD_DECODE(msg->flags) != NTP_FLAG_MD_SERVER) {
309                 DBG("unsupported mode %d", NTP_FLAGS_MD_DECODE(msg->flags));
310                 return;
311         }
312
313         m_delta = mrx_time->tv_sec - mtx_time.tv_sec +
314                 1.0e-9 * (mrx_time->tv_nsec - mtx_time.tv_nsec);
315
316         org = tv->tv_sec + (1.0e-6 * tv->tv_usec) - m_delta + OFFSET_1900_1970;
317         rec = ntohl(msg->rectime.seconds) +
318                         ((double) ntohl(msg->rectime.fraction) / UINT_MAX);
319         xmt = ntohl(msg->xmttime.seconds) +
320                         ((double) ntohl(msg->xmttime.fraction) / UINT_MAX);
321         dst = tv->tv_sec + (1.0e-6 * tv->tv_usec) + OFFSET_1900_1970;
322
323         DBG("org=%f rec=%f xmt=%f dst=%f", org, rec, xmt, dst);
324
325         offset = ((rec - org) + (xmt - dst)) / 2;
326         delay = (dst - org) - (xmt - rec);
327
328         DBG("offset=%f delay=%f", offset, delay);
329
330         /* Remove the timeout, as timeserver has responded */
331
332         reset_timeout();
333
334         /*
335          * Now poll the server every transmit_delay seconds
336          * for time correction.
337          */
338         if (poll_id > 0)
339                 g_source_remove(poll_id);
340
341         DBG("Timeserver %s, next sync in %d seconds", timeserver, transmit_delay);
342
343         poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
344
345 #if defined TIZEN_EXT
346         //send the dbus message to alram-manager
347         {
348 #define TIME_BUS_NAME "org.tizen.alarm.manager"
349 #define TIME_INTERFACE "org.tizen.alarm.manager"
350 #define TIME_PATH "/org/tizen/alarm/manager"
351 #define TIME_METHOD "alarm_set_time_with_propagation_delay"
352
353                 struct timespec cur = {0};
354                 struct timespec req = {0};
355                 double dtime;
356
357                 DBusConnection *connection = NULL;
358                 DBusMessage *msg = NULL, *reply = NULL;
359                 DBusError error;
360
361                 dbus_error_init(&error);
362
363                 connection = connman_dbus_get_connection();
364                 if(!connection){
365                         DBG("dbus connection does not exist");
366                         return;
367                 }
368
369                 clock_gettime(CLOCK_REALTIME, &cur);
370                 dtime = offset + cur.tv_sec + 1.0e-9 * cur.tv_nsec;
371                 cur.tv_sec = (long) dtime;
372                 cur.tv_nsec = (dtime - cur.tv_sec) * 1000000000;
373
374                 clock_gettime(CLOCK_REALTIME, &req);
375                 msg = dbus_message_new_method_call(TIME_BUS_NAME, TIME_PATH,
376                         TIME_INTERFACE, TIME_METHOD);
377                 dbus_message_append_args(msg, DBUS_TYPE_UINT32, &(cur.tv_sec),
378                         DBUS_TYPE_UINT32, &(cur.tv_nsec),
379                         DBUS_TYPE_UINT32, &(req.tv_sec),
380                         DBUS_TYPE_UINT32, &(req.tv_nsec), DBUS_TYPE_INVALID);
381                 reply = dbus_connection_send_with_reply_and_block(connection, msg,
382                                 DBUS_TIMEOUT_USE_DEFAULT, &error);
383                 if(reply == NULL){
384                         if(dbus_error_is_set(&error)){
385                                 DBG("%s", error.message);
386                                 dbus_error_free(&error);
387                         }
388                         else{
389                                 DBG("Failed to request set time");
390                         }
391                         dbus_connection_unref(connection);
392                         dbus_message_unref(msg);
393                         return;
394                 }
395
396                 dbus_message_unref(msg);
397                 dbus_message_unref(reply);
398                 dbus_connection_unref(connection);
399
400                 DBG("%lu cur seconds, %lu cur nsecs, %lu req seconds, %lu req nsecs",
401                         cur.tv_sec, cur.tv_nsec, req.tv_sec, req.tv_nsec);
402                 DBG("setting time");
403         }
404 #else
405         if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
406                 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
407                 tmx.status = STA_PLL;
408                 tmx.offset = offset * NSEC_PER_SEC;
409                 tmx.constant = msg->poll - 4;
410                 tmx.maxerror = 0;
411                 tmx.esterror = 0;
412
413                 connman_info("ntp: adjust (slew): %+.6f sec", offset);
414         } else {
415                 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR;
416
417                 /* ADJ_NANO uses nanoseconds in the microseconds field */
418                 tmx.time.tv_sec = (long)offset;
419                 tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
420                 tmx.maxerror = 0;
421                 tmx.esterror = 0;
422
423                 /* the kernel expects -0.3s as {-1, 7000.000.000} */
424                 if (tmx.time.tv_usec < 0) {
425                         tmx.time.tv_sec  -= 1;
426                         tmx.time.tv_usec += NSEC_PER_SEC;
427                 }
428
429                 connman_info("ntp: adjust (jump): %+.6f sec", offset);
430         }
431
432         if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_ADDSECOND)
433                 tmx.status |= STA_INS;
434         else if (NTP_FLAGS_LI_DECODE(msg->flags) & NTP_FLAG_LI_DELSECOND)
435                 tmx.status |= STA_DEL;
436
437         if (adjtimex(&tmx) < 0) {
438                 connman_error("Failed to adjust time");
439                 return;
440         }
441
442         DBG("interval/delta/delay/drift %fs/%+.3fs/%.3fs/%+ldppm",
443                         LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
444 #endif
445 }
446
447 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
448                                                         gpointer user_data)
449 {
450         unsigned char buf[128];
451         struct sockaddr_in6 sender_addr;
452         struct msghdr msg;
453         struct iovec iov;
454         struct cmsghdr *cmsg;
455         struct timeval *tv;
456         struct timespec mrx_time;
457         char aux[128];
458         ssize_t len;
459         int fd;
460         int size;
461         void * addr_ptr;
462         void * src_ptr;
463
464         if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
465                 connman_error("Problem with timer server channel");
466                 channel_watch = 0;
467                 return FALSE;
468         }
469
470         fd = g_io_channel_unix_get_fd(channel);
471
472         iov.iov_base = buf;
473         iov.iov_len = sizeof(buf);
474
475         memset(&msg, 0, sizeof(msg));
476         msg.msg_iov = &iov;
477         msg.msg_iovlen = 1;
478         msg.msg_control = aux;
479         msg.msg_controllen = sizeof(aux);
480         msg.msg_name = &sender_addr;
481         msg.msg_namelen = sizeof(sender_addr);
482
483         len = recvmsg(fd, &msg, MSG_DONTWAIT);
484         if (len < 0)
485                 return TRUE;
486
487         if (sender_addr.sin6_family == AF_INET) {
488                 size = 4;
489                 addr_ptr = &((struct sockaddr_in *)&timeserver_addr)->sin_addr;
490                 src_ptr = &((struct sockaddr_in *)&sender_addr)->sin_addr;
491         } else if (sender_addr.sin6_family == AF_INET6) {
492                 size = 16;
493                 addr_ptr = &((struct sockaddr_in6 *)&timeserver_addr)->sin6_addr;
494                 src_ptr = &((struct sockaddr_in6 *)&sender_addr)->sin6_addr;
495         } else {
496                 connman_error("Not a valid family type");
497                 return TRUE;
498         }
499
500         if(memcmp(addr_ptr, src_ptr, size) != 0)
501                 return TRUE;
502
503         tv = NULL;
504         clock_gettime(CLOCK_MONOTONIC, &mrx_time);
505
506         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
507                 if (cmsg->cmsg_level != SOL_SOCKET)
508                         continue;
509
510                 switch (cmsg->cmsg_type) {
511                 case SCM_TIMESTAMP:
512                         tv = (struct timeval *) CMSG_DATA(cmsg);
513                         break;
514                 }
515         }
516
517         decode_msg(iov.iov_base, iov.iov_len, tv, &mrx_time);
518
519         return TRUE;
520 }
521
522 static void start_ntp(char *server)
523 {
524         GIOChannel *channel;
525         struct addrinfo hint;
526         struct addrinfo *info;
527         struct sockaddr * addr;
528         struct sockaddr_in  * in4addr;
529         struct sockaddr_in6 in6addr;
530         int size;
531         int family;
532         int tos = IPTOS_LOWDELAY, timestamp = 1;
533         int ret;
534
535         if (!server)
536                 return;
537
538         memset(&hint, 0, sizeof(hint));
539         hint.ai_family = AF_UNSPEC;
540         hint.ai_socktype = SOCK_DGRAM;
541         hint.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
542         ret = getaddrinfo(server, NULL, &hint, &info);
543
544         if (ret) {
545                 connman_error("cannot get server info");
546                 return;
547         }
548
549         family = info->ai_family;
550
551         memcpy(&timeserver_addr, info->ai_addr, info->ai_addrlen);
552         freeaddrinfo(info);
553         memset(&in6addr, 0, sizeof(in6addr));
554
555         if (family == AF_INET) {
556                 ((struct sockaddr_in *)&timeserver_addr)->sin_port = htons(123);
557                 in4addr = (struct sockaddr_in *)&in6addr;
558                 in4addr->sin_family = family;
559                 addr = (struct sockaddr *)in4addr;
560                 size = sizeof(struct sockaddr_in);
561         } else if (family == AF_INET6) {
562                 timeserver_addr.sin6_port = htons(123);
563                 in6addr.sin6_family = family;
564                 addr = (struct sockaddr *)&in6addr;
565                 size = sizeof(in6addr);
566         } else {
567                 connman_error("Family is neither ipv4 nor ipv6");
568                 return;
569         }
570
571         DBG("server %s family %d", server, family);
572
573         if (channel_watch > 0)
574                 goto send;
575
576         transmit_fd = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
577
578         if (transmit_fd <= 0) {
579                 connman_error("Failed to open time server socket");
580                 return;
581         }
582
583         if (bind(transmit_fd, (struct sockaddr *) addr, size) < 0) {
584                 connman_error("Failed to bind time server socket");
585                 close(transmit_fd);
586                 return;
587         }
588
589         if (family == AF_INET) {
590                 if (setsockopt(transmit_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
591                         connman_error("Failed to set type of service option");
592                         close(transmit_fd);
593                         return;
594                 }
595         }
596
597         if (setsockopt(transmit_fd, SOL_SOCKET, SO_TIMESTAMP, &timestamp,
598                                                 sizeof(timestamp)) < 0) {
599                 connman_error("Failed to enable timestamp support");
600                 close(transmit_fd);
601                 return;
602         }
603
604         channel = g_io_channel_unix_new(transmit_fd);
605         if (!channel) {
606                 close(transmit_fd);
607                 return;
608         }
609
610         g_io_channel_set_encoding(channel, NULL, NULL);
611         g_io_channel_set_buffered(channel, FALSE);
612
613         g_io_channel_set_close_on_unref(channel, TRUE);
614
615         channel_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
616                                 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
617                                 received_data, NULL, NULL);
618
619         g_io_channel_unref(channel);
620
621 send:
622         send_packet(transmit_fd, (struct sockaddr*)&timeserver_addr, NTP_SEND_TIMEOUT);
623 }
624
625 int __connman_ntp_start(char *server)
626 {
627         DBG("%s", server);
628
629         if (!server)
630                 return -EINVAL;
631
632         if (timeserver)
633                 g_free(timeserver);
634
635         timeserver = g_strdup(server);
636
637         start_ntp(timeserver);
638
639         return 0;
640 }
641
642 void __connman_ntp_stop()
643 {
644         DBG("");
645
646         if (poll_id > 0) {
647                 g_source_remove(poll_id);
648                 poll_id = 0;
649         }
650
651         reset_timeout();
652
653         if (channel_watch > 0) {
654                 g_source_remove(channel_watch);
655                 channel_watch = 0;
656                 transmit_fd = 0;
657         }
658
659         if (timeserver) {
660                 g_free(timeserver);
661                 timeserver = NULL;
662         }
663 }