aboutsummaryrefslogtreecommitdiff
path: root/networking/ntpd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-24 07:07:42 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-24 07:07:42 +0100
commitca6c7e42f93eb2b0ce246eafd8b0e4ac27414f6b (patch)
tree05b52babec2451c1e7ef62e02a59ea30317eeaf8 /networking/ntpd.c
parent887d96303725d784e245c6562cf9fd5583b37224 (diff)
downloadbusybox-w32-ca6c7e42f93eb2b0ce246eafd8b0e4ac27414f6b.tar.gz
busybox-w32-ca6c7e42f93eb2b0ce246eafd8b0e4ac27414f6b.tar.bz2
busybox-w32-ca6c7e42f93eb2b0ce246eafd8b0e4ac27414f6b.zip
ntp: simplifications; libbb: simpler resolution of numeric hostnames
function old new delta str2sockaddr 405 567 +162 ntp_init 310 317 +7 scale_interval 58 59 +1 error_interval 22 23 +1 ntpd_main 3257 3214 -43 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 171/-43) Total: 128 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r--networking/ntpd.c208
1 files changed, 108 insertions, 100 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 8ee42e627..4e661ce98 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -5,7 +5,6 @@
5 * 5 *
6 * Licensed under GPLv2, see file LICENSE in this tarball for details. 6 * Licensed under GPLv2, see file LICENSE in this tarball for details.
7 */ 7 */
8
9#include "libbb.h" 8#include "libbb.h"
10#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */ 9#include <netinet/ip.h> /* For IPTOS_LOWDELAY definition */
11 10
@@ -59,30 +58,32 @@ typedef struct {
59 uint16_t fractions; 58 uint16_t fractions;
60} s_fixedpt_t; 59} s_fixedpt_t;
61 60
62#define NTP_DIGESTSIZE 16 61enum {
63#define NTP_MSGSIZE_NOAUTH 48 62 NTP_DIGESTSIZE = 16,
64#define NTP_MSGSIZE (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE) 63 NTP_MSGSIZE_NOAUTH = 48,
64 NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE),
65};
65 66
66typedef struct { 67typedef struct {
67 uint8_t status; /* status of local clock and leap info */ 68 uint8_t status; /* status of local clock and leap info */
68 uint8_t stratum; /* Stratum level */ 69 uint8_t stratum; /* stratum level */
69 uint8_t ppoll; /* poll value */ 70 uint8_t ppoll; /* poll value */
70 int8_t precision; 71 int8_t precision;
71 s_fixedpt_t rootdelay; 72 s_fixedpt_t rootdelay;
72 s_fixedpt_t dispersion; 73 s_fixedpt_t dispersion;
73 uint32_t refid; 74 uint32_t refid;
74 l_fixedpt_t reftime; 75 l_fixedpt_t reftime;
75 l_fixedpt_t orgtime; 76 l_fixedpt_t orgtime;
76 l_fixedpt_t rectime; 77 l_fixedpt_t rectime;
77 l_fixedpt_t xmttime; 78 l_fixedpt_t xmttime;
78 uint32_t keyid; 79 uint32_t keyid;
79 uint8_t digest[NTP_DIGESTSIZE]; 80 uint8_t digest[NTP_DIGESTSIZE];
80} ntp_msg_t; 81} ntp_msg_t;
81 82
82typedef struct { 83typedef struct {
83 int fd; 84 int fd;
84 ntp_msg_t msg; 85 ntp_msg_t msg;
85 double xmttime; 86 double xmttime;
86} ntp_query_t; 87} ntp_query_t;
87 88
88enum { 89enum {
@@ -97,6 +98,7 @@ enum {
97 /* Status Masks */ 98 /* Status Masks */
98 MODE_MASK = (7 << 0), 99 MODE_MASK = (7 << 0),
99 VERSION_MASK = (7 << 3), 100 VERSION_MASK = (7 << 3),
101 VERSION_SHIFT = 3,
100 LI_MASK = (3 << 6), 102 LI_MASK = (3 << 6),
101 103
102 /* Mode values */ 104 /* Mode values */
@@ -107,7 +109,7 @@ enum {
107 MODE_SERVER = 4, /* server */ 109 MODE_SERVER = 4, /* server */
108 MODE_BROADCAST = 5, /* broadcast */ 110 MODE_BROADCAST = 5, /* broadcast */
109 MODE_RES1 = 6, /* reserved for NTP control message */ 111 MODE_RES1 = 6, /* reserved for NTP control message */
110 MODE_RES2 = 7 /* reserved for private use */ 112 MODE_RES2 = 7, /* reserved for private use */
111}; 113};
112 114
113#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ 115#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
@@ -115,7 +117,7 @@ enum {
115enum client_state { 117enum client_state {
116 STATE_NONE, 118 STATE_NONE,
117 STATE_QUERY_SENT, 119 STATE_QUERY_SENT,
118 STATE_REPLY_RECEIVED 120 STATE_REPLY_RECEIVED,
119}; 121};
120 122
121typedef struct { 123typedef struct {
@@ -132,24 +134,27 @@ typedef struct {
132} ntp_status_t; 134} ntp_status_t;
133 135
134typedef struct { 136typedef struct {
135 ntp_status_t status; 137 ntp_status_t status;
136 double offset; 138 double offset;
137 double delay; 139 double delay;
138 double error; 140 double error;
139 time_t rcvd; 141 time_t rcvd;
140 uint8_t good; 142 uint8_t good;
141} ntp_offset_t; 143} ntp_offset_t;
142 144
143typedef struct { 145typedef struct {
146//TODO:
147// (1) store dotted addr str, to avoid constant translations
148// (2) periodically re-resolve DNS names
144 len_and_sockaddr *lsa; 149 len_and_sockaddr *lsa;
145 ntp_query_t query; 150 ntp_query_t query;
146 ntp_offset_t reply[OFFSET_ARRAY_SIZE]; 151 ntp_offset_t reply[OFFSET_ARRAY_SIZE];
147 ntp_offset_t update; 152 ntp_offset_t update;
148 enum client_state state; 153 enum client_state state;
149 time_t next; 154 time_t next;
150 time_t deadline; 155 time_t deadline;
151 uint8_t shift; 156 uint8_t shift;
152 uint8_t trustlevel; 157 uint8_t trustlevel;
153} ntp_peer_t; 158} ntp_peer_t;
154 159
155enum { 160enum {
@@ -211,8 +216,7 @@ add_peers(const char *s)
211static double 216static double
212gettime(void) 217gettime(void)
213{ 218{
214 struct timeval tv; 219 struct timeval tv;
215
216 gettimeofday(&tv, NULL); /* never fails */ 220 gettimeofday(&tv, NULL); /* never fails */
217 return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec); 221 return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
218} 222}
@@ -228,45 +232,43 @@ d_to_tv(double d, struct timeval *tv)
228static double 232static double
229lfp_to_d(l_fixedpt_t lfp) 233lfp_to_d(l_fixedpt_t lfp)
230{ 234{
231 double ret; 235 double ret;
232
233 lfp.int_partl = ntohl(lfp.int_partl); 236 lfp.int_partl = ntohl(lfp.int_partl);
234 lfp.fractionl = ntohl(lfp.fractionl); 237 lfp.fractionl = ntohl(lfp.fractionl);
235 ret = (double)(lfp.int_partl) + ((double)lfp.fractionl / UINT_MAX); 238 ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX);
236 return ret; 239 return ret;
237} 240}
238 241
239#if ENABLE_FEATURE_NTPD_SERVER
240static l_fixedpt_t
241d_to_lfp(double d)
242{
243 l_fixedpt_t lfp;
244
245 lfp.int_partl = htonl((uint32_t)d);
246 lfp.fractionl = htonl((uint32_t)((d - (u_int32_t)d) * UINT_MAX));
247 return lfp;
248}
249#endif
250
251static double 242static double
252sfp_to_d(s_fixedpt_t sfp) 243sfp_to_d(s_fixedpt_t sfp)
253{ 244{
254 double ret; 245 double ret;
255
256 sfp.int_parts = ntohs(sfp.int_parts); 246 sfp.int_parts = ntohs(sfp.int_parts);
257 sfp.fractions = ntohs(sfp.fractions); 247 sfp.fractions = ntohs(sfp.fractions);
258 ret = (double)(sfp.int_parts) + ((double)sfp.fractions / USHRT_MAX); 248 ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX);
259 return ret; 249 return ret;
260} 250}
261 251
262#if ENABLE_FEATURE_NTPD_SERVER 252#if ENABLE_FEATURE_NTPD_SERVER
253static l_fixedpt_t
254d_to_lfp(double d)
255{
256 l_fixedpt_t lfp;
257 lfp.int_partl = (uint32_t)d;
258 lfp.fractionl = (uint32_t)((d - lfp.int_partl) * UINT_MAX);
259 lfp.int_partl = htonl(lfp.int_partl);
260 lfp.fractionl = htonl(lfp.fractionl);
261 return lfp;
262}
263
263static s_fixedpt_t 264static s_fixedpt_t
264d_to_sfp(double d) 265d_to_sfp(double d)
265{ 266{
266 s_fixedpt_t sfp; 267 s_fixedpt_t sfp;
267 268 sfp.int_parts = (uint16_t)d;
268 sfp.int_parts = htons((uint16_t)d); 269 sfp.fractions = (uint16_t)((d - sfp.int_parts) * USHRT_MAX);
269 sfp.fractions = htons((uint16_t)((d - (u_int16_t)d) * USHRT_MAX)); 270 sfp.int_parts = htons(sfp.int_parts);
271 sfp.fractions = htons(sfp.fractions);
270 return sfp; 272 return sfp;
271} 273}
272#endif 274#endif
@@ -282,9 +284,8 @@ static time_t
282error_interval(void) 284error_interval(void)
283{ 285{
284 time_t interval, r; 286 time_t interval, r;
285
286 interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN; 287 interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN;
287 r = random() % (interval / 10); 288 r = (unsigned)random() % (unsigned long)(interval / 10);
288 return (interval + r); 289 return (interval + r);
289} 290}
290 291
@@ -352,12 +353,8 @@ client_query(ntp_peer_t *p)
352static int 353static int
353offset_compare(const void *aa, const void *bb) 354offset_compare(const void *aa, const void *bb)
354{ 355{
355 const ntp_peer_t * const *a; 356 const ntp_peer_t *const *a = aa;
356 const ntp_peer_t * const *b; 357 const ntp_peer_t *const *b = bb;
357
358 a = aa;
359 b = bb;
360
361 if ((*a)->update.offset < (*b)->update.offset) 358 if ((*a)->update.offset < (*b)->update.offset)
362 return -1; 359 return -1;
363 return ((*a)->update.offset > (*b)->update.offset); 360 return ((*a)->update.offset > (*b)->update.offset);
@@ -368,7 +365,6 @@ updated_scale(double offset)
368{ 365{
369 if (offset < 0) 366 if (offset < 0)
370 offset = -offset; 367 offset = -offset;
371
372 if (offset > QSCALE_OFF_MAX) 368 if (offset > QSCALE_OFF_MAX)
373 return 1; 369 return 1;
374 if (offset < QSCALE_OFF_MIN) 370 if (offset < QSCALE_OFF_MIN)
@@ -559,9 +555,8 @@ static time_t
559scale_interval(time_t requested) 555scale_interval(time_t requested)
560{ 556{
561 time_t interval, r; 557 time_t interval, r;
562
563 interval = requested * G.scale; 558 interval = requested * G.scale;
564 r = random() % MAX(5, interval / 10); 559 r = (unsigned)random() % (unsigned long)(MAX(5, interval / 10));
565 return (interval + r); 560 return (interval + r);
566} 561}
567 562
@@ -577,9 +572,10 @@ client_dispatch(ntp_peer_t *p)
577 572
578 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa); 573 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
579 574
580 size = recvfrom(p->query.fd, &msg, sizeof(msg), 0, NULL, NULL); 575//TODO: use MSG_DONTWAIT flag?
576 size = recv(p->query.fd, &msg, sizeof(msg), 0);
581 if (size == -1) { 577 if (size == -1) {
582 bb_perror_msg("recvfrom(%s) error", addr); 578 bb_perror_msg("recv(%s) error", addr);
583 if (errno == EHOSTUNREACH || errno == EHOSTDOWN 579 if (errno == EHOSTUNREACH || errno == EHOSTDOWN
584 || errno == ENETUNREACH || errno == ENETDOWN 580 || errno == ENETUNREACH || errno == ENETDOWN
585 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL 581 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
@@ -693,48 +689,58 @@ client_dispatch(ntp_peer_t *p)
693static void 689static void
694server_dispatch(int fd) 690server_dispatch(int fd)
695{ 691{
696 ssize_t size; 692 ssize_t size;
697 uint8_t version; 693 uint8_t version;
698 double rectime; 694 double rectime;
699 len_and_sockaddr *to; 695 len_and_sockaddr *to;
700 struct sockaddr *from; 696 struct sockaddr *from;
701 ntp_msg_t query, reply; 697 ntp_msg_t msg;
698 uint8_t query_status;
699 uint8_t query_ppoll;
700 l_fixedpt_t query_xmttime;
702 701
703 to = get_sock_lsa(G.listen_fd); 702 to = get_sock_lsa(G.listen_fd);
704 from = xzalloc(to->len); 703 from = xzalloc(to->len);
705 704
706 size = recv_from_to(fd, &query, sizeof(query), 0, from, &to->u.sa, to->len); 705//TODO: use MGS_DONTWAIT flag?
707 if (size == -1) 706 size = recv_from_to(fd, &msg, sizeof(msg), 0, from, &to->u.sa, to->len);
708 bb_error_msg_and_die("recv_from_to");
709 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 707 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
710 char *addr = xmalloc_sockaddr2dotted_noport(from); 708 char *addr;
709 if (size < 0)
710 bb_error_msg_and_die("recv_from_to");
711 addr = xmalloc_sockaddr2dotted_noport(from);
711 bb_error_msg("malformed packet received from %s", addr); 712 bb_error_msg("malformed packet received from %s", addr);
712 free(addr); 713 free(addr);
713 goto bail; 714 goto bail;
714 } 715 }
715 716
716 rectime = gettime(); 717 query_status = msg.status;
717 version = (query.status & VERSION_MASK) >> 3; 718 query_ppoll = msg.ppoll;
719 query_xmttime = msg.xmttime;
718 720
719 memset(&reply, 0, sizeof(reply)); 721 /* Build a reply packet */
720 reply.status = G.status.synced ? G.status.leap : LI_ALARM; 722 memset(&msg, 0, sizeof(msg));
721 reply.status |= (query.status & VERSION_MASK); 723 msg.status = G.status.synced ? G.status.leap : LI_ALARM;
722 reply.status |= ((query.status & MODE_MASK) == MODE_CLIENT) ? 724 msg.status |= (query_status & VERSION_MASK);
725 msg.status |= ((query_status & MODE_MASK) == MODE_CLIENT) ?
723 MODE_SERVER : MODE_SYM_PAS; 726 MODE_SERVER : MODE_SYM_PAS;
724 reply.stratum = G.status.stratum; 727 msg.stratum = G.status.stratum;
725 reply.ppoll = query.ppoll; 728 msg.ppoll = query_ppoll;
726 reply.precision = G.status.precision; 729 msg.precision = G.status.precision;
727 reply.rectime = d_to_lfp(rectime); 730 rectime = gettime();
728 reply.reftime = d_to_lfp(G.status.reftime); 731 msg.xmttime = msg.rectime = d_to_lfp(rectime);
729 reply.xmttime = d_to_lfp(gettime()); 732 msg.reftime = d_to_lfp(G.status.reftime);
730 reply.orgtime = query.xmttime; 733 //msg.xmttime = d_to_lfp(gettime()); // = msg.rectime
731 reply.rootdelay = d_to_sfp(G.status.rootdelay); 734 msg.orgtime = query_xmttime;
732 reply.refid = (version > 3) ? G.status.refid4 : G.status.refid; 735 msg.rootdelay = d_to_sfp(G.status.rootdelay);
736 version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */
737 msg.refid = (version > (3 << VERSION_SHIFT)) ? G.status.refid4 : G.status.refid;
733 738
734 /* We reply from the address packet was sent to, 739 /* We reply from the address packet was sent to,
735 * this makes to/from look swapped here: */ 740 * this makes to/from look swapped here: */
736 sendmsg_wrap(fd, /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len, 741 sendmsg_wrap(fd,
737 &reply, size); 742 /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
743 &msg, size);
738 744
739 bail: 745 bail:
740 free(to); 746 free(to);
@@ -835,7 +841,8 @@ static NOINLINE void ntp_init(char **argv)
835 unsigned opts; 841 unsigned opts;
836 llist_t *peers; 842 llist_t *peers;
837 843
838 tzset(); 844 srandom(getpid());
845 /* tzset(); - why? it's called automatically when needed, no? */
839 846
840 if (getuid()) 847 if (getuid())
841 bb_error_msg_and_die("need root privileges"); 848 bb_error_msg_and_die("need root privileges");
@@ -911,7 +918,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
911 918
912 while (!bb_got_signal) { 919 while (!bb_got_signal) {
913 llist_t *item; 920 llist_t *item;
914 unsigned i, j, idx_peers; 921 unsigned i, j, first_peer_idx;
915 unsigned sent_cnt, trial_cnt; 922 unsigned sent_cnt, trial_cnt;
916 int nfds, timeout; 923 int nfds, timeout;
917 time_t nextaction; 924 time_t nextaction;
@@ -926,7 +933,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
926 i++; 933 i++;
927 } 934 }
928#endif 935#endif
929 idx_peers = i; 936 first_peer_idx = i;
930 sent_cnt = trial_cnt = 0; 937 sent_cnt = trial_cnt = 0;
931 for (item = g.ntp_peers; item != NULL; item = item->link) { 938 for (item = g.ntp_peers; item != NULL; item = item->link) {
932 ntp_peer_t *p = (ntp_peer_t *) item->data; 939 ntp_peer_t *p = (ntp_peer_t *) item->data;
@@ -960,7 +967,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
960 if (p->state == STATE_QUERY_SENT) { 967 if (p->state == STATE_QUERY_SENT) {
961 pfd[i].fd = p->query.fd; 968 pfd[i].fd = p->query.fd;
962 pfd[i].events = POLLIN; 969 pfd[i].events = POLLIN;
963 idx2peer[i - idx_peers] = p; 970 idx2peer[i - first_peer_idx] = p;
964 i++; 971 i++;
965 } 972 }
966 } 973 }
@@ -978,7 +985,8 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
978 985
979 j = 0; 986 j = 0;
980#if ENABLE_FEATURE_NTPD_SERVER 987#if ENABLE_FEATURE_NTPD_SERVER
981 for (; nfds > 0 && j < idx_peers; j++) { 988//TODO: simplify. There is only one server fd!
989 for (; nfds > 0 && j < first_peer_idx; j++) {
982 if (pfd[j].revents & (POLLIN|POLLERR)) { 990 if (pfd[j].revents & (POLLIN|POLLERR)) {
983 nfds--; 991 nfds--;
984 server_dispatch(pfd[j].fd); 992 server_dispatch(pfd[j].fd);
@@ -988,7 +996,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
988 for (; nfds > 0 && j < i; j++) { 996 for (; nfds > 0 && j < i; j++) {
989 if (pfd[j].revents & (POLLIN|POLLERR)) { 997 if (pfd[j].revents & (POLLIN|POLLERR)) {
990 nfds--; 998 nfds--;
991 client_dispatch(idx2peer[j - idx_peers]); 999 client_dispatch(idx2peer[j - first_peer_idx]);
992 } 1000 }
993 } 1001 }
994 } /* while (!bb_got_signal) */ 1002 } /* while (!bb_got_signal) */