aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-12-02 01:51:24 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-12-02 01:51:24 +0100
commit386960a38e5aee4f56a04214f86709c71dff120d (patch)
tree416cf9f19ee69749fbeb33931bc464edafe74321 /networking/ntpd.c
parentfae9f499b2ab3becb8a672d982c50f318114dee9 (diff)
downloadbusybox-w32-386960a38e5aee4f56a04214f86709c71dff120d.tar.gz
busybox-w32-386960a38e5aee4f56a04214f86709c71dff120d.tar.bz2
busybox-w32-386960a38e5aee4f56a04214f86709c71dff120d.zip
htpd: better logging; removed some unused code and data. -212 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r--networking/ntpd.c443
1 files changed, 222 insertions, 221 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index f10a81cee..3b9e7b7ff 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -67,27 +67,21 @@ enum {
67}; 67};
68 68
69typedef struct { 69typedef struct {
70 uint8_t status; /* status of local clock and leap info */ 70 uint8_t m_status; /* status of local clock and leap info */
71 uint8_t stratum; /* stratum level */ 71 uint8_t m_stratum; /* stratum level */
72 uint8_t ppoll; /* poll value */ 72 uint8_t m_ppoll; /* poll value */
73 int8_t precision; 73 int8_t m_precision;
74 s_fixedpt_t rootdelay; 74 s_fixedpt_t m_rootdelay;
75 s_fixedpt_t dispersion; 75 s_fixedpt_t m_dispersion;
76 uint32_t refid; 76 uint32_t m_refid;
77 l_fixedpt_t reftime; 77 l_fixedpt_t m_reftime;
78 l_fixedpt_t orgtime; 78 l_fixedpt_t m_orgtime;
79 l_fixedpt_t rectime; 79 l_fixedpt_t m_rectime;
80 l_fixedpt_t xmttime; 80 l_fixedpt_t m_xmttime;
81 uint32_t keyid; 81 uint32_t m_keyid;
82 uint8_t digest[NTP_DIGESTSIZE]; 82 uint8_t m_digest[NTP_DIGESTSIZE];
83} ntp_msg_t; 83} ntp_msg_t;
84 84
85typedef struct {
86 int fd;
87 ntp_msg_t msg;
88 double xmttime;
89} ntp_query_t;
90
91enum { 85enum {
92 NTP_VERSION = 4, 86 NTP_VERSION = 4,
93 NTP_MAXSTRATUM = 15, 87 NTP_MAXSTRATUM = 15,
@@ -116,48 +110,38 @@ enum {
116 110
117#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */ 111#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
118 112
119enum client_state {
120 STATE_NONE,
121 STATE_QUERY_SENT,
122 STATE_REPLY_RECEIVED,
123};
124
125typedef struct { 113typedef struct {
126 double rootdelay; 114 double o_offset;
127 double rootdispersion; 115 double o_delay;
128 double reftime; 116 //UNUSED: double o_error;
129 uint32_t refid; 117 time_t o_rcvd;
130 uint32_t refid4; 118 uint32_t o_refid4;
131 uint8_t synced; 119 uint8_t o_leap;
132 uint8_t leap; 120 uint8_t o_stratum;
133 int8_t precision; 121 uint8_t o_good;
134 uint8_t poll;
135 uint8_t stratum;
136} ntp_status_t;
137
138typedef struct {
139 ntp_status_t status;
140 double offset;
141 double delay;
142 double error;
143 time_t rcvd;
144 uint8_t good;
145} ntp_offset_t; 122} ntp_offset_t;
146 123
147typedef struct { 124typedef struct {
148//TODO: 125//TODO: periodically re-resolve DNS names?
149// (1) store dotted addr str, to avoid constant translations
150// (2) periodically re-resolve DNS names
151 len_and_sockaddr *lsa; 126 len_and_sockaddr *lsa;
152 ntp_query_t query; 127 char *dotted;
153 ntp_offset_t reply[OFFSET_ARRAY_SIZE]; 128 double xmttime;
154 ntp_offset_t update;
155 enum client_state state;
156 time_t next; 129 time_t next;
157 time_t deadline; 130 time_t deadline;
131 int fd;
132 uint8_t state;
158 uint8_t shift; 133 uint8_t shift;
159 uint8_t trustlevel; 134 uint8_t trustlevel;
135 ntp_msg_t msg;
136 ntp_offset_t update;
137 ntp_offset_t reply[OFFSET_ARRAY_SIZE];
160} ntp_peer_t; 138} ntp_peer_t;
139/* for ntp_peer_t::state */
140enum {
141 STATE_NONE,
142 STATE_QUERY_SENT,
143 STATE_REPLY_RECEIVED,
144};
161 145
162enum { 146enum {
163 OPT_n = (1 << 0), 147 OPT_n = (1 << 0),
@@ -172,14 +156,21 @@ enum {
172 156
173 157
174struct globals { 158struct globals {
175 unsigned verbose; 159 double rootdelay;
160 double reftime;
161 llist_t *ntp_peers;
176#if ENABLE_FEATURE_NTPD_SERVER 162#if ENABLE_FEATURE_NTPD_SERVER
177 int listen_fd; 163 int listen_fd;
178#endif 164#endif
165 unsigned verbose;
179 unsigned peer_cnt; 166 unsigned peer_cnt;
180 llist_t *ntp_peers; 167 uint32_t refid;
181 ntp_status_t status; 168 uint32_t refid4;
182 uint32_t scale; 169 uint32_t scale;
170 uint8_t synced;
171 uint8_t leap;
172 int8_t precision;
173 uint8_t stratum;
183 uint8_t time_is_set; 174 uint8_t time_is_set;
184 uint8_t first_adj_done; 175 uint8_t first_adj_done;
185}; 176};
@@ -190,7 +181,7 @@ static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
190 181
191 182
192static void 183static void
193set_next(ntp_peer_t *p, time_t t) 184set_next(ntp_peer_t *p, unsigned t)
194{ 185{
195 p->next = time(NULL) + t; 186 p->next = time(NULL) + t;
196 p->deadline = 0; 187 p->deadline = 0;
@@ -204,12 +195,12 @@ add_peers(const char *s)
204 p = xzalloc(sizeof(*p)); 195 p = xzalloc(sizeof(*p));
205//TODO: big ntpd uses all IPs, not just 1st, do we need to mimic that? 196//TODO: big ntpd uses all IPs, not just 1st, do we need to mimic that?
206 p->lsa = xhost2sockaddr(s, 123); 197 p->lsa = xhost2sockaddr(s, 123);
207 p->query.fd = -1; 198 p->dotted = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
208 p->query.msg.status = MODE_CLIENT | (NTP_VERSION << 3); 199 p->fd = -1;
200 p->msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
209 if (STATE_NONE != 0) 201 if (STATE_NONE != 0)
210 p->state = STATE_NONE; 202 p->state = STATE_NONE;
211 p->trustlevel = TRUSTLEVEL_PATHETIC; 203 p->trustlevel = TRUSTLEVEL_PATHETIC;
212 p->query.fd = -1;
213 set_next(p, 0); 204 set_next(p, 0);
214 205
215 llist_add_to(&G.ntp_peers, p); 206 llist_add_to(&G.ntp_peers, p);
@@ -241,6 +232,7 @@ lfp_to_d(l_fixedpt_t lfp)
241 return ret; 232 return ret;
242} 233}
243 234
235#if 0 //UNUSED
244static double 236static double
245sfp_to_d(s_fixedpt_t sfp) 237sfp_to_d(s_fixedpt_t sfp)
246{ 238{
@@ -250,6 +242,7 @@ sfp_to_d(s_fixedpt_t sfp)
250 ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX); 242 ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX);
251 return ret; 243 return ret;
252} 244}
245#endif
253 246
254#if ENABLE_FEATURE_NTPD_SERVER 247#if ENABLE_FEATURE_NTPD_SERVER
255static l_fixedpt_t 248static l_fixedpt_t
@@ -282,17 +275,17 @@ set_deadline(ntp_peer_t *p, time_t t)
282 p->next = 0; 275 p->next = 0;
283} 276}
284 277
285static time_t 278static unsigned
286error_interval(void) 279error_interval(void)
287{ 280{
288 time_t interval, r; 281 unsigned interval, r;
289 interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN; 282 interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
290 r = (unsigned)random() % (unsigned long)(interval / 10); 283 r = (unsigned)random() % (unsigned)(interval / 10);
291 return (interval + r); 284 return (interval + r);
292} 285}
293 286
294static int 287static int
295sendmsg_wrap(int fd, 288do_sendto(int fd,
296 const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen, 289 const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen,
297 ntp_msg_t *msg, ssize_t len) 290 ntp_msg_t *msg, ssize_t len)
298{ 291{
@@ -331,16 +324,16 @@ send_query_to_peer(ntp_peer_t *p)
331 // Uncomment this and use strace to see it in action: 324 // Uncomment this and use strace to see it in action:
332#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } 325#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); }
333 326
334 if (p->query.fd == -1) { 327 if (p->fd == -1) {
335 int fd, family; 328 int fd, family;
336 len_and_sockaddr *local_lsa; 329 len_and_sockaddr *local_lsa;
337 330
338 family = p->lsa->u.sa.sa_family; 331 family = p->lsa->u.sa.sa_family;
339 //was: p->query.fd = xsocket(family, SOCK_DGRAM, 0); 332 //was: p->fd = xsocket(family, SOCK_DGRAM, 0);
340 p->query.fd = fd = xsocket_type(&local_lsa, family, SOCK_DGRAM); 333 p->fd = fd = xsocket_type(&local_lsa, family, SOCK_DGRAM);
341 /* local_lsa has "null" address and port 0 now. 334 /* local_lsa has "null" address and port 0 now.
342 * bind() ensures we have a *particular port* selected by kernel 335 * bind() ensures we have a *particular port* selected by kernel
343 * and remembered in p->query.fd, thus later recv(p->query.fd) 336 * and remembered in p->fd, thus later recv(p->fd)
344 * receives only packets sent to this port. 337 * receives only packets sent to this port.
345 */ 338 */
346 PROBE_LOCAL_ADDR 339 PROBE_LOCAL_ADDR
@@ -367,16 +360,19 @@ send_query_to_peer(ntp_peer_t *p)
367 * Save the real transmit timestamp locally. 360 * Save the real transmit timestamp locally.
368 */ 361 */
369 362
370 p->query.msg.xmttime.int_partl = random(); 363 p->msg.m_xmttime.int_partl = random();
371 p->query.msg.xmttime.fractionl = random(); 364 p->msg.m_xmttime.fractionl = random();
372 p->query.xmttime = gettime1900fp(); 365 p->xmttime = gettime1900fp();
373 366
374 if (sendmsg_wrap(p->query.fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len, 367 if (do_sendto(p->fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len,
375 &p->query.msg, NTP_MSGSIZE_NOAUTH) == -1) { 368 &p->msg, NTP_MSGSIZE_NOAUTH) == -1
369 ) {
376 set_next(p, INTERVAL_QUERY_PATHETIC); 370 set_next(p, INTERVAL_QUERY_PATHETIC);
377 return -1; 371 return -1;
378 } 372 }
379 373
374 if (G.verbose)
375 bb_error_msg("sent request to %s", p->dotted);
380 p->state = STATE_QUERY_SENT; 376 p->state = STATE_QUERY_SENT;
381 set_deadline(p, QUERYTIME_MAX); 377 set_deadline(p, QUERYTIME_MAX);
382 378
@@ -384,13 +380,13 @@ send_query_to_peer(ntp_peer_t *p)
384} 380}
385 381
386static int 382static int
387offset_compare(const void *aa, const void *bb) 383compare_offsets(const void *aa, const void *bb)
388{ 384{
389 const ntp_peer_t *const *a = aa; 385 const ntp_peer_t *const *a = aa;
390 const ntp_peer_t *const *b = bb; 386 const ntp_peer_t *const *b = bb;
391 if ((*a)->update.offset < (*b)->update.offset) 387 if ((*a)->update.o_offset < (*b)->update.o_offset)
392 return -1; 388 return -1;
393 return ((*a)->update.offset > (*b)->update.offset); 389 return ((*a)->update.o_offset > (*b)->update.o_offset);
394} 390}
395 391
396static uint32_t 392static uint32_t
@@ -406,24 +402,20 @@ updated_scale(double offset)
406} 402}
407 403
408static void 404static void
409adjtime_wrap(void) 405slew_time(void)
410{ 406{
411 ntp_peer_t *p; 407 ntp_peer_t *p;
408 llist_t *item;
412 unsigned offset_cnt; 409 unsigned offset_cnt;
413 unsigned middle;
414 int i = 0;
415 ntp_peer_t **peers;
416 double offset_median; 410 double offset_median;
417 llist_t *item; 411 struct timeval tv;
418 len_and_sockaddr *lsa;
419 struct timeval tv, olddelta;
420 412
421 offset_cnt = 0; 413 offset_cnt = 0;
422 for (item = G.ntp_peers; item != NULL; item = item->link) { 414 for (item = G.ntp_peers; item != NULL; item = item->link) {
423 p = (ntp_peer_t *) item->data; 415 p = (ntp_peer_t *) item->data;
424 if (p->trustlevel < TRUSTLEVEL_BADPEER) 416 if (p->trustlevel < TRUSTLEVEL_BADPEER)
425 continue; 417 continue;
426 if (!p->update.good) 418 if (!p->update.o_good)
427 return; 419 return;
428 offset_cnt++; 420 offset_cnt++;
429 } 421 }
@@ -431,68 +423,74 @@ adjtime_wrap(void)
431 if (offset_cnt == 0) 423 if (offset_cnt == 0)
432 goto clear_good; 424 goto clear_good;
433 425
434 peers = xzalloc(sizeof(peers[0]) * offset_cnt); 426 {
435 for (item = G.ntp_peers; item != NULL; item = item->link) { 427 len_and_sockaddr *lsa;
436 p = (ntp_peer_t *) item->data; 428 unsigned middle;
437 if (p->trustlevel < TRUSTLEVEL_BADPEER) 429 unsigned i = 0;
438 continue; 430 ntp_peer_t **peers = xzalloc(sizeof(peers[0]) * offset_cnt);
439 peers[i++] = p; 431
440 } 432 for (item = G.ntp_peers; item != NULL; item = item->link) {
441 433 p = (ntp_peer_t *) item->data;
442 qsort(peers, offset_cnt, sizeof(peers[0]), offset_compare); 434 if (p->trustlevel < TRUSTLEVEL_BADPEER)
435 continue;
436 peers[i++] = p;
437 }
443 438
444 middle = offset_cnt / 2; 439 qsort(peers, offset_cnt, sizeof(peers[0]), compare_offsets);
445 if (middle != 0 && (offset_cnt & 1) == 0) { 440
446 offset_median = (peers[middle-1]->update.offset + peers[middle]->update.offset) / 2; 441 middle = offset_cnt / 2;
447 G.status.rootdelay = (peers[middle-1]->update.delay + peers[middle]->update.delay) / 2; 442 if (middle != 0 && (offset_cnt & 1) == 0) {
448 G.status.stratum = MAX(peers[middle-1]->update.status.stratum, peers[middle]->update.status.stratum); 443 offset_median = (peers[middle-1]->update.o_offset + peers[middle]->update.o_offset) / 2;
449 } else { 444 G.rootdelay = (peers[middle-1]->update.o_delay + peers[middle]->update.o_delay) / 2;
450 offset_median = peers[middle]->update.offset; 445 G.stratum = 1 + MAX(peers[middle-1]->update.o_stratum, peers[middle]->update.o_stratum);
451 G.status.rootdelay = peers[middle]->update.delay; 446 } else {
452 G.status.stratum = peers[middle]->update.status.stratum; 447 offset_median = peers[middle]->update.o_offset;
448 G.rootdelay = peers[middle]->update.o_delay;
449 G.stratum = 1 + peers[middle]->update.o_stratum;
450 }
451 G.leap = peers[middle]->update.o_leap;
452 G.refid4 = peers[middle]->update.o_refid4;
453 lsa = peers[middle]->lsa;
454 G.refid =
455#if ENABLE_FEATURE_IPV6
456 lsa->u.sa.sa_family != AF_INET ?
457 G.refid4 :
458#endif
459 lsa->u.sin.sin_addr.s_addr;
460 free(peers);
453 } 461 }
454 G.status.leap = peers[middle]->update.status.leap;
455 462
456 bb_info_msg("adjusting local clock by %fs", offset_median); 463 bb_error_msg("adjusting clock by %fs, our stratum is %u", offset_median, G.stratum);
464
457 errno = 0; 465 errno = 0;
458 d_to_tv(offset_median, &tv); 466 d_to_tv(offset_median, &tv);
459 if (adjtime(&tv, &olddelta) == -1) { 467 if (adjtime(&tv, &tv) == -1) {
460 bb_perror_msg("adjtime failed"); //TODO: maybe _and_die? 468 bb_perror_msg("adjtime failed"); //TODO: maybe _and_die?
461 } else 469 } else {
462 if (G.first_adj_done 470 if (G.verbose >= 2)
463 && olddelta.tv_sec == 0 471 bb_error_msg("old adjust: %d.%06u", (int)tv.tv_sec, (unsigned)tv.tv_usec);
464 && olddelta.tv_usec == 0 472 if (G.first_adj_done
465 && !G.status.synced 473 && tv.tv_sec == 0
466 ) { 474 && tv.tv_usec == 0 // TODO: allow for tiny values?
467 bb_info_msg("clock synced"); 475 && !G.synced
468 G.status.synced = 1; 476 ) {
469 } else 477 G.synced = 1;
470 if (G.status.synced) { 478 bb_error_msg("clock %ssynced", "");
471 bb_info_msg("clock unsynced"); 479 } else
472 G.status.synced = 0; 480 if (G.synced) {
481 G.synced = 0;
482 bb_error_msg("clock %ssynced", "un");
483 }
473 } 484 }
474 485
475 G.first_adj_done = 1; 486 G.first_adj_done = 1;
476 G.status.reftime = gettime1900fp(); 487 G.reftime = gettime1900fp();
477 G.status.stratum++; /* one more than selected peer */
478 G.scale = updated_scale(offset_median); 488 G.scale = updated_scale(offset_median);
479 489
480 G.status.refid4 = peers[middle]->update.status.refid4;
481
482 lsa = peers[middle]->lsa;
483 G.status.refid =
484#if ENABLE_FEATURE_IPV6
485 lsa->u.sa.sa_family != AF_INET ?
486 G.status.refid4 :
487#endif
488 lsa->u.sin.sin_addr.s_addr;
489
490 free(peers);
491
492 clear_good: 490 clear_good:
493 for (item = G.ntp_peers; item != NULL; item = item->link) { 491 for (item = G.ntp_peers; item != NULL; item = item->link) {
494 p = (ntp_peer_t *) item->data; 492 p = (ntp_peer_t *) item->data;
495 p->update.good = 0; 493 p->update.o_good = 0;
496 } 494 }
497} 495}
498 496
@@ -530,7 +528,7 @@ step_time_once(double offset)
530 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval)); 528 strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", localtime(&tval));
531 529
532 /* Do we want to print message below to system log when daemonized? */ 530 /* Do we want to print message below to system log when daemonized? */
533 bb_info_msg("set local clock to %s (offset %fs)", buf, offset); 531 bb_error_msg("set local clock to %s (offset %fs)", buf, offset);
534 532
535 for (item = G.ntp_peers; item != NULL; item = item->link) { 533 for (item = G.ntp_peers; item != NULL; item = item->link) {
536 p = (ntp_peer_t *) item->data; 534 p = (ntp_peer_t *) item->data;
@@ -548,69 +546,68 @@ step_time_once(double offset)
548static void 546static void
549update_peer_data(ntp_peer_t *p) 547update_peer_data(ntp_peer_t *p)
550{ 548{
551 int i, best = 0, good = 0; 549 /* Clock filter.
552 550 * Find the offset which arrived with the lowest delay.
553 /* 551 * Use that as the peer update.
554 * clock filter 552 * Invalidate it and all older ones.
555 * find the offset which arrived with the lowest delay
556 * use that as the peer update
557 * invalidate it and all older ones
558 */ 553 */
554 int i;
555 int best = best; /* for compiler */
556 int good;
559 557
560 for (i = 0; good == 0 && i < OFFSET_ARRAY_SIZE; i++) { 558 good = 0;
561 if (p->reply[i].good) { 559 for (i = 0; i < OFFSET_ARRAY_SIZE; i++) {
560 if (p->reply[i].o_good) {
562 good++; 561 good++;
563 best = i; 562 best = i++;
563 break;
564 } 564 }
565 } 565 }
566 566
567 for (; i < OFFSET_ARRAY_SIZE; i++) { 567 for (; i < OFFSET_ARRAY_SIZE; i++) {
568 if (p->reply[i].good) { 568 if (p->reply[i].o_good) {
569 good++; 569 good++;
570 if (p->reply[i].delay < p->reply[best].delay) 570 if (p->reply[i].o_delay < p->reply[best].o_delay)
571 best = i; 571 best = i;
572 } 572 }
573 } 573 }
574 574
575 if (good < 8) 575 if (good < 8) //FIXME: was it meant to be OFFSET_ARRAY_SIZE, not 8?
576 return; 576 return;
577 577
578 memcpy(&p->update, &p->reply[best], sizeof(p->update)); 578 memcpy(&p->update, &p->reply[best], sizeof(p->update));
579 adjtime_wrap(); 579 slew_time();
580 580
581 for (i = 0; i < OFFSET_ARRAY_SIZE; i++) 581 for (i = 0; i < OFFSET_ARRAY_SIZE; i++)
582 if (p->reply[i].rcvd <= p->reply[best].rcvd) 582 if (p->reply[i].o_rcvd <= p->reply[best].o_rcvd)
583 p->reply[i].good = 0; 583 p->reply[i].o_good = 0;
584} 584}
585 585
586static time_t 586static unsigned
587scale_interval(time_t requested) 587scale_interval(unsigned requested)
588{ 588{
589 time_t interval, r; 589 unsigned interval, r;
590 interval = requested * G.scale; 590 interval = requested * G.scale;
591 r = (unsigned)random() % (unsigned long)(MAX(5, interval / 10)); 591 r = (unsigned)random() % (unsigned)(MAX(5, interval / 10));
592 return (interval + r); 592 return (interval + r);
593} 593}
594 594
595static void 595static void
596recv_and_process_peer_pkt(ntp_peer_t *p) 596recv_and_process_peer_pkt(ntp_peer_t *p)
597{ 597{
598 char *addr;
599 ssize_t size; 598 ssize_t size;
600 ntp_msg_t msg; 599 ntp_msg_t msg;
601 double T1, T2, T3, T4; 600 double T1, T2, T3, T4;
602 time_t interval; 601 unsigned interval;
603 ntp_offset_t *offset; 602 ntp_offset_t *offset;
604 603
605 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
606
607 /* We can recvfrom here and check from.IP, but some multihomed 604 /* We can recvfrom here and check from.IP, but some multihomed
608 * ntp servers reply from their *other IP*. 605 * ntp servers reply from their *other IP*.
609 * TODO: maybe we should check at least what we can: from.port == 123? 606 * TODO: maybe we should check at least what we can: from.port == 123?
610 */ 607 */
611 size = recv(p->query.fd, &msg, sizeof(msg), MSG_DONTWAIT); 608 size = recv(p->fd, &msg, sizeof(msg), MSG_DONTWAIT);
612 if (size == -1) { 609 if (size == -1) {
613 bb_perror_msg("recv(%s) error", addr); 610 bb_perror_msg("recv(%s) error", p->dotted);
614 if (errno == EHOSTUNREACH || errno == EHOSTDOWN 611 if (errno == EHOSTUNREACH || errno == EHOSTDOWN
615 || errno == ENETUNREACH || errno == ENETDOWN 612 || errno == ENETUNREACH || errno == ENETDOWN
616 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL 613 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
@@ -618,7 +615,7 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
618 ) { 615 ) {
619//TODO: always do this? 616//TODO: always do this?
620 set_next(p, error_interval()); 617 set_next(p, error_interval());
621 goto bail; 618 goto close_sock;
622 } 619 }
623 xfunc_die(); 620 xfunc_die();
624 } 621 }
@@ -626,23 +623,23 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
626 T4 = gettime1900fp(); 623 T4 = gettime1900fp();
627 624
628 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 625 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
629 bb_error_msg("malformed packet received from %s", addr); 626 bb_error_msg("malformed packet received from %s", p->dotted);
630 goto bail; 627 goto bail;
631 } 628 }
632 629
633 if (msg.orgtime.int_partl != p->query.msg.xmttime.int_partl 630 if (msg.m_orgtime.int_partl != p->msg.m_xmttime.int_partl
634 || msg.orgtime.fractionl != p->query.msg.xmttime.fractionl 631 || msg.m_orgtime.fractionl != p->msg.m_xmttime.fractionl
635 ) { 632 ) {
636 goto bail; 633 goto bail;
637 } 634 }
638 635
639 if ((msg.status & LI_ALARM) == LI_ALARM 636 if ((msg.m_status & LI_ALARM) == LI_ALARM
640 || msg.stratum == 0 637 || msg.m_stratum == 0
641 || msg.stratum > NTP_MAXSTRATUM 638 || msg.m_stratum > NTP_MAXSTRATUM
642 ) { 639 ) {
643 interval = error_interval(); 640 interval = error_interval();
644 bb_info_msg("reply from %s: not synced, next query %ds", addr, (int) interval); 641 bb_error_msg("reply from %s: not synced, next query %us", p->dotted, interval);
645 goto bail; 642 goto close_sock;
646 } 643 }
647 644
648 /* 645 /*
@@ -660,34 +657,34 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
660 * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2. 657 * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2.
661 */ 658 */
662 659
663 T1 = p->query.xmttime; 660 T1 = p->xmttime;
664 T2 = lfp_to_d(msg.rectime); 661 T2 = lfp_to_d(msg.m_rectime);
665 T3 = lfp_to_d(msg.xmttime); 662 T3 = lfp_to_d(msg.m_xmttime);
666 663
667 offset = &p->reply[p->shift]; 664 offset = &p->reply[p->shift];
668 665
669 offset->offset = ((T2 - T1) + (T3 - T4)) / 2; 666 offset->o_offset = ((T2 - T1) + (T3 - T4)) / 2;
670 offset->delay = (T4 - T1) - (T3 - T2); 667 offset->o_delay = (T4 - T1) - (T3 - T2);
671 if (offset->delay < 0) { 668 if (offset->o_delay < 0) {
672 interval = error_interval(); 669 interval = error_interval();
673 set_next(p, interval); 670 set_next(p, interval);
674 bb_info_msg("reply from %s: negative delay %f", addr, p->reply[p->shift].delay); 671 bb_error_msg("reply from %s: negative delay %f", p->dotted, p->reply[p->shift].o_delay);
675 goto bail; 672 goto close_sock;
676 } 673 }
677 offset->error = (T2 - T1) - (T3 - T4); 674 //UNUSED: offset->o_error = (T2 - T1) - (T3 - T4);
678// Can we use (T4 - OFFSET_1900_1970) instead of time(NULL)? 675// Can we use (T4 - OFFSET_1900_1970) instead of time(NULL)?
679 offset->rcvd = time(NULL); 676 offset->o_rcvd = time(NULL);
680 offset->good = 1; 677 offset->o_good = 1;
681 678
682 offset->status.leap = (msg.status & LI_MASK); 679 offset->o_leap = (msg.m_status & LI_MASK);
683 offset->status.precision = msg.precision; 680 //UNUSED: offset->o_precision = msg.m_precision;
684 offset->status.rootdelay = sfp_to_d(msg.rootdelay); 681 //UNUSED: offset->o_rootdelay = sfp_to_d(msg.m_rootdelay);
685 offset->status.rootdispersion = sfp_to_d(msg.dispersion); 682 //UNUSED: offset->o_rootdispersion = sfp_to_d(msg.m_dispersion);
686 offset->status.refid = ntohl(msg.refid); 683 //UNUSED: offset->o_refid = ntohl(msg.m_refid);
687 offset->status.refid4 = msg.xmttime.fractionl; 684 offset->o_refid4 = msg.m_xmttime.fractionl;
688 offset->status.reftime = lfp_to_d(msg.reftime); 685 //UNUSED: offset->o_reftime = lfp_to_d(msg.m_reftime);
689 offset->status.poll = msg.ppoll; 686 //UNUSED: offset->o_poll = msg.m_ppoll;
690 offset->status.stratum = msg.stratum; 687 offset->o_stratum = msg.m_stratum;
691 688
692 if (p->trustlevel < TRUSTLEVEL_PATHETIC) 689 if (p->trustlevel < TRUSTLEVEL_PATHETIC)
693 interval = scale_interval(INTERVAL_QUERY_PATHETIC); 690 interval = scale_interval(INTERVAL_QUERY_PATHETIC);
@@ -703,21 +700,29 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
703 if (p->trustlevel < TRUSTLEVEL_MAX) { 700 if (p->trustlevel < TRUSTLEVEL_MAX) {
704 p->trustlevel++; 701 p->trustlevel++;
705 if (p->trustlevel == TRUSTLEVEL_BADPEER) 702 if (p->trustlevel == TRUSTLEVEL_BADPEER)
706 bb_info_msg("peer %s now valid", addr); 703 bb_error_msg("peer %s now valid", p->dotted);
707 } 704 }
708 705
709 bb_info_msg("reply from %s: offset %f delay %f, next query %ds", addr, 706 if (G.verbose)
710 offset->offset, offset->delay, (int) interval); 707 bb_error_msg("reply from %s: offset %f delay %f, next query %us", p->dotted,
708 offset->o_offset, offset->o_delay, interval);
711 709
712 update_peer_data(p); 710 update_peer_data(p);
713 step_time_once(offset->offset); 711 step_time_once(offset->o_offset);
714 712
715 p->shift++; 713 p->shift++;
716 if (p->shift >= OFFSET_ARRAY_SIZE) 714 if (p->shift >= OFFSET_ARRAY_SIZE)
717 p->shift = 0; 715 p->shift = 0;
718 716
717 close_sock:
718 /* We do not expect any more packets for now.
719 * Closing the socket informs kernel about it.
720 * We open a new socket when we send a new query.
721 */
722 close(p->fd);
723 p->fd = -1;
719 bail: 724 bail:
720 free(addr); 725 return;
721} 726}
722 727
723#if ENABLE_FEATURE_NTPD_SERVER 728#if ENABLE_FEATURE_NTPD_SERVER
@@ -751,31 +756,31 @@ recv_and_process_client_pkt(void /*int fd*/)
751 goto bail; 756 goto bail;
752 } 757 }
753 758
754 query_status = msg.status; 759 query_status = msg.m_status;
755 query_ppoll = msg.ppoll; 760 query_ppoll = msg.m_ppoll;
756 query_xmttime = msg.xmttime; 761 query_xmttime = msg.m_xmttime;
757 762
758 /* Build a reply packet */ 763 /* Build a reply packet */
759 memset(&msg, 0, sizeof(msg)); 764 memset(&msg, 0, sizeof(msg));
760 msg.status = G.status.synced ? G.status.leap : LI_ALARM; 765 msg.m_status = G.synced ? G.leap : LI_ALARM;
761 msg.status |= (query_status & VERSION_MASK); 766 msg.m_status |= (query_status & VERSION_MASK);
762 msg.status |= ((query_status & MODE_MASK) == MODE_CLIENT) ? 767 msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
763 MODE_SERVER : MODE_SYM_PAS; 768 MODE_SERVER : MODE_SYM_PAS;
764 msg.stratum = G.status.stratum; 769 msg.m_stratum = G.stratum;
765 msg.ppoll = query_ppoll; 770 msg.m_ppoll = query_ppoll;
766 msg.precision = G.status.precision; 771 msg.m_precision = G.precision;
767 rectime = gettime1900fp(); 772 rectime = gettime1900fp();
768 msg.xmttime = msg.rectime = d_to_lfp(rectime); 773 msg.m_xmttime = msg.m_rectime = d_to_lfp(rectime);
769 msg.reftime = d_to_lfp(G.status.reftime); 774 msg.m_reftime = d_to_lfp(G.reftime);
770 //msg.xmttime = d_to_lfp(gettime1900fp()); // = msg.rectime 775 //msg.m_xmttime = d_to_lfp(gettime1900fp()); // = msg.m_rectime
771 msg.orgtime = query_xmttime; 776 msg.m_orgtime = query_xmttime;
772 msg.rootdelay = d_to_sfp(G.status.rootdelay); 777 msg.m_rootdelay = d_to_sfp(G.rootdelay);
773 version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */ 778 version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
774 msg.refid = (version > (3 << VERSION_SHIFT)) ? G.status.refid4 : G.status.refid; 779 msg.m_refid = (version > (3 << VERSION_SHIFT)) ? G.refid4 : G.refid;
775 780
776 /* We reply from the local address packet was sent to, 781 /* We reply from the local address packet was sent to,
777 * this makes to/from look swapped here: */ 782 * this makes to/from look swapped here: */
778 sendmsg_wrap(G.listen_fd, 783 do_sendto(G.listen_fd,
779 /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len, 784 /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
780 &msg, size); 785 &msg, size);
781 786
@@ -931,7 +936,7 @@ static NOINLINE void ntp_init(char **argv)
931#endif 936#endif
932 while (b > 1) 937 while (b > 1)
933 prec--, b >>= 1; 938 prec--, b >>= 1;
934 G.status.precision = prec; 939 G.precision = prec;
935 } 940 }
936 G.scale = 1; 941 G.scale = 1;
937 942
@@ -991,18 +996,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
991 } 996 }
992 if (p->deadline != 0 && p->deadline <= cur_time) { 997 if (p->deadline != 0 && p->deadline <= cur_time) {
993 /* Timed out waiting for reply */ 998 /* Timed out waiting for reply */
994 char *addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
995
996 timeout = error_interval(); 999 timeout = error_interval();
997 bb_info_msg("no reply from %s received in time, " 1000 bb_error_msg("timed out waiting for %s, "
998 "next query %ds", addr, timeout); 1001 "next query %us", p->dotted, timeout);
999 if (p->trustlevel >= TRUSTLEVEL_BADPEER) { 1002 if (p->trustlevel >= TRUSTLEVEL_BADPEER) {
1000 p->trustlevel /= 2; 1003 p->trustlevel /= 2;
1001 if (p->trustlevel < TRUSTLEVEL_BADPEER) 1004 if (p->trustlevel < TRUSTLEVEL_BADPEER)
1002 bb_info_msg("peer %s now invalid", addr); 1005 bb_error_msg("peer %s now invalid", p->dotted);
1003 } 1006 }
1004 free(addr);
1005
1006 set_next(p, timeout); 1007 set_next(p, timeout);
1007 } 1008 }
1008 1009
@@ -1013,7 +1014,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1013 1014
1014 if (p->state == STATE_QUERY_SENT) { 1015 if (p->state == STATE_QUERY_SENT) {
1015 /* Wait for reply from this peer */ 1016 /* Wait for reply from this peer */
1016 pfd[i].fd = p->query.fd; 1017 pfd[i].fd = p->fd;
1017 pfd[i].events = POLLIN; 1018 pfd[i].events = POLLIN;
1018 idx2peer[i] = p; 1019 idx2peer[i] = p;
1019 i++; 1020 i++;
@@ -1024,12 +1025,12 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1024 step_time_once(0); /* no good peers, don't wait */ 1025 step_time_once(0); /* no good peers, don't wait */
1025 1026
1026 timeout = nextaction - cur_time; 1027 timeout = nextaction - cur_time;
1027 if (timeout < 0) 1028 if (timeout < 1)
1028 timeout = 0; 1029 timeout = 1;
1029 1030
1030 /* Here we may block */ 1031 /* Here we may block */
1031 if (g.verbose) 1032 if (g.verbose >= 2)
1032 bb_error_msg("entering poll %u secs", timeout); 1033 bb_error_msg("poll %u sec, waiting on %u sockets", timeout, i);
1033 nfds = poll(pfd, i, timeout * 1000); 1034 nfds = poll(pfd, i, timeout * 1000);
1034 if (nfds <= 0) 1035 if (nfds <= 0)
1035 continue; 1036 continue;