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