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