aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-24 16:03:47 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-24 16:03:47 +0100
commitb1278a38bcb108fad3230ecce94a53b64571f9de (patch)
tree27ccecf5dd5a76cff75e809d5518fb1589479d85
parent9cc60d7e6b21e659a07042e46b9cd88f498fc8c0 (diff)
downloadbusybox-w32-b1278a38bcb108fad3230ecce94a53b64571f9de.tar.gz
busybox-w32-b1278a38bcb108fad3230ecce94a53b64571f9de.tar.bz2
busybox-w32-b1278a38bcb108fad3230ecce94a53b64571f9de.zip
ntpd: locally bind every peer socket. +22 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/xconnect.c2
-rw-r--r--networking/ntpd.c87
3 files changed, 64 insertions, 28 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 77c9e2888..1194f7eca 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -490,7 +490,8 @@ enum {
490/* Create stream socket, and allocate suitable lsa. 490/* Create stream socket, and allocate suitable lsa.
491 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) 491 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6))
492 * af == AF_UNSPEC will result in trying to create IPv6 socket, 492 * af == AF_UNSPEC will result in trying to create IPv6 socket,
493 * and if kernel doesn't support it, IPv4. 493 * and if kernel doesn't support it, fall back to IPv4.
494 * This is useful if you plan to bind to resulting local lsa.
494 */ 495 */
495#if ENABLE_FEATURE_IPV6 496#if ENABLE_FEATURE_IPV6
496int xsocket_type(len_and_sockaddr **lsap, int af, int sock_type) FAST_FUNC; 497int xsocket_type(len_and_sockaddr **lsap, int af, int sock_type) FAST_FUNC;
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index b6848ea6f..8a1e1c1b2 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -346,7 +346,7 @@ int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, IF_FEATURE_IPV6(int family,)
346 len = sizeof(struct sockaddr_in6); 346 len = sizeof(struct sockaddr_in6);
347 } 347 }
348#endif 348#endif
349 lsa = xzalloc(offsetof(len_and_sockaddr, u.sa) + len); 349 lsa = xzalloc(LSA_LEN_SIZE + len);
350 lsa->len = len; 350 lsa->len = len;
351 lsa->u.sa.sa_family = family; 351 lsa->u.sa.sa_family = family;
352 *lsap = lsa; 352 *lsap = lsa;
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 086b3ea74..12e498d48 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -12,22 +12,22 @@
12# error "Sorry, your kernel has to support IP_PKTINFO" 12# error "Sorry, your kernel has to support IP_PKTINFO"
13#endif 13#endif
14 14
15#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every n secs */ 15#define INTERVAL_QUERY_NORMAL 30 /* sync to peers every n secs */
16#define INTERVAL_QUERY_PATHETIC 60 16#define INTERVAL_QUERY_PATHETIC 60
17#define INTERVAL_QUERY_AGRESSIVE 5 17#define INTERVAL_QUERY_AGRESSIVE 5
18 18
19#define TRUSTLEVEL_BADPEER 6 /* bad if *less than* TRUSTLEVEL_BADPEER */ 19#define TRUSTLEVEL_BADPEER 6 /* bad if *less than* TRUSTLEVEL_BADPEER */
20#define TRUSTLEVEL_PATHETIC 2 20#define TRUSTLEVEL_PATHETIC 2
21#define TRUSTLEVEL_AGRESSIVE 8 21#define TRUSTLEVEL_AGRESSIVE 8
22#define TRUSTLEVEL_MAX 10 22#define TRUSTLEVEL_MAX 10
23 23
24#define QSCALE_OFF_MIN 0.05 24#define QSCALE_OFF_MIN 0.05
25#define QSCALE_OFF_MAX 0.50 25#define QSCALE_OFF_MAX 0.50
26 26
27#define QUERYTIME_MAX 15 /* single query might take n secs max */ 27#define QUERYTIME_MAX 15 /* single query might take n secs max */
28#define OFFSET_ARRAY_SIZE 8 28#define OFFSET_ARRAY_SIZE 8
29#define SETTIME_MIN_OFFSET 180 /* min offset for settime at start */ 29#define SETTIME_MIN_OFFSET 180 /* min offset for settime at start */
30#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */ 30#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */
31 31
32/* Style borrowed from NTP ref/tcpdump and updated for SNTPv4 (RFC2030). */ 32/* Style borrowed from NTP ref/tcpdump and updated for SNTPv4 (RFC2030). */
33 33
@@ -112,7 +112,7 @@ enum {
112 MODE_RES2 = 7, /* reserved for private use */ 112 MODE_RES2 = 7, /* reserved for private use */
113}; 113};
114 114
115#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ 115#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */
116 116
117enum client_state { 117enum client_state {
118 STATE_NONE, 118 STATE_NONE,
@@ -173,12 +173,12 @@ struct globals {
173#if ENABLE_FEATURE_NTPD_SERVER 173#if ENABLE_FEATURE_NTPD_SERVER
174 int listen_fd; 174 int listen_fd;
175#endif 175#endif
176 unsigned peer_cnt;
176 llist_t *ntp_peers; 177 llist_t *ntp_peers;
177 ntp_status_t status; 178 ntp_status_t status;
178 uint32_t scale; 179 uint32_t scale;
179 uint8_t settime; 180 uint8_t settime;
180 uint8_t firstadj; 181 uint8_t firstadj;
181 smallint peer_cnt;
182}; 182};
183#define G (*ptr_to_globals) 183#define G (*ptr_to_globals)
184 184
@@ -214,11 +214,11 @@ add_peers(const char *s)
214} 214}
215 215
216static double 216static double
217gettime_fp(void) 217gettime1900fp(void)
218{ 218{
219 struct timeval tv; 219 struct timeval tv;
220 gettimeofday(&tv, NULL); /* never fails */ 220 gettimeofday(&tv, NULL); /* never fails */
221 return (tv.tv_sec + 1.0e-6 * tv.tv_usec + JAN_1970); 221 return (tv.tv_sec + 1.0e-6 * tv.tv_usec + OFFSET_1900_1970);
222} 222}
223 223
224static void 224static void
@@ -311,12 +311,43 @@ sendmsg_wrap(int fd,
311static int 311static int
312send_query_to_peer(ntp_peer_t *p) 312send_query_to_peer(ntp_peer_t *p)
313{ 313{
314 // Why do we need to bind()?
315 // See what happens when we don't bind:
316 //
317 // socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
318 // setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0
319 // gettimeofday({1259071266, 327885}, NULL) = 0
320 // sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48
321 // ^^^ we sent it from some source port picked by kernel.
322 // time(NULL) = 1259071266
323 // write(2, "ntpd: entering poll 15 secs\n", 28) = 28
324 // poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}])
325 // recv(3, "yyy", 68, MSG_DONTWAIT) = 48
326 // ^^^ this recv will receive packets to any local port!
327 //
328 // Uncomment this and use strace to see it in action:
329#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); }
330
314 if (p->query.fd == -1) { 331 if (p->query.fd == -1) {
315 p->query.fd = xsocket(p->lsa->u.sa.sa_family, SOCK_DGRAM, 0); 332 int fd, family;
333 len_and_sockaddr *local_lsa;
334
335 family = p->lsa->u.sa.sa_family;
336 //was: p->query.fd = xsocket(family, SOCK_DGRAM, 0);
337 p->query.fd = fd = xsocket_type(&local_lsa, family, SOCK_DGRAM);
338 /* local_lsa has "null" address and port 0 now.
339 * bind() ensures we have a *particular port* selected by kernel
340 * and remembered in p->query.fd, thus later recv(p->query.fd)
341 * receives only packets sent to this port.
342 */
343 PROBE_LOCAL_ADDR
344 xbind(fd, &local_lsa->u.sa, local_lsa->len);
345 PROBE_LOCAL_ADDR
316#if ENABLE_FEATURE_IPV6 346#if ENABLE_FEATURE_IPV6
317 if (p->lsa->u.sa.sa_family == AF_INET) 347 if (family == AF_INET)
318#endif 348#endif
319 setsockopt(p->query.fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); 349 setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
350 free(local_lsa);
320 } 351 }
321 352
322 /* 353 /*
@@ -335,7 +366,7 @@ send_query_to_peer(ntp_peer_t *p)
335 366
336 p->query.msg.xmttime.int_partl = random(); 367 p->query.msg.xmttime.int_partl = random();
337 p->query.msg.xmttime.fractionl = random(); 368 p->query.msg.xmttime.fractionl = random();
338 p->query.xmttime = gettime_fp(); 369 p->query.xmttime = gettime1900fp();
339 370
340 if (sendmsg_wrap(p->query.fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len, 371 if (sendmsg_wrap(p->query.fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len,
341 &p->query.msg, NTP_MSGSIZE_NOAUTH) == -1) { 372 &p->query.msg, NTP_MSGSIZE_NOAUTH) == -1) {
@@ -437,7 +468,7 @@ adjtime_wrap(void)
437 } 468 }
438 469
439 G.firstadj = 0; 470 G.firstadj = 0;
440 G.status.reftime = gettime_fp(); 471 G.status.reftime = gettime1900fp();
441 G.status.stratum++; /* one more than selected peer */ 472 G.status.stratum++; /* one more than selected peer */
442 G.scale = updated_scale(offset_median); 473 G.scale = updated_scale(offset_median);
443 474
@@ -568,6 +599,10 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
568 599
569 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa); 600 addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
570 601
602 /* We can recvfrom here and check from.IP, but some multihomed
603 * ntp servers reply from their *other IP*.
604 * TODO: maybe we should check at least what we can: from.port == 123?
605 */
571 size = recv(p->query.fd, &msg, sizeof(msg), MSG_DONTWAIT); 606 size = recv(p->query.fd, &msg, sizeof(msg), MSG_DONTWAIT);
572 if (size == -1) { 607 if (size == -1) {
573 bb_perror_msg("recv(%s) error", addr); 608 bb_perror_msg("recv(%s) error", addr);
@@ -583,7 +618,7 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
583 xfunc_die(); 618 xfunc_die();
584 } 619 }
585 620
586 T4 = gettime_fp(); 621 T4 = gettime1900fp();
587 622
588 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 623 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
589 bb_error_msg("malformed packet received from %s", addr); 624 bb_error_msg("malformed packet received from %s", addr);
@@ -635,7 +670,7 @@ recv_and_process_peer_pkt(ntp_peer_t *p)
635 goto bail; 670 goto bail;
636 } 671 }
637 offset->error = (T2 - T1) - (T3 - T4); 672 offset->error = (T2 - T1) - (T3 - T4);
638// Can we use (T4 - JAN_1970) instead of time(NULL)? 673// Can we use (T4 - OFFSET_1900_1970) instead of time(NULL)?
639 offset->rcvd = time(NULL); 674 offset->rcvd = time(NULL);
640 offset->good = 1; 675 offset->good = 1;
641 676
@@ -724,10 +759,10 @@ recv_and_process_client_pkt(void /*int fd*/)
724 msg.stratum = G.status.stratum; 759 msg.stratum = G.status.stratum;
725 msg.ppoll = query_ppoll; 760 msg.ppoll = query_ppoll;
726 msg.precision = G.status.precision; 761 msg.precision = G.status.precision;
727 rectime = gettime_fp(); 762 rectime = gettime1900fp();
728 msg.xmttime = msg.rectime = d_to_lfp(rectime); 763 msg.xmttime = msg.rectime = d_to_lfp(rectime);
729 msg.reftime = d_to_lfp(G.status.reftime); 764 msg.reftime = d_to_lfp(G.status.reftime);
730 //msg.xmttime = d_to_lfp(gettime_fp()); // = msg.rectime 765 //msg.xmttime = d_to_lfp(gettime1900fp()); // = msg.rectime
731 msg.orgtime = query_xmttime; 766 msg.orgtime = query_xmttime;
732 msg.rootdelay = d_to_sfp(G.status.rootdelay); 767 msg.rootdelay = d_to_sfp(G.status.rootdelay);
733 version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */ 768 version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */