]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/timesync/timesyncd.c
rename timedate-sntp to timesync
[thirdparty/systemd.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 }