aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorAdam Tkac <vonsch@gmail.com>2009-11-22 03:43:55 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-22 03:43:55 +0100
commitb1585064fdac138b3bd14c2b64f64c67ec08b654 (patch)
treeb632b12a9aea4953751bb1569bf9290db42c5c4d /networking/ntpd.c
parentd095fd4d95fd6241847f01e4fd674bc177310c33 (diff)
downloadbusybox-w32-b1585064fdac138b3bd14c2b64f64c67ec08b654.tar.gz
busybox-w32-b1585064fdac138b3bd14c2b64f64c67ec08b654.tar.bz2
busybox-w32-b1585064fdac138b3bd14c2b64f64c67ec08b654.zip
ntpd: new applet by Adam Tkac. +5k.
Signed-off-by: Adam Tkac <vonsch@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r--networking/ntpd.c999
1 files changed, 999 insertions, 0 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
new file mode 100644
index 000000000..62a00a5bf
--- /dev/null
+++ b/networking/ntpd.c
@@ -0,0 +1,999 @@
1/*
2 * NTP client/server, based on OpenNTPD 3.9p1
3 *
4 * Author: Adam Tkac <vonsch@gmail.com>
5 *
6 * Licensed under GPLv2, see file LICENSE in this tarball for details.
7 */
8
9#include "libbb.h"
10#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
11
12#ifndef IP_PKTINFO
13# error "Sorry, your kernel has to support IP_PKTINFO"
14#endif
15
16#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every n secs */
17#define INTERVAL_QUERY_PATHETIC 60
18#define INTERVAL_QUERY_AGRESSIVE 5
19
20#define TRUSTLEVEL_BADPEER 6
21#define TRUSTLEVEL_PATHETIC 2
22#define TRUSTLEVEL_AGRESSIVE 8
23#define TRUSTLEVEL_MAX 10
24
25#define QSCALE_OFF_MIN 0.05
26#define QSCALE_OFF_MAX 0.50
27
28#define QUERYTIME_MAX 15 /* single query might take n secs max */
29#define OFFSET_ARRAY_SIZE 8
30#define SETTIME_MIN_OFFSET 180 /* min offset for settime at start */
31#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */
32
33/* Style borrowed from NTP ref/tcpdump and updated for SNTPv4 (RFC2030). */
34
35/*
36 * RFC Section 3
37 *
38 * 0 1 2 3
39 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Integer Part |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * | Fraction Part |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 *
46 * 0 1 2 3
47 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * | Integer Part | Fraction Part |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51*/
52typedef struct {
53 uint32_t int_partl;
54 uint32_t fractionl;
55} l_fixedpt_t;
56
57typedef struct {
58 uint16_t int_parts;
59 uint16_t fractions;
60} s_fixedpt_t;
61
62#define NTP_DIGESTSIZE 16
63#define NTP_MSGSIZE_NOAUTH 48
64#define NTP_MSGSIZE (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE)
65
66typedef struct {
67 uint8_t status; /* status of local clock and leap info */
68 uint8_t stratum; /* Stratum level */
69 uint8_t ppoll; /* poll value */
70 int8_t precision;
71 s_fixedpt_t rootdelay;
72 s_fixedpt_t dispersion;
73 uint32_t refid;
74 l_fixedpt_t reftime;
75 l_fixedpt_t orgtime;
76 l_fixedpt_t rectime;
77 l_fixedpt_t xmttime;
78 uint32_t keyid;
79 uint8_t digest[NTP_DIGESTSIZE];
80} ntp_msg_t;
81
82typedef struct {
83 int fd;
84 ntp_msg_t msg;
85 double xmttime;
86} ntp_query_t;
87
88enum {
89 NTP_VERSION = 4,
90 NTP_MAXSTRATUM = 15,
91 /* Leap Second Codes (high order two bits) */
92 LI_NOWARNING = (0 << 6), /* no warning */
93 LI_PLUSSEC = (1 << 6), /* add a second (61 seconds) */
94 LI_MINUSSEC = (2 << 6), /* minus a second (59 seconds) */
95 LI_ALARM = (3 << 6), /* alarm condition */
96
97 /* Status Masks */
98 MODE_MASK = (7 << 0),
99 VERSION_MASK = (7 << 3),
100 LI_MASK = (3 << 6),
101
102 /* Mode values */
103 MODE_RES0 = 0, /* reserved */
104 MODE_SYM_ACT = 1, /* symmetric active */
105 MODE_SYM_PAS = 2, /* symmetric passive */
106 MODE_CLIENT = 3, /* client */
107 MODE_SERVER = 4, /* server */
108 MODE_BROADCAST = 5, /* broadcast */
109 MODE_RES1 = 6, /* reserved for NTP control message */
110 MODE_RES2 = 7 /* reserved for private use */
111};
112
113#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
114
115enum client_state {
116 STATE_NONE,
117 STATE_QUERY_SENT,
118 STATE_REPLY_RECEIVED
119};
120
121typedef struct {
122 double rootdelay;
123 double rootdispersion;
124 double reftime;
125 uint32_t refid;
126 uint32_t refid4;
127 uint8_t synced;
128 uint8_t leap;
129 int8_t precision;
130 uint8_t poll;
131 uint8_t stratum;
132} ntp_status_t;
133
134typedef struct {
135 ntp_status_t status;
136 double offset;
137 double delay;
138 double error;
139 time_t rcvd;
140 uint8_t good;
141} ntp_offset_t;
142
143typedef struct {
144 len_and_sockaddr *lsa;
145 ntp_query_t query;
146 ntp_offset_t reply[OFFSET_ARRAY_SIZE];
147 ntp_offset_t update;
148 enum client_state state;
149 time_t next;
150 time_t deadline;
151 uint8_t shift;
152 uint8_t trustlevel;
153} ntp_peer_t;
154
155
156struct globals {
157 unsigned verbose;
158#if ENABLE_FEATURE_NTPD_SERVER
159 int listen_fd;
160#endif
161 llist_t *ntp_peers;
162 ntp_status_t status;
163 uint32_t scale;
164 uint8_t settime;
165 uint8_t firstadj;
166 smallint peer_cnt;
167
168};
169#define G (*ptr_to_globals)
170
171
172static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
173
174
175static void
176set_next(ntp_peer_t *p, time_t t)
177{
178 p->next = time(NULL) + t;
179 p->deadline = 0;
180}
181
182static void
183add_peers(const char *s)
184{
185 ntp_peer_t *p;
186
187 p = xzalloc(sizeof(*p));
188//TODO: big ntpd uses all IPs, not just 1st, do we need to mimic that?
189 p->lsa = xhost2sockaddr(s, 123);
190 p->query.fd = -1;
191 p->query.msg.status = MODE_CLIENT | (NTP_VERSION << 3);
192 if (STATE_NONE != 0)
193 p->state = STATE_NONE;
194 p->trustlevel = TRUSTLEVEL_PATHETIC;
195 p->query.fd = -1;
196 set_next(p, 0);
197
198 llist_add_to(&G.ntp_peers, p);
199 G.peer_cnt++;
200}
201
202static double
203gettime(void)
204{
205 struct timeval tv;
206
207 gettimeofday(&tv, NULL); /* never fails */
208 return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
209}
210
211
212static void
213d_to_tv(double d, struct timeval *tv)
214{
215 tv->tv_sec = (long)d;
216 tv->tv_usec = (d - tv->tv_sec) * 1000000;
217}
218
219static double
220lfp_to_d(l_fixedpt_t lfp)
221{
222 double ret;
223
224 lfp.int_partl = ntohl(lfp.int_partl);
225 lfp.fractionl = ntohl(lfp.fractionl);
226 ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX);
227 return ret;
228}
229
230#if ENABLE_FEATURE_NTPD_SERVER
231static l_fixedpt_t
232d_to_lfp(double d)
233{
234 l_fixedpt_t lfp;
235
236 lfp.int_partl = htonl((uint32_t)d);
237 lfp.fractionl = htonl((uint32_t)((d - (u_int32_t)d) * UINT_MAX));
238 return lfp;
239}
240#endif
241
242static double
243sfp_to_d(s_fixedpt_t sfp)
244{
245 double ret;
246
247 sfp.int_parts = ntohs(sfp.int_parts);
248 sfp.fractions = ntohs(sfp.fractions);
249 ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX);
250 return ret;
251}
252
253#if ENABLE_FEATURE_NTPD_SERVER
254static s_fixedpt_t
255d_to_sfp(double d)
256{
257 s_fixedpt_t sfp;
258
259 sfp.int_parts = htons((uint16_t)d);
260 sfp.fractions = htons((uint16_t)((d - (u_int16_t)d) * USHRT_MAX));
261 return sfp;
262}
263#endif
264
265static void
266set_deadline(ntp_peer_t *p, time_t t)
267{
268 p->deadline = time(NULL) + t;
269 p->next = 0;
270}
271
272static time_t
273error_interval(void)
274{
275 time_t interval, r;
276
277 interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
278 r = random() % (interval / 10);
279 return (interval + r);
280}
281
282static int
283sendmsg_wrap(int fd,
284 const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen,
285 ntp_msg_t *msg, ssize_t len)
286{
287 ssize_t ret;
288
289 errno = 0;
290 if (!from) {
291 ret = sendto(fd, msg, len, 0, to, addrlen);
292 } else {
293 ret = send_to_from(fd, msg, len, 0, to, from, addrlen);
294 }
295 if (ret != len) {
296 bb_perror_msg("send failed");
297 return -1;
298 }
299 return 0;
300}
301
302static int
303client_query(ntp_peer_t *p)
304{
305 if (p->query.fd == -1) {
306 p->query.fd = xsocket(p->lsa->u.sa.sa_family, SOCK_DGRAM, 0);
307#if ENABLE_FEATURE_IPV6
308 if (p->lsa->u.sa.sa_family == AF_INET)
309#endif
310 setsockopt(p->query.fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
311 }
312
313 /*
314 * Send out a random 64-bit number as our transmit time. The NTP
315 * server will copy said number into the originate field on the
316 * response that it sends us. This is totally legal per the SNTP spec.
317 *
318 * The impact of this is two fold: we no longer send out the current
319 * system time for the world to see (which may aid an attacker), and
320 * it gives us a (not very secure) way of knowing that we're not
321 * getting spoofed by an attacker that can't capture our traffic
322 * but can spoof packets from the NTP server we're communicating with.
323 *
324 * Save the real transmit timestamp locally.
325 */
326
327 p->query.msg.xmttime.int_partl = random();
328 p->query.msg.xmttime.fractionl = random();
329 p->query.xmttime = gettime();
330
331 if (sendmsg_wrap(p->query.fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len,
332 &p->query.msg, NTP_MSGSIZE_NOAUTH) == -1) {
333 set_next(p, INTERVAL_QUERY_PATHETIC);
334 return -1;
335 }
336
337 p->state = STATE_QUERY_SENT;
338 set_deadline(p, QUERYTIME_MAX);
339
340 return 0;
341}
342
343static int
344offset_compare(const void *aa, const void *bb)
345{
346 const ntp_peer_t * const *a;
347 const ntp_peer_t * const *b;
348
349 a = aa;
350 b = bb;
351
352 if ((*a)->update.offset < (*b)->update.offset)
353 return -1;
354 return ((*a)->update.offset > (*b)->update.offset);
355}
356
357static uint32_t
358updated_scale(double offset)
359{
360 if (offset < 0)
361 offset = -offset;
362
363 if (offset > QSCALE_OFF_MAX)
364 return 1;
365 if (offset < QSCALE_OFF_MIN)
366 return QSCALE_OFF_MAX / QSCALE_OFF_MIN;
367 return QSCALE_OFF_MAX / offset;
368}
369
370static void
371adjtime_wrap(void)
372{
373 ntp_peer_t *p;
374 unsigned offset_cnt;
375 int i = 0;
376 ntp_peer_t **peers;
377 double offset_median;
378 llist_t *item;
379 len_and_sockaddr *lsa;
380 struct timeval tv, olddelta;
381
382 offset_cnt = 0;
383 for (item = G.ntp_peers; item != NULL; item = item->link) {
384 p = (ntp_peer_t *) item->data;
385 if (p->trustlevel < TRUSTLEVEL_BADPEER)
386 continue;
387 if (!p->update.good)
388 return;
389 offset_cnt++;
390 }
391
392 peers = xzalloc(sizeof(ntp_peer_t *) * offset_cnt);
393 for (item = G.ntp_peers; item != NULL; item = item->link) {
394 p = (ntp_peer_t *) item->data;
395 if (p->trustlevel < TRUSTLEVEL_BADPEER)
396 continue;
397 peers[i++] = p;
398 }
399
400 qsort(peers, offset_cnt, sizeof(ntp_peer_t *), offset_compare);
401
402 if (offset_cnt != 0) {
403 if ((offset_cnt & 1) == 0) {
404//TODO: try offset_cnt /= 2...
405 offset_median =
406 (peers[offset_cnt / 2 - 1]->update.offset +
407 peers[offset_cnt / 2]->update.offset) / 2;
408 G.status.rootdelay =
409 (peers[offset_cnt / 2 - 1]->update.delay +
410 peers[offset_cnt / 2]->update.delay) / 2;
411 G.status.stratum = MAX(
412 peers[offset_cnt / 2 - 1]->update.status.stratum,
413 peers[offset_cnt / 2]->update.status.stratum);
414 } else {
415 offset_median = peers[offset_cnt / 2]->update.offset;
416 G.status.rootdelay = peers[offset_cnt / 2]->update.delay;
417 G.status.stratum = peers[offset_cnt / 2]->update.status.stratum;
418 }
419 G.status.leap = peers[offset_cnt / 2]->update.status.leap;
420
421 bb_info_msg("adjusting local clock by %fs", offset_median);
422
423 d_to_tv(offset_median, &tv);
424 if (adjtime(&tv, &olddelta) == -1)
425 bb_error_msg("adjtime failed");
426 else if (!G.firstadj
427 && olddelta.tv_sec == 0
428 && olddelta.tv_usec == 0
429 && !G.status.synced
430 ) {
431 bb_info_msg("clock synced");
432 G.status.synced = 1;
433 } else if (G.status.synced) {
434 bb_info_msg("clock unsynced");
435 G.status.synced = 0;
436 }
437
438 G.firstadj = 0;
439 G.status.reftime = gettime();
440 G.status.stratum++; /* one more than selected peer */
441 G.scale = updated_scale(offset_median);
442
443 G.status.refid4 = peers[offset_cnt / 2]->update.status.refid4;
444
445 lsa = peers[offset_cnt / 2]->lsa;
446 G.status.refid =
447#if ENABLE_FEATURE_IPV6
448 lsa->u.sa.sa_family != AF_INET ?
449 G.status.refid4 :
450#endif
451 lsa->u.sin.sin_addr.s_addr;
452 }
453
454 free(peers);
455
456 for (item = G.ntp_peers; item != NULL; item = item->link) {
457 p = (ntp_peer_t *) item->data;
458 p->update.good = 0;
459 }
460}
461
462static void
463settime(double offset)
464{
465 ntp_peer_t *p;
466 llist_t *item;
467 struct timeval tv, curtime;
468 char buf[80];
469 time_t tval;
470
471#if 0
472 if (!G.settime)
473 return;
474#endif
475
476 /* if the offset is small, don't call settimeofday */
477 if (offset < SETTIME_MIN_OFFSET && offset > -SETTIME_MIN_OFFSET)
478 return;
479
480 gettimeofday(&curtime, NULL); /* never fails */
481
482 d_to_tv(offset, &tv);
483 curtime.tv_usec += tv.tv_usec + 1000000;
484 curtime.tv_sec += tv.tv_sec - 1 + (curtime.tv_usec / 1000000);
485 curtime.tv_usec %= 1000000;
486
487 if (settimeofday(&curtime, NULL) == -1) {
488 bb_error_msg("settimeofday");
489 return;
490 }
491
492 G.settime = 0;
493
494 tval = curtime.tv_sec;
495 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
496
497 /* Do we want to print message below to system log when daemonized? */
498 bb_info_msg("set local clock to %s (offset %fs)", buf, offset);
499
500 for (item = G.ntp_peers; item != NULL; item = item->link) {
501 p = (ntp_peer_t *) item->data;
502 if (p->next)
503 p->next -= offset;
504 if (p->deadline)
505 p->deadline -= offset;
506 }
507}
508
509static void
510client_update(ntp_peer_t *p)
511{
512 int i, best = 0, good = 0;
513
514 /*
515 * clock filter
516 * find the offset which arrived with the lowest delay
517 * use that as the peer update
518 * invalidate it and all older ones
519 */
520
521 for (i = 0; good == 0 && i < OFFSET_ARRAY_SIZE; i++) {
522 if (p->reply[i].good) {
523 good++;
524 best = i;
525 }
526 }
527
528 for (; i < OFFSET_ARRAY_SIZE; i++) {
529 if (p->reply[i].good) {
530 good++;
531 if (p->reply[i].delay < p->reply[best].delay)
532 best = i;
533 }
534 }
535
536 if (good < 8)
537 return;
538
539 memcpy(&p->update, &p->reply[best], sizeof(p->update));
540 adjtime_wrap();
541
542 for (i = 0; i < OFFSET_ARRAY_SIZE; i++)
543 if (p->reply[i].rcvd <= p->reply[best].rcvd)
544 p->reply[i].good = 0;
545}
546
547static time_t
548scale_interval(time_t requested)
549{
550 time_t interval, r;
551
552 interval = requested * G.scale;
553 r = random() % MAX(5, interval / 10);
554 return (interval + r);
555}
556
557static void
558client_dispatch(ntp_peer_t *p)
559{
560 char *addr;
561 ssize_t size;
562 ntp_msg_t msg;
563 double T1, T2, T3, T4;
564 time_t interval;
565 ntp_offset_t *offset;
566
567 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
568
569 size = recvfrom(p->query.fd, &msg, sizeof(msg), 0, NULL, NULL);
570 if (size == -1) {
571 bb_perror_msg("recvfrom(%s) error", addr);
572 if (errno == EHOSTUNREACH || errno == EHOSTDOWN
573 || errno == ENETUNREACH || errno == ENETDOWN
574 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
575 ) {
576//TODO: always do this?
577 set_next(p, error_interval());
578 goto bail;
579 }
580 xfunc_die();
581 }
582
583 T4 = gettime();
584
585 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
586 bb_error_msg("malformed packet received from %s", addr);
587 goto bail;
588 }
589
590 if (msg.orgtime.int_partl != p->query.msg.xmttime.int_partl
591 || msg.orgtime.fractionl != p->query.msg.xmttime.fractionl
592 ) {
593 goto bail;
594 }
595
596 if ((msg.status & LI_ALARM) == LI_ALARM
597 || msg.stratum == 0
598 || msg.stratum > NTP_MAXSTRATUM
599 ) {
600 interval = error_interval();
601 bb_info_msg("reply from %s: not synced, next query %ds", addr, (int) interval);
602 goto bail;
603 }
604
605 /*
606 * From RFC 2030 (with a correction to the delay math):
607 *
608 * Timestamp Name ID When Generated
609 * ------------------------------------------------------------
610 * Originate Timestamp T1 time request sent by client
611 * Receive Timestamp T2 time request received by server
612 * Transmit Timestamp T3 time reply sent by server
613 * Destination Timestamp T4 time reply received by client
614 *
615 * The roundtrip delay d and local clock offset t are defined as
616 *
617 * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2.
618 */
619
620 T1 = p->query.xmttime;
621 T2 = lfp_to_d(msg.rectime);
622 T3 = lfp_to_d(msg.xmttime);
623
624 offset = &p->reply[p->shift];
625
626 offset->offset = ((T2 - T1) + (T3 - T4)) / 2;
627 offset->delay = (T4 - T1) - (T3 - T2);
628 if (offset->delay < 0) {
629 interval = error_interval();
630 set_next(p, interval);
631 bb_info_msg("reply from %s: negative delay %f", addr, p->reply[p->shift].delay);
632 goto bail;
633 }
634 offset->error = (T2 - T1) - (T3 - T4);
635 offset->rcvd = time(NULL);
636 offset->good = 1;
637
638 offset->status.leap = (msg.status & LI_MASK);
639 offset->status.precision = msg.precision;
640 offset->status.rootdelay = sfp_to_d(msg.rootdelay);
641 offset->status.rootdispersion = sfp_to_d(msg.dispersion);
642 offset->status.refid = ntohl(msg.refid);
643 offset->status.refid4 = msg.xmttime.fractionl;
644 offset->status.reftime = lfp_to_d(msg.reftime);
645 offset->status.poll = msg.ppoll;
646 offset->status.stratum = msg.stratum;
647
648 if (p->trustlevel < TRUSTLEVEL_PATHETIC)
649 interval = scale_interval(INTERVAL_QUERY_PATHETIC);
650 else if (p->trustlevel < TRUSTLEVEL_AGRESSIVE)
651 interval = scale_interval(INTERVAL_QUERY_AGRESSIVE);
652 else
653 interval = scale_interval(INTERVAL_QUERY_NORMAL);
654
655 set_next(p, interval);
656 p->state = STATE_REPLY_RECEIVED;
657
658 /* every received reply which we do not discard increases trust */
659 if (p->trustlevel < TRUSTLEVEL_MAX) {
660 if (p->trustlevel < TRUSTLEVEL_BADPEER
661 && p->trustlevel + 1 >= TRUSTLEVEL_BADPEER
662 ) {
663 bb_info_msg("peer %s now valid", addr);
664 }
665 p->trustlevel++;
666 }
667
668 bb_info_msg("reply from %s: offset %f delay %f, next query %ds", addr,
669 offset->offset, offset->delay, (int) interval);
670
671 client_update(p);
672 if (!G.settime)
673 settime(offset->offset);
674
675 if (++p->shift >= OFFSET_ARRAY_SIZE)
676 p->shift = 0;
677
678 bail:
679 free(addr);
680}
681
682#if ENABLE_FEATURE_NTPD_SERVER
683static void
684server_dispatch(int fd)
685{
686 ssize_t size;
687 uint8_t version;
688 double rectime;
689 len_and_sockaddr *to;
690 struct sockaddr *from;
691 ntp_msg_t query, reply;
692
693 to = get_sock_lsa(G.listen_fd);
694 from = xzalloc(to->len);
695
696 size = recv_from_to(fd, &query, sizeof(query), 0, from, &to->u.sa, to->len);
697 if (size == -1)
698 bb_error_msg_and_die("recv_from_to");
699 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
700 char *addr = xmalloc_sockaddr2dotted_noport(from);
701 bb_error_msg("malformed packet received from %s", addr);
702 free(addr);
703 goto bail;
704 }
705
706 rectime = gettime();
707 version = (query.status & VERSION_MASK) >> 3;
708
709 memset(&reply, 0, sizeof(reply));
710 reply.status = G.status.synced ? G.status.leap : LI_ALARM;
711 reply.status |= (query.status & VERSION_MASK);
712 reply.status |= ((query.status & MODE_MASK) == MODE_CLIENT) ?
713 MODE_SERVER : MODE_SYM_PAS;
714 reply.stratum = G.status.stratum;
715 reply.ppoll = query.ppoll;
716 reply.precision = G.status.precision;
717 reply.rectime = d_to_lfp(rectime);
718 reply.reftime = d_to_lfp(G.status.reftime);
719 reply.xmttime = d_to_lfp(gettime());
720 reply.orgtime = query.xmttime;
721 reply.rootdelay = d_to_sfp(G.status.rootdelay);
722 reply.refid = (version > 3) ? G.status.refid4 : G.status.refid;
723
724 /* We reply from the address packet was sent to,
725 * this makes to/from look swapped here: */
726 sendmsg_wrap(fd, /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
727 &reply, size);
728
729 bail:
730 free(to);
731 free(from);
732}
733#endif
734
735/* Upstream ntpd's options:
736 *
737 * -4 Force DNS resolution of host names to the IPv4 namespace.
738 * -6 Force DNS resolution of host names to the IPv6 namespace.
739 * -a Require cryptographic authentication for broadcast client,
740 * multicast client and symmetric passive associations.
741 * This is the default.
742 * -A Do not require cryptographic authentication for broadcast client,
743 * multicast client and symmetric passive associations.
744 * This is almost never a good idea.
745 * -b Enable the client to synchronize to broadcast servers.
746 * -c conffile
747 * Specify the name and path of the configuration file,
748 * default /etc/ntp.conf
749 * -d Specify debugging mode. This option may occur more than once,
750 * with each occurrence indicating greater detail of display.
751 * -D level
752 * Specify debugging level directly.
753 * -f driftfile
754 * Specify the name and path of the frequency file.
755 * This is the same operation as the "driftfile FILE"
756 * configuration command.
757 * -g Normally, ntpd exits with a message to the system log
758 * if the offset exceeds the panic threshold, which is 1000 s
759 * by default. This option allows the time to be set to any value
760 * without restriction; however, this can happen only once.
761 * If the threshold is exceeded after that, ntpd will exit
762 * with a message to the system log. This option can be used
763 * with the -q and -x options. See the tinker command for other options.
764 * -i jaildir
765 * Chroot the server to the directory jaildir. This option also implies
766 * that the server attempts to drop root privileges at startup
767 * (otherwise, chroot gives very little additional security).
768 * You may need to also specify a -u option.
769 * -k keyfile
770 * Specify the name and path of the symmetric key file,
771 * default /etc/ntp/keys. This is the same operation
772 * as the "keys FILE" configuration command.
773 * -l logfile
774 * Specify the name and path of the log file. The default
775 * is the system log file. This is the same operation as
776 * the "logfile FILE" configuration command.
777 * -L Do not listen to virtual IPs. The default is to listen.
778 * -n Don't fork.
779 * -N To the extent permitted by the operating system,
780 * run the ntpd at the highest priority.
781 * -p pidfile
782 * Specify the name and path of the file used to record the ntpd
783 * process ID. This is the same operation as the "pidfile FILE"
784 * configuration command.
785 * -P priority
786 * To the extent permitted by the operating system,
787 * run the ntpd at the specified priority.
788 * -q Exit the ntpd just after the first time the clock is set.
789 * This behavior mimics that of the ntpdate program, which is
790 * to be retired. The -g and -x options can be used with this option.
791 * Note: The kernel time discipline is disabled with this option.
792 * -r broadcastdelay
793 * Specify the default propagation delay from the broadcast/multicast
794 * server to this client. This is necessary only if the delay
795 * cannot be computed automatically by the protocol.
796 * -s statsdir
797 * Specify the directory path for files created by the statistics
798 * facility. This is the same operation as the "statsdir DIR"
799 * configuration command.
800 * -t key
801 * Add a key number to the trusted key list. This option can occur
802 * more than once.
803 * -u user[:group]
804 * Specify a user, and optionally a group, to switch to.
805 * -v variable
806 * -V variable
807 * Add a system variable listed by default.
808 * -x Normally, the time is slewed if the offset is less than the step
809 * threshold, which is 128 ms by default, and stepped if above
810 * the threshold. This option sets the threshold to 600 s, which is
811 * well within the accuracy window to set the clock manually.
812 * Note: since the slew rate of typical Unix kernels is limited
813 * to 0.5 ms/s, each second of adjustment requires an amortization
814 * interval of 2000 s. Thus, an adjustment as much as 600 s
815 * will take almost 14 days to complete. This option can be used
816 * with the -g and -q options. See the tinker command for other options.
817 * Note: The kernel time discipline is disabled with this option.
818 */
819
820enum {
821 OPT_n = (1 << 0),
822 OPT_g = (1 << 1),
823 OPT_p = (1 << 2),
824 OPT_l = (1 << 3),
825};
826
827/* By doing init in a separate function we decrease stack usage
828 * in main loop.
829 */
830static NOINLINE void ntp_init(char **argv)
831{
832 unsigned opts;
833 llist_t *peers;
834
835 tzset();
836
837 if (getuid())
838 bb_error_msg_and_die("need root privileges");
839
840 peers = NULL;
841 opt_complementary = "dd:p::"; /* d: counter, p: list */
842 opts = getopt32(argv,
843 "ng" /* compat */
844 "p:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
845 "d" /* compat */
846 "46aAbLNx", /* compat, ignored */
847 &peers, &G.verbose);
848#if ENABLE_FEATURE_NTPD_SERVER
849 G.listen_fd = -1;
850 if (opts & OPT_l) {
851 G.listen_fd = create_and_bind_dgram_or_die(NULL, 123);
852 socket_want_pktinfo(G.listen_fd);
853 setsockopt(G.listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
854 }
855#endif
856 if (opts & OPT_g)
857 G.settime = 1;
858 while (peers)
859 add_peers(llist_pop(&peers));
860 if (!(opts & OPT_n)) {
861 logmode = LOGMODE_NONE;
862 bb_daemonize(DAEMON_DEVNULL_STDIO);
863 }
864
865 /* Set some globals */
866 {
867 int prec = 0;
868 int b;
869#if 0
870 struct timespec tp;
871 /* We can use sys_clock_getres but assuming 10ms tick should be fine */
872 clock_getres(CLOCK_REALTIME, &tp);
873 tp.tv_sec = 0;
874 tp.tv_nsec = 10000000;
875 b = 1000000000 / tp.tv_nsec; /* convert to Hz */
876#else
877 b = 100; /* b = 1000000000/10000000 = 100 */
878#endif
879 while (b > 1)
880 prec--, b >>= 1;
881 G.status.precision = prec;
882 }
883 G.scale = 1;
884 G.firstadj = 1;
885
886 bb_signals((1 << SIGTERM) | (1 << SIGINT), record_signo);
887 bb_signals((1 << SIGPIPE) | (1 << SIGHUP), SIG_IGN);
888}
889
890int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
891int ntpd_main(int argc UNUSED_PARAM, char **argv)
892{
893 struct globals g;
894 unsigned new_cnt;
895 struct pollfd *pfd;
896 ntp_peer_t **idx2peer;
897
898 memset(&g, 0, sizeof(g));
899 SET_PTR_TO_GLOBALS(&g);
900
901 ntp_init(argv);
902
903 new_cnt = g.peer_cnt;
904 idx2peer = xzalloc(sizeof(void *) * new_cnt);
905#if ENABLE_FEATURE_NTPD_SERVER
906 if (g.listen_fd != -1)
907 new_cnt++;
908#endif
909 pfd = xzalloc(sizeof(pfd[0]) * new_cnt);
910
911 while (!bb_got_signal) {
912 llist_t *item;
913 unsigned i, j, idx_peers;
914 unsigned sent_cnt, trial_cnt;
915 int nfds, timeout;
916 time_t nextaction;
917
918 nextaction = time(NULL) + 3600;
919
920 i = 0;
921#if ENABLE_FEATURE_NTPD_SERVER
922 if (g.listen_fd != -1) {
923 pfd[0].fd = g.listen_fd;
924 pfd[0].events = POLLIN;
925 i++;
926 }
927#endif
928 idx_peers = i;
929 sent_cnt = trial_cnt = 0;
930 for (item = g.ntp_peers; item != NULL; item = item->link) {
931 ntp_peer_t *p = (ntp_peer_t *) item->data;
932
933 if (p->next > 0 && p->next <= time(NULL)) {
934 trial_cnt++;
935 if (client_query(p) == 0)
936 sent_cnt++;
937 }
938 if (p->next > 0 && p->next < nextaction)
939 nextaction = p->next;
940 if (p->deadline > 0 && p->deadline < nextaction)
941 nextaction = p->deadline;
942
943 if (p->deadline > 0 && p->deadline <= time(NULL)) {
944 char *addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
945
946 timeout = error_interval();
947 bb_info_msg("no reply from %s received in time, "
948 "next query %ds", addr, timeout);
949 if (p->trustlevel >= TRUSTLEVEL_BADPEER) {
950 p->trustlevel /= 2;
951 if (p->trustlevel < TRUSTLEVEL_BADPEER)
952 bb_info_msg("peer %s now invalid", addr);
953 }
954 free(addr);
955
956 set_next(p, timeout);
957 }
958
959 if (p->state == STATE_QUERY_SENT) {
960 pfd[i].fd = p->query.fd;
961 pfd[i].events = POLLIN;
962 idx2peer[i - idx_peers] = p;
963 i++;
964 }
965 }
966
967 if (g.settime
968 && ((trial_cnt > 0 && sent_cnt == 0) || g.peer_cnt == 0)
969 ) {
970 settime(0); /* no good peers, don't wait */
971 }
972
973 timeout = nextaction - time(NULL);
974 if (timeout < 0)
975 timeout = 0;
976
977 if (g.verbose)
978 bb_error_msg("entering poll %u secs", timeout);
979 nfds = poll(pfd, i, timeout * 1000);
980
981 j = 0;
982#if ENABLE_FEATURE_NTPD_SERVER
983 for (; nfds > 0 && j < idx_peers; j++) {
984 if (pfd[j].revents & (POLLIN|POLLERR)) {
985 nfds--;
986 server_dispatch(pfd[j].fd);
987 }
988 }
989#endif
990 for (; nfds > 0 && j < i; j++) {
991 if (pfd[j].revents & (POLLIN|POLLERR)) {
992 nfds--;
993 client_dispatch(idx2peer[j - idx_peers]);
994 }
995 }
996 } /* while (!bb_got_signal) */
997
998 kill_myself_with_sig(bb_got_signal);
999}