chiark / gitweb /
f6c96d3d1618e72b945c6d3188b82e061ea32977
[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 ts_to_d(const struct timespec *ts) {
158         return ts->tv_sec + (1.0e-9 * ts->tv_nsec);
159 }
160
161 static double tv_to_d(const struct timeval *tv) {
162         return tv->tv_sec + (1.0e-6 * tv->tv_usec);
163 }
164
165 static double square(double d) {
166         return d * d;
167 }
168
169 static int sntp_send_request(Manager *m) {
170         struct ntp_msg ntpmsg = {};
171         struct sockaddr_in addr = {};
172         ssize_t len;
173         int r;
174
175         /*
176          * "The client initializes the NTP message header, sends the request
177          * to the server, and strips the time of day from the Transmit
178          * Timestamp field of the reply.  For this purpose, all the NTP
179          * header fields are set to 0, except the Mode, VN, and optional
180          * Transmit Timestamp fields."
181          */
182         ntpmsg.field = NTP_FIELD(0, 4, NTP_MODE_CLIENT);
183
184         /*
185          * Set transmit timestamp, remember it; the server will send that back
186          * as the origin timestamp and we have an indication that this is the
187          * matching answer to our request.
188          *
189          * The actual value does not matter, We do not care about the correct
190          * NTP UINT_MAX fraction; we just pass the plain nanosecond value.
191          */
192         clock_gettime(CLOCK_MONOTONIC, &m->trans_time_mon);
193         clock_gettime(CLOCK_REALTIME, &m->trans_time);
194         ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970);
195         ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec);
196
197         addr.sin_family = AF_INET;
198         addr.sin_port = htobe16(123);
199         addr.sin_addr.s_addr = inet_addr(m->server);
200         len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &addr, sizeof(addr));
201         if (len == sizeof(ntpmsg)) {
202                 m->pending = true;
203                 log_debug("Sent NTP request to: %s", m->server);
204         } else
205                 log_debug("Sending NTP request to %s failed: %m", m->server);
206
207         /* re-arm timer with incresing timeout, in case the packets never arrive back */
208         if (m->retry_interval > 0) {
209                 if (m->retry_interval < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
210                         m->retry_interval *= 2;
211         } else
212                 m->retry_interval = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
213         r = sntp_arm_timer(m, m->retry_interval);
214         if (r < 0)
215                 return r;
216
217         return 0;
218 }
219
220 static int sntp_timer(sd_event_source *source, usec_t usec, void *userdata) {
221         Manager *m = userdata;
222
223         assert(m);
224
225         sntp_send_request(m);
226         return 0;
227 }
228
229 static int sntp_arm_timer(Manager *m, usec_t next) {
230         int r;
231
232         assert(m);
233         assert(m->event_receive);
234
235         if (next == 0) {
236                 m->event_timer = sd_event_source_unref(m->event_timer);
237                 return 0;
238         }
239
240         if (m->event_timer) {
241                 r = sd_event_source_set_time(m->event_timer, now(CLOCK_MONOTONIC) + next);
242                 if (r < 0)
243                         return r;
244
245                 return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT);
246         }
247
248         r = sd_event_add_time(
249                         m->event,
250                         &m->event_timer,
251                         CLOCK_MONOTONIC,
252                         now(CLOCK_MONOTONIC) + next, 0,
253                         sntp_timer, m);
254         if (r < 0)
255                 return r;
256
257         return 0;
258 }
259
260 static int sntp_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
261         Manager *m = userdata;
262
263         assert(m);
264         assert(m->event_receive);
265
266         /* rearm timer */
267         sntp_clock_watch_setup(m);
268
269         /* skip our own jumps */
270         if (m->jumped) {
271                 m->jumped = false;
272                 return 0;
273         }
274
275         /* resync */
276         log_info("System time changed. Resyncing.");
277         m->poll_resync = true;
278         sntp_send_request(m);
279
280         return 0;
281 }
282
283 /* wake up when the system time changes underneath us */
284 static int sntp_clock_watch_setup(Manager *m) {
285         struct itimerspec its = { .it_value.tv_sec = TIME_T_MAX };
286         _cleanup_close_ int fd = -1;
287         sd_event *e;
288         sd_event_source *source;
289         int r;
290
291         assert(m);
292         assert(m->event_receive);
293
294         fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
295         if (fd < 0) {
296                 log_error("Failed to create timerfd: %m");
297                 return -errno;
298         }
299
300         if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
301                 log_error("Failed to set up timerfd: %m");
302                 return -errno;
303         }
304
305         e = sd_event_source_get_event(m->event_receive);
306         r = sd_event_add_io(e, &source, fd, EPOLLIN, sntp_clock_watch, m);
307         if (r < 0) {
308                 log_error("Failed to create clock watch event source: %s", strerror(-r));
309                 return r;
310         }
311
312         sd_event_source_unref(m->event_clock_watch);
313         m->event_clock_watch = source;
314
315         if (m->clock_watch_fd >= 0)
316                 close(m->clock_watch_fd);
317         m->clock_watch_fd = fd;
318         fd = -1;
319
320         return 0;
321 }
322
323 static int sntp_adjust_clock(Manager *m, double offset, int leap_sec) {
324         struct timex tmx = {};
325         int r;
326
327         /*
328          * For small deltas, tell the kernel to gradually adjust the system
329          * clock to the NTP time, larger deltas are just directly set.
330          *
331          * Clear STA_UNSYNC, it will enable the kernel's 11-minute mode, which
332          * syncs the system time periodically to the hardware clock.
333          */
334         if (fabs(offset) < NTP_MAX_ADJUST) {
335                 tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
336                 tmx.status = STA_PLL;
337                 tmx.offset = offset * NSEC_PER_SEC;
338                 tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4;
339                 tmx.maxerror = 0;
340                 tmx.esterror = 0;
341                 log_debug("  adjust (slew): %+.3f sec\n", offset);
342         } else {
343                 tmx.modes = ADJ_SETOFFSET | ADJ_NANO;
344
345                 /* ADJ_NANO uses nanoseconds in the microseconds field */
346                 tmx.time.tv_sec = (long)offset;
347                 tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC;
348
349                 /* the kernel expects -0.3s as {-1, 7000.000.000} */
350                 if (tmx.time.tv_usec < 0) {
351                         tmx.time.tv_usec  -= 1;
352                         tmx.time.tv_usec += NSEC_PER_SEC;
353                 }
354
355                 m->jumped = true;
356                 log_debug("  adjust (jump): %+.3f sec\n", offset);
357         }
358
359         switch (leap_sec) {
360         case 1:
361                 tmx.status |= STA_INS;
362                 break;
363         case -1:
364                 tmx.status |= STA_DEL;
365                 break;
366         }
367
368         r = clock_adjtime(CLOCK_REALTIME, &tmx);
369         if (r < 0)
370                 return r;
371
372         log_debug("  status       : %04i %s\n"
373                   "  time now     : %li.%03lli\n"
374                   "  constant     : %li\n"
375                   "  offset       : %+.3f sec\n"
376                   "  freq offset  : %+li (%i ppm)\n",
377                   tmx.status, tmx.status & STA_UNSYNC ? "" : "sync",
378                   tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC,
379                   tmx.constant,
380                   (double)tmx.offset / NSEC_PER_SEC,
381                   tmx.freq, abs(tmx.freq) / 65536);
382
383         return 0;
384 }
385
386 static bool sntp_sample_spike_detection(Manager *m, double offset, double delay) {
387         unsigned int i, idx_cur, idx_new, idx_min;
388         double jitter;
389         double j;
390
391         m->packet_count++;
392
393         /* ignore initial sample */
394         if (m->packet_count == 1)
395                 return false;
396
397         /* store the current data in our samples array */
398         idx_cur = m->samples_idx;
399         idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples);
400         m->samples_idx = idx_new;
401         m->samples[idx_new].offset = offset;
402         m->samples[idx_new].delay = delay;
403
404         /* calculate new jitter value from the RMS differences relative to the lowest delay sample */
405         jitter = m->samples_jitter;
406         for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++)
407                 if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay)
408                         idx_min = i;
409
410         j = 0;
411         for (i = 0; i < ELEMENTSOF(m->samples); i++)
412                 j += square(m->samples[i].offset - m->samples[idx_min].offset);
413         m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1));
414
415         /* ignore samples when resyncing */
416         if (m->poll_resync)
417                 return false;
418
419         /* always accept offset if we are farther off than the round-trip delay */
420         if (fabs(offset) > delay)
421                 return false;
422
423         /* we need a few samples before looking at them */
424         if (m->packet_count < 4)
425                 return false;
426
427         /* do not accept anything worse than the maximum possible error of the best sample */
428         if (fabs(offset) > m->samples[idx_min].delay)
429                 return true;
430
431         /* compare the difference between the current offset to the previous offset and jitter */
432         return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter;
433 }
434
435 static void sntp_adjust_poll(Manager *m, double offset, bool spike) {
436         if (m->poll_resync) {
437                 m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
438                 m->poll_resync = false;
439                 return;
440         }
441
442         /* set to minimal poll interval */
443         if (!spike && fabs(offset) > NTP_ACCURACY_SEC) {
444                 m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
445                 return;
446         }
447
448         /* increase polling interval */
449         if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) {
450                 if (m->poll_interval_usec < NTP_POLL_INTERVAL_MAX_SEC * USEC_PER_SEC)
451                         m->poll_interval_usec *= 2;
452                 return;
453         }
454
455         /* decrease polling interval */
456         if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) {
457                 if (m->poll_interval_usec > NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC)
458                         m->poll_interval_usec /= 2;
459                 return;
460         }
461 }
462
463 static int sntp_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
464         Manager *m = userdata;
465         unsigned char buf[sizeof(struct ntp_msg)];
466         struct iovec iov = {
467                 .iov_base = buf,
468                 .iov_len = sizeof(buf),
469         };
470         union {
471                 struct cmsghdr cmsghdr;
472                 uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
473         } control;
474         struct sockaddr_in server_addr;
475         struct msghdr msghdr = {
476                 .msg_iov = &iov,
477                 .msg_iovlen = 1,
478                 .msg_control = &control,
479                 .msg_controllen = sizeof(control),
480                 .msg_name = &server_addr,
481                 .msg_namelen = sizeof(server_addr),
482         };
483         struct cmsghdr *cmsg;
484         struct timespec now_ts;
485         struct timeval *recv_time;
486         ssize_t len;
487         struct ntp_msg *ntpmsg;
488         double origin, receive, trans, dest;
489         double delay, offset;
490         bool spike;
491         int leap_sec;
492         int r;
493
494         if (revents & (EPOLLHUP|EPOLLERR)) {
495                 log_debug("Server connection returned error. Closing.");
496                 sntp_server_disconnect(m);
497                 return -ENOTCONN;
498         }
499
500         len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
501         if (len < 0) {
502                 log_debug("Error receiving message. Disconnecting.");
503                 return -EINVAL;
504         }
505
506         if (iov.iov_len < sizeof(struct ntp_msg)) {
507                 log_debug("Invalid response from server. Disconnecting.");
508                 return -EINVAL;
509         }
510
511         if (m->server_addr.sin_addr.s_addr != server_addr.sin_addr.s_addr) {
512                 log_debug("Response from unknown server. Disconnecting.");
513                 return -EINVAL;
514         }
515
516         recv_time = NULL;
517         for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
518                 if (cmsg->cmsg_level != SOL_SOCKET)
519                         continue;
520
521                 switch (cmsg->cmsg_type) {
522                 case SCM_TIMESTAMP:
523                         recv_time = (struct timeval *) CMSG_DATA(cmsg);
524                         break;
525                 }
526         }
527         if (!recv_time) {
528                 log_debug("Invalid packet timestamp. Disconnecting.");
529                 return -EINVAL;
530         }
531
532         ntpmsg = iov.iov_base;
533         if (!m->pending) {
534                 log_debug("Unexpected reply. Ignoring.");
535                 return 0;
536         }
537
538         /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
539         if (be32toh(ntpmsg->origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
540             be32toh(ntpmsg->origin_time.frac) != m->trans_time.tv_nsec) {
541                 log_debug("Invalid reply; not our transmit time. Ignoring.");
542                 return 0;
543         }
544
545         if (NTP_FIELD_LEAP(ntpmsg->field) == NTP_LEAP_NOTINSYNC) {
546                 log_debug("Server is not synchronized. Disconnecting.");
547                 return -EINVAL;
548         }
549
550         if (NTP_FIELD_VERSION(ntpmsg->field) != 4) {
551                 log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg->field));
552                 return -EINVAL;
553         }
554
555         if (NTP_FIELD_MODE(ntpmsg->field) != NTP_MODE_SERVER) {
556                 log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg->field));
557                 return -EINVAL;
558         }
559
560         /* valid packet */
561         m->pending = false;
562         m->retry_interval = 0;
563
564         /* announce leap seconds */
565         if (NTP_FIELD_LEAP(ntpmsg->field) & NTP_LEAP_PLUSSEC)
566                 leap_sec = 1;
567         else if (NTP_FIELD_LEAP(ntpmsg->field) & NTP_LEAP_MINUSSEC)
568                 leap_sec = -1;
569         else
570                 leap_sec = 0;
571
572         /*
573          * "Timestamp Name          ID   When Generated
574          *  ------------------------------------------------------------
575          *  Originate Timestamp     T1   time request sent by client
576          *  Receive Timestamp       T2   time request received by server
577          *  Transmit Timestamp      T3   time reply sent by server
578          *  Destination Timestamp   T4   time reply received by client
579          *
580          *  The round-trip delay, d, and system clock offset, t, are defined as:
581          *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
582          */
583         clock_gettime(CLOCK_MONOTONIC, &now_ts);
584         origin = tv_to_d(recv_time) - (ts_to_d(&now_ts) - ts_to_d(&m->trans_time_mon)) + OFFSET_1900_1970;
585         receive = ntp_ts_to_d(&ntpmsg->recv_time);
586         trans = ntp_ts_to_d(&ntpmsg->trans_time);
587         dest = tv_to_d(recv_time) + OFFSET_1900_1970;
588
589         offset = ((receive - origin) + (trans - dest)) / 2;
590         delay = (dest - origin) - (trans - receive);
591
592         spike = sntp_sample_spike_detection(m, offset, delay);
593
594         sntp_adjust_poll(m, offset, spike);
595
596         log_debug("NTP response:\n"
597                   "  leap         : %u\n"
598                   "  version      : %u\n"
599                   "  mode         : %u\n"
600                   "  stratum      : %u\n"
601                   "  precision    : %.6f sec (%d)\n"
602                   "  reference    : %.4s\n"
603                   "  origin       : %.3f\n"
604                   "  receive      : %.3f\n"
605                   "  transmit     : %.3f\n"
606                   "  dest         : %.3f\n"
607                   "  offset       : %+.3f sec\n"
608                   "  delay        : %+.3f sec\n"
609                   "  packet count : %"PRIu64"\n"
610                   "  jitter       : %.3f%s\n"
611                   "  poll interval: %llu\n",
612                   NTP_FIELD_LEAP(ntpmsg->field),
613                   NTP_FIELD_VERSION(ntpmsg->field),
614                   NTP_FIELD_MODE(ntpmsg->field),
615                   ntpmsg->stratum,
616                   exp2(ntpmsg->precision), ntpmsg->precision,
617                   ntpmsg->stratum == 1 ? ntpmsg->refid : "n/a",
618                   origin - OFFSET_1900_1970,
619                   receive - OFFSET_1900_1970,
620                   trans - OFFSET_1900_1970,
621                   dest - OFFSET_1900_1970,
622                   offset, delay,
623                   m->packet_count,
624                   m->samples_jitter, spike ? " spike" : "",
625                   m->poll_interval_usec / USEC_PER_SEC);
626
627         log_info("%s: interval/delta/delay/jitter %llu/%+.3f/%.3f/%.3f%s",
628                  m->server, m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, spike ? " (ignored)" : "");
629
630         if (!spike) {
631                 r = sntp_adjust_clock(m, offset, leap_sec);
632                 if (r < 0)
633                         log_error("Failed to call clock_adjtime(): %m");
634         }
635
636         r = sntp_arm_timer(m, m->poll_interval_usec);
637         if (r < 0)
638                 return r;
639
640         return 0;
641 }
642
643 static int sntp_server_connect(Manager *m, const char *server) {
644         _cleanup_free_ char *s = NULL;
645
646         assert(m);
647         assert(server);
648         assert(m->server_socket >= 0);
649
650         s = strdup(server);
651         if (!s)
652                 return -ENOMEM;
653
654         free(m->server);
655         m->server = s;
656         s = NULL;
657
658         zero(m->server_addr);
659         m->server_addr.sin_family = AF_INET;
660         m->server_addr.sin_addr.s_addr = inet_addr(server);
661
662         m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;
663
664         return sntp_send_request(m);
665 }
666
667 static void sntp_server_disconnect(Manager *m) {
668         if (!m->server)
669                 return;
670
671         m->event_timer = sd_event_source_unref(m->event_timer);
672
673         m->event_clock_watch = sd_event_source_unref(m->event_clock_watch);
674         if (m->clock_watch_fd > 0)
675                 close(m->clock_watch_fd);
676         m->clock_watch_fd = -1;
677
678         m->event_receive = sd_event_source_unref(m->event_receive);
679         if (m->server_socket > 0)
680                 close(m->server_socket);
681         m->server_socket = -1;
682
683         zero(m->server_addr);
684         free(m->server);
685         m->server = NULL;
686 }
687
688 static int sntp_listen_setup(Manager *m) {
689         _cleanup_close_ int fd = -1;
690         struct sockaddr_in addr;
691         const int on = 1;
692         const int tos = IPTOS_LOWDELAY;
693         int r;
694
695         fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
696         if (fd < 0)
697                 return -errno;
698
699         zero(addr);
700         addr.sin_family = AF_INET;
701         r = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
702         if (r < 0)
703                 return -errno;
704
705         r = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
706         if (r < 0)
707                 return -errno;
708
709         r = setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
710         if (r < 0)
711                 return -errno;
712
713         r = sd_event_add_io(m->event, &m->event_receive, fd, EPOLLIN, sntp_receive_response, m);
714         if (r < 0)
715                 return r;
716
717         m->server_socket = fd;
718         fd = -1;
719
720         return 0;
721 }
722
723 static int manager_new(Manager **ret) {
724         _cleanup_manager_free_ Manager *m = NULL;
725         int r;
726
727         m = new0(Manager, 1);
728         if (!m)
729                 return -ENOMEM;
730
731         r = sd_event_default(&m->event);
732         if (r < 0)
733                 return r;
734
735         r = sntp_listen_setup(m);
736         if (r < 0)
737                 return r;
738
739         r = sntp_clock_watch_setup(m);
740         if (r < 0)
741                 return r;
742
743         *ret = m;
744         m = NULL;
745
746         return 0;
747 }
748
749 static void manager_free(Manager *m) {
750
751         if (!m)
752                 return;
753
754         sd_event_unref(m->event);
755         free(m);
756 }
757
758 int main(int argc, char *argv[]) {
759         _cleanup_manager_free_ Manager *m = NULL;
760         const char *server;
761         int r;
762
763         log_set_target(LOG_TARGET_AUTO);
764         log_parse_environment();
765         log_open();
766
767         r = manager_new(&m);
768         if (r < 0)
769                 goto out;
770
771         server = "216.239.32.15";       /* time1.google.com */
772
773         sd_notifyf(false,
774                   "READY=1");
775
776         r = sntp_server_connect(m, server);
777         if (r < 0)
778                 goto out;
779
780         sd_notifyf(false,
781                   "STATUS=Using time server: %s", server);
782
783         r = sd_event_loop(m->event);
784         if (r < 0)
785                 goto out;
786
787 out:
788         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
789 }