chiark / gitweb /
rename timedate-sntp to timesync
[elogind.git] / src / timesync / timesyncd.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 Kay Sievers
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <time.h>
28 #include <math.h>
29 #include <arpa/inet.h>
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <sys/timerfd.h>
33 #include <sys/timex.h>
34 #include <sys/socket.h>
35
36 #include "missing.h"
37 #include "util.h"
38 #include "sparse-endian.h"
39 #include "log.h"
40 #include "sd-event.h"
41 #include "sd-daemon.h"
42
43 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
44
45 #ifndef ADJ_SETOFFSET
46 #define ADJ_SETOFFSET                   0x0100  /* add 'time' to current time */
47 #endif
48
49 /* expected accuracy of time synchronization; used to adjust the poll interval */
50 #define NTP_ACCURACY_SEC                0.2
51
52 /*
53  * "A client MUST NOT under any conditions use a poll interval less
54  * than 15 seconds."
55  */
56 #define NTP_POLL_INTERVAL_MIN_SEC       32
57 #define NTP_POLL_INTERVAL_MAX_SEC       2048
58
59 /*
60  * Maximum delta in seconds which the system clock is gradually adjusted
61  * (slew) to approach the network time. Deltas larger that this are set by
62  * letting the system time jump. The kernel's limit for adjtime is 0.5s.
63  */
64 #define NTP_MAX_ADJUST                  0.4
65
66 /* NTP protocol, packet header */
67 #define NTP_LEAP_PLUSSEC                1
68 #define NTP_LEAP_MINUSSEC               2
69 #define NTP_LEAP_NOTINSYNC              3
70 #define NTP_MODE_CLIENT                 3
71 #define NTP_MODE_SERVER                 4
72 #define NTP_FIELD_LEAP(f)               (((f) >> 6) & 3)
73 #define NTP_FIELD_VERSION(f)            (((f) >> 3) & 7)
74 #define NTP_FIELD_MODE(f)               ((f) & 7)
75 #define NTP_FIELD(l, v, m)              (((l) << 6) | ((v) << 3) | (m))
76
77 /*
78  * "NTP timestamps are represented as a 64-bit unsigned fixed-point number,
79  * in seconds relative to 0h on 1 January 1900."
80  */
81 #define OFFSET_1900_1970        2208988800UL
82
83 struct ntp_ts {
84         be32_t sec;
85         be32_t frac;
86 } _packed_;
87
88 struct ntp_ts_short {
89         be16_t sec;
90         be16_t frac;
91 } _packed_;
92
93 struct ntp_msg {
94         uint8_t field;
95         uint8_t stratum;
96         int8_t poll;
97         int8_t precision;
98         struct ntp_ts_short root_delay;
99         struct ntp_ts_short root_dispersion;
100         char refid[4];
101         struct ntp_ts reference_time;
102         struct ntp_ts origin_time;
103         struct ntp_ts recv_time;
104         struct ntp_ts trans_time;
105 } _packed_;
106
107 typedef struct Manager Manager;
108 struct Manager {
109         sd_event *event;
110
111         /* peer */
112         sd_event_source *event_receive;
113         char *server;
114         struct sockaddr_in server_addr;
115         int server_socket;
116         uint64_t packet_count;
117
118         /* last sent packet */
119         struct timespec trans_time_mon;
120         struct timespec trans_time;
121         usec_t retry_interval;
122         bool pending;
123
124         /* poll timer */
125         sd_event_source *event_timer;
126         usec_t poll_interval_usec;
127         bool poll_resync;
128
129         /* history data */
130         struct {
131                 double offset;
132                 double delay;
133         } samples[8];
134         unsigned int samples_idx;
135         double samples_jitter;
136
137         /* last change */
138         bool jumped;
139
140         /* watch for time changes */
141         sd_event_source *event_clock_watch;
142         int clock_watch_fd;
143 };
144
145 static void manager_free(Manager *m);
146 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
147 #define _cleanup_manager_free_ _cleanup_(manager_freep)
148
149 static int sntp_arm_timer(Manager *m, usec_t next);
150 static int sntp_clock_watch_setup(Manager *m);
151 static void sntp_server_disconnect(Manager *m);
152
153 static double ntp_ts_to_d(const struct ntp_ts *ts) {
154         return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX);
155 }
156
157 static double tv_to_d(const struct timeval *tv) {
158         return tv->tv_sec + (1.0e-6 * tv->tv_usec);
159 }
160
161 static double ts_to_d(const struct timespec *ts) {
162         return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
163 }
164
165 static void d_to_tv(double d, struct timeval *tv) {
166         tv->tv_sec = (long)d;
167         tv->tv_usec = (d - tv->tv_sec) * 1000 * 1000;
168
169         /* the kernel expects -0.3s as {-1, 7000.000} */
170         if (tv->tv_usec < 0) {
171                 tv->tv_sec  -= 1;
172                 tv->tv_usec += 1000 * 1000;
173         }
174 }
175
176 static double square(double d) {
177         return d * d;
178 }
179
180 static int sntp_send_request(Manager *m) {
181         struct ntp_msg ntpmsg = {};
182         struct sockaddr_in addr = {};
183         ssize_t len;
184         int r;
185
186         /*
187          * "The client initializes the NTP message header, sends the request
188          * to the server, and strips the time of day from the Transmit
189          * Timestamp field of the reply.  For this purpose, all the NTP
190          * header fields are set to 0, except the Mode, VN, and optional
191          * Transmit Timestamp fields."
192          */
193         ntpmsg.field = NTP_FIELD(0, 4, NTP_MODE_CLIENT);
194
195         /*
196          * Set transmit timestamp, remember it; the server will send that back
197          * as the origin timestamp and we have an indication that this is the
198          * matching answer to our request.
199          *
200          * The actual value does not matter, We do not care about the correct
201          * NTP UINT_MAX fraction; we just pass the plain nanosecond value.
202          */
203         clock_gettime(CLOCK_MONOTONIC, &m->trans_time_mon);
204         clock_gettime(CLOCK_REALTIME, &m->trans_time);
205         ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970);
206         ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec);
207
208         addr.sin_family = AF_INET;
209         addr.sin_port = htobe16(123);
210         addr.sin_addr.s_addr = inet_addr(m->server);
211         len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &addr, sizeof(addr));
212         if (len == sizeof(ntpmsg)) {
213                 m->pending = true;
214                 log_debug("Sent NTP request to: %s", m->server);
215         } else
216                 log_debug("Sending NTP request to %s failed: %m", m->server);
217
218         /* re-arm timer with incresing timeout, in case the packets never arrive back */
219         if (m->retry_interval > 0) {
220                 if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
221                         m->retry_interval *= 2;
222         } else
223                 m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
224         r = sntp_arm_timer(m, m->retry_interval);
225         if (r < 0)
226                 return r;
227
228         return 0;
229 }
230
231 static int sntp_timer(sd_event_source *source, usec_t usec, void *userdata) {
232         Manager *m = userdata;
233
234         assert(m);
235
236         sntp_send_request(m);
237         return 0;
238 }
239
240 static int sntp_arm_timer(Manager *m, usec_t next) {
241         int r;
242
243         assert(m);
244         assert(m->event_receive);
245
246         if (next == 0) {
247                 m->event_timer = sd_event_source_unref(m->event_timer);
248                 return 0;
249         }
250
251         if (m->event_timer) {
252                 r = sd_event_source_set_time(m->event_timer, now(CLOCK_MONOTONIC) + next);
253                 if (r < 0)
254                         return r;
255
256                 return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT);
257         }
258
259         r = sd_event_add_time(
260                         m->event,
261                         &m->event_timer,
262                         CLOCK_MONOTONIC,
263                         now(CLOCK_MONOTONIC) + next, 0,
264                         sntp_timer, m);
265         if (r < 0)
266                 return r;
267
268         return 0;
269 }
270
271 static int sntp_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
272         Manager *m = userdata;
273
274         assert(m);
275         assert(m->event_receive);
276
277         /* rearm timer */
278         sntp_clock_watch_setup(m);
279
280         /* skip our own jumps */
281         if (m->jumped) {
282                 m->jumped = false;
283                 return 0;
284         }
285
286         /* resync */
287         log_info("System time changed. Resyncing.");
288         m->poll_resync = true;
289         sntp_send_request(m);
290
291         return 0;
292 }
293
294 /* wake up when the system time changes underneath us */
295 static int sntp_clock_watch_setup(Manager *m) {
296         struct itimerspec its = { .it_value.tv_sec = TIME_T_MAX };
297         _cleanup_close_ int fd = -1;
298         sd_event *e;
299         sd_event_source *source;
300         int r;
301
302         assert(m);
303         assert(m->event_receive);
304
305         fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
306         if (fd < 0) {
307                 log_error("Failed to create timerfd: %m");
308                 return -errno;
309         }
310
311         if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
312                 log_error("Failed to set up timerfd: %m");
313                 return -errno;
314         }
315
316         e = sd_event_source_get_event(m->event_receive);
317         r = sd_event_add_io(e, &source, fd, EPOLLIN, sntp_clock_watch, m);
318         if (r < 0) {
319                 log_error("Failed to create clock watch event source: %s", strerror(-r));
320                 return r;
321         }
322
323         sd_event_source_unref(m->event_clock_watch);
324         m->event_clock_watch = source;
325
326         if (m->clock_watch_fd >= 0)
327                 close(m->clock_watch_fd);
328         m->clock_watch_fd = fd;
329         fd = -1;
330
331         return 0;
332 }
333
334 static int sntp_adjust_clock(Manager *m, double offset, int leap_sec) {
335         struct timex tmx = {};
336         int r;
337
338         /*
339          * For small deltas, tell the kernel to gradually adjust the system
340          * clock to the NTP time, larger deltas are just directly set.
341          *
342          * Clear STA_UNSYNC, it will enable the kernel's 11-minute mode, which
343          * syncs the system time periodically to the hardware clock.
344          */
345         if (fabs(offset) < NTP_MAX_ADJUST) {
346                 tmx.modes = ADJ_STATUS | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
347                 tmx.status = STA_PLL;
348                 tmx.offset = offset * USEC_PER_SEC;
349                 tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 6;
350                 tmx.maxerror = 0;
351                 tmx.esterror = 0;
352                 log_debug("  adjust (slew): %+f sec\n", (double)tmx.offset / USEC_PER_SEC);
353         } else {
354                 tmx.modes = ADJ_SETOFFSET;
355                 d_to_tv(offset, &tmx.time);
356
357                 m->jumped = true;
358                 log_debug("  adjust (jump): %+f sec\n", tv_to_d(&tmx.time));
359         }
360
361         switch (leap_sec) {
362         case 1:
363                 tmx.status |= STA_INS;
364                 break;
365         case -1:
366                 tmx.status |= STA_DEL;
367                 break;
368         }
369
370         //r = clock_adjtime(CLOCK_REALTIME, &tmx);
371         r = adjtimex(&tmx);
372         if (r < 0)
373                 return r;
374
375         log_debug("  status       : %04i %s\n"
376                   "  time now     : %li.%06li\n"
377                   "  constant     : %li\n"
378                   "  offset       : %+f sec\n"
379                   "  freq offset  : %+li (%+.3f ppm)\n",
380                   tmx.status, tmx.status & STA_UNSYNC ? "" : "sync",
381                   tmx.time.tv_sec, tmx.time.tv_usec,
382                   tmx.constant,
383                   (double)tmx.offset / USEC_PER_SEC,
384                   tmx.freq, (double)tmx.freq / 65536);
385
386         return 0;
387 }
388
389 static bool sntp_sample_spike_detection(Manager *m, double offset, double delay) {
390         unsigned int i, idx_cur, idx_new, idx_min;
391         double jitter;
392         double j;
393
394         m->packet_count++;
395
396         /* ignore initial sample */
397         if (m->packet_count == 1)
398                 return false;
399
400         /* store the current data in our samples array */
401         idx_cur = m->samples_idx;
402         idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
403         m->samples_idx = idx_new;
404         m->samples[idx_new].offset = offset;
405         m->samples[idx_new].delay = delay;
406
407         /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
408         jitter = m->samples_jitter;
409         for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++)
410                 if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay)
411                         idx_min = i;
412
413         j = 0;
414         for (i = 0; i < ELEMENTSOF(m->samples); i++)
415                 j += square(m->samples[i].offset - m->samples[idx_min].offset);
416         m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
417
418         /* ignore samples when resyncing */
419         if (m->poll_resync)
420                 return false;
421
422         /* always accept offset if we are farther off than the round-trip delay */
423         if (fabs(offset) > delay)
424                 return false;
425
426         /* we need a few samples before looking at them */
427         if (m->packet_count < 4)
428                 return false;
429
430         /* do not accept anything worse than the maximum possible error of the best sample */
431         if (fabs(offset) > m->samples[idx_min].delay)
432                 return true;
433
434         /* compare the difference between the current offset to the previous offset and jitter */
435         return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
436 }
437
438 static void sntp_adjust_poll(Manager *m, double offset, bool spike) {
439         if (m->poll_resync) {
440                 m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
441                 m->poll_resync = false;
442                 return;
443         }
444
445         /* set to minimal poll interval */
446         if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
447                 m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
448                 return;
449         }
450
451         /* increase polling interval */
452         if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
453                 if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
454                         m->poll_interval_usec *= 2;
455                 return;
456         }
457
458         /* decrease polling interval */
459         if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
460                 if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
461                         m->poll_interval_usec /= 2;
462                 return;
463         }
464 }
465
466 static int sntp_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
467         Manager *m = userdata;
468         unsigned char buf[sizeof(struct ntp_msg)];
469         struct iovec iov = {
470                 .iov_base = buf,
471                 .iov_len = sizeof(buf),
472         };
473         union {
474                 struct cmsghdr cmsghdr;
475                 uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
476         } control;
477         struct sockaddr_in server_addr;
478         struct msghdr msghdr = {
479                 .msg_iov = &iov,
480                 .msg_iovlen = 1,
481                 .msg_control = &control,
482                 .msg_controllen = sizeof(control),
483                 .msg_name = &server_addr,
484                 .msg_namelen = sizeof(server_addr),
485         };
486         struct cmsghdr *cmsg;
487         struct timespec now_ts;
488         struct timeval *recv_time;
489         ssize_t len;
490         struct ntp_msg *ntpmsg;
491         double origin, receive, trans, dest;
492         double delay, offset;
493         bool spike;
494         int leap_sec;
495         int r;
496
497         if (revents & (EPOLLHUP|EPOLLERR)) {
498                 log_debug("Server connection returned error. Closing.");
499                 sntp_server_disconnect(m);
500                 return -ENOTCONN;
501         }
502
503         len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
504         if (len < 0) {
505                 log_debug("Error receiving message. Disconnecting.");
506                 return -EINVAL;
507         }
508
509         if (iov.iov_len < sizeof(struct ntp_msg)) {
510                 log_debug("Invalid response from server. Disconnecting.");
511                 return -EINVAL;
512         }
513
514         if (m->server_addr.sin_addr.s_addr != server_addr.sin_addr.s_addr) {
515                 log_debug("Response from unknown server. Disconnecting.");
516                 return -EINVAL;
517         }
518
519         recv_time = NULL;
520         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
521                 if (cmsg->cmsg_level != SOL_SOCKET)
522                         continue;
523
524                 switch (cmsg->cmsg_type) {
525                 case SCM_TIMESTAMP:
526                         recv_time = (struct timeval *) CMSG_DATA(cmsg);
527                         break;
528                 }
529         }
530         if (!recv_time) {
531                 log_debug("Invalid packet timestamp. Disconnecting.");
532                 return -EINVAL;
533         }
534
535         ntpmsg = iov.iov_base;
536         if (!m->pending) {
537                 log_debug("Unexpected reply. Ignoring.");
538                 return 0;
539         }
540
541         /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
542         if (be32toh(ntpmsg->origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
543             be32toh(ntpmsg->origin_time.frac) != m->trans_time.tv_nsec) {
544                 log_debug("Invalid reply; not our transmit time. Ignoring.");
545                 return 0;
546         }
547
548         if (NTP_FIELD_LEAP(ntpmsg->field) == NTP_LEAP_NOTINSYNC) {
549                 log_debug("Server is not synchronized. Disconnecting.");
550                 return -EINVAL;
551         }
552
553         if (NTP_FIELD_VERSION(ntpmsg->field) != 4) {
554                 log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg->field));
555                 return -EINVAL;
556         }
557
558         if (NTP_FIELD_MODE(ntpmsg->field) != NTP_MODE_SERVER) {
559                 log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg->field));
560                 return -EINVAL;
561         }
562
563         /* valid packet */
564         m->pending = false;
565         m->retry_interval = 0;
566
567         /* announce leap seconds */
568         if (NTP_FIELD_LEAP(ntpmsg->field) & NTP_LEAP_PLUSSEC)
569                 leap_sec = 1;
570         else if (NTP_FIELD_LEAP(ntpmsg->field) & NTP_LEAP_MINUSSEC)
571                 leap_sec = -1;
572         else
573                 leap_sec = 0;
574
575         /*
576          * "Timestamp Name          ID   When Generated
577          *  ------------------------------------------------------------
578          *  Originate Timestamp     T1   time request sent by client
579          *  Receive Timestamp       T2   time request received by server
580          *  Transmit Timestamp      T3   time reply sent by server
581          *  Destination Timestamp   T4   time reply received by client
582          *
583          *  The round-trip delay, d, and system clock offset, t, are defined as:
584          *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
585          */
586         clock_gettime(CLOCK_MONOTONIC, &now_ts);
587         origin = tv_to_d(recv_time) - (ts_to_d(&now_ts) - ts_to_d(&m->trans_time_mon)) + OFFSET_1900_1970;
588         receive = ntp_ts_to_d(&ntpmsg->recv_time);
589         trans = ntp_ts_to_d(&ntpmsg->trans_time);
590         dest = tv_to_d(recv_time) + OFFSET_1900_1970;
591
592         offset = ((receive - origin) + (trans - dest)) / 2;
593         delay = (dest - origin) - (trans - receive);
594
595         spike = sntp_sample_spike_detection(m, offset, delay);
596
597         sntp_adjust_poll(m, offset, spike);
598
599         log_debug("NTP response:\n"
600                   "  leap         : %u\n"
601                   "  version      : %u\n"
602                   "  mode         : %u\n"
603                   "  stratum      : %u\n"
604                   "  precision    : %f sec (%d)\n"
605                   "  reference    : %.4s\n"
606                   "  origin       : %f\n"
607                   "  receive      : %f\n"
608                   "  transmit     : %f\n"
609                   "  dest         : %f\n"
610                   "  offset       : %+f sec\n"
611                   "  delay        : %+f sec\n"
612                   "  packet count : %"PRIu64"\n"
613                   "  jitter       : %f%s\n"
614                   "  poll interval: %llu\n",
615                   NTP_FIELD_LEAP(ntpmsg->field),
616                   NTP_FIELD_VERSION(ntpmsg->field),
617                   NTP_FIELD_MODE(ntpmsg->field),
618                   ntpmsg->stratum,
619                   exp2(ntpmsg->precision), ntpmsg->precision,
620                   ntpmsg->stratum == 1 ? ntpmsg->refid : "n/a",
621                   origin - OFFSET_1900_1970,
622                   receive - OFFSET_1900_1970,
623                   trans - OFFSET_1900_1970,
624                   dest - OFFSET_1900_1970,
625                   offset, delay,
626                   m->packet_count,
627                   m->samples_jitter, spike ? " spike" : "",
628                   m->poll_interval_usec / USEC_PER_SEC);
629
630         log_info("%4llu %+10f %10f %10f%s",
631                  m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, spike ? " spike" : "");
632
633         if (!spike) {
634                 r = sntp_adjust_clock(m, offset, leap_sec);
635                 if (r < 0)
636                         log_error("Failed to call clock_adjtime(): %m");
637         }
638
639         r = sntp_arm_timer(m, m->poll_interval_usec);
640         if (r < 0)
641                 return r;
642
643         return 0;
644 }
645
646 static int sntp_server_connect(Manager *m, const char *server) {
647         _cleanup_free_ char *s = NULL;
648
649         assert(m);
650         assert(server);
651         assert(m->server_socket >= 0);
652
653         s = strdup(server);
654         if (!s)
655                 return -ENOMEM;
656
657         free(m->server);
658         m->server = s;
659         s = NULL;
660
661         zero(m->server_addr);
662         m->server_addr.sin_family = AF_INET;
663         m->server_addr.sin_addr.s_addr = inet_addr(server);
664
665         m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
666
667         return sntp_send_request(m);
668 }
669
670 static void sntp_server_disconnect(Manager *m) {
671         if (!m->server)
672                 return;
673
674         m->event_timer = sd_event_source_unref(m->event_timer);
675
676         m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
677         if (m->clock_watch_fd > 0)
678                 close(m->clock_watch_fd);
679         m->clock_watch_fd = -1;
680
681         m->event_receive = sd_event_source_unref(m->event_receive);
682         if (m->server_socket > 0)
683                 close(m->server_socket);
684         m->server_socket = -1;
685
686         zero(m->server_addr);
687         free(m->server);
688         m->server = NULL;
689 }
690
691 static int sntp_listen_setup(Manager *m) {
692         _cleanup_close_ int fd = -1;
693         struct sockaddr_in addr;
694         const int on = 1;
695         const int tos = IPTOS_LOWDELAY;
696         int r;
697
698         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
699         if (fd < 0)
700                 return -errno;
701
702         zero(addr);
703         addr.sin_family = AF_INET;
704         r = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
705         if (r < 0)
706                 return -errno;
707
708         r = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
709         if (r < 0)
710                 return -errno;
711
712         r = setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
713         if (r < 0)
714                 return -errno;
715
716         r = sd_event_add_io(m->event, &m->event_receive, fd, EPOLLIN, sntp_receive_response, m);
717         if (r < 0)
718                 return r;
719
720         m->server_socket = fd;
721         fd = -1;
722
723         return 0;
724 }
725
726 static int manager_new(Manager **ret) {
727         _cleanup_manager_free_ Manager *m = NULL;
728         int r;
729
730         m = new0(Manager, 1);
731         if (!m)
732                 return -ENOMEM;
733
734         r = sd_event_default(&m->event);
735         if (r < 0)
736                 return r;
737
738         r = sntp_listen_setup(m);
739         if (r < 0)
740                 return r;
741
742         r = sntp_clock_watch_setup(m);
743         if (r < 0)
744                 return r;
745
746         *ret = m;
747         m = NULL;
748
749         return 0;
750 }
751
752 static void manager_free(Manager *m) {
753
754         if (!m)
755                 return;
756
757         sd_event_unref(m->event);
758         free(m);
759 }
760
761 int main(int argc, char *argv[]) {
762         _cleanup_manager_free_ Manager *m = NULL;
763         const char *server;
764         int r;
765
766         log_set_target(LOG_TARGET_AUTO);
767         log_parse_environment();
768         log_open();
769
770         r = manager_new(&m);
771         if (r < 0)
772                 goto out;
773
774         //server = "216.239.32.15";       /* time1.google.com */
775         //server = "192.53.103.108";      /* ntp1.ptb.de */
776         server = "27.54.95.11";         /* au.pool.ntp.org */
777
778         sd_notifyf(false,
779                   "READY=1\n"
780                   "STATUS=Connecting to %s", server);
781
782         r = sntp_server_connect(m, server);
783         if (r < 0)
784                 goto out;
785
786         r = sd_event_loop(m->event);
787         if (r < 0)
788                 goto out;
789
790 out:
791         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
792 }