aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2017-01-06 16:18:45 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-06 16:21:09 +0100
commitb62ea34afed7d3bf60a6c8ef5a030fea52f55b10 (patch)
treec35f49e40a487b16dc82cb00fd2f4c85d37ab74e
parente6add210b220bd8fe56ca711279b44e111bdd8f0 (diff)
downloadbusybox-w32-b62ea34afed7d3bf60a6c8ef5a030fea52f55b10.tar.gz
busybox-w32-b62ea34afed7d3bf60a6c8ef5a030fea52f55b10.tar.bz2
busybox-w32-b62ea34afed7d3bf60a6c8ef5a030fea52f55b10.zip
ntpd: improve postponed hostname resolution
Run the namelookup from the main loop so a misspelled first ntp server name does not block everything forever. This fixes the following situation which would block forever: $ sudo ./busybox ntpd -dn -p foobar -p pool.ntp.org ntpd: bad address 'foobar' ntpd: bad address 'foobar' ntpd: bad address 'foobar' ... New behavior: ntpd: bad address 'foobar' ntpd: sending query to 137.190.2.4 ntpd: reply from 137.190.2.4: offset:-1.009775 delay:0.175550 status:0x24 strat:1 refid:0x00535047 rootdelay:0.000000 reach:0x01 ntpd: sending query to 137.190.2.4 ntpd: reply from 137.190.2.4: offset:-1.009605 delay:0.175461 status:0x24 strat:1 refid:0x00535047 rootdelay:0.000000 reach:0x03 ntpd: sending query to 137.190.2.4 ntpd: reply from 137.190.2.4: offset:-1.005327 delay:0.167027 status:0x24 strat:1 refid:0x00535047 rootdelay:0.000000 reach:0x07 ntpd: sending query to 137.190.2.4 ntpd: bad address 'foobar' ntpd: reply from 137.190.2.4: offset:-1.046349 delay:0.248705 status:0x24 strat:1 refid:0x00535047 rootdelay:0.000000 reach:0x0f This patch is based on Kaarle Ritvanens work. http://lists.busybox.net/pipermail/busybox/2016-May/084197.html function old new delta ntpd_main 1061 1079 +18 ntp_init 556 560 +4 resolve_peer_hostname 81 75 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 22/-6) Total: 16 bytes Signed-off-by: Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> Signed-off-by: Natanael Copa <ncopa@alpinelinux.org> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c73
1 files changed, 34 insertions, 39 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index b7fa5dce9..bfd5705fc 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -155,6 +155,7 @@
155#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ 155#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */
156#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ 156#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */
157#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ 157#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */
158#define HOSTNAME_INTERVAL 5 /* hostname lookup failed. Wait N secs for next try */
158 159
159/* Step threshold (sec). std ntpd uses 0.128. 160/* Step threshold (sec). std ntpd uses 0.128.
160 */ 161 */
@@ -790,28 +791,20 @@ reset_peer_stats(peer_t *p, double offset)
790 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time); 791 VERB6 bb_error_msg("%s->lastpkt_recv_time=%f", p->p_dotted, p->lastpkt_recv_time);
791} 792}
792 793
793static void 794static len_and_sockaddr*
794resolve_peer_hostname(peer_t *p, int loop_on_fail) 795resolve_peer_hostname(peer_t *p)
795{ 796{
796 len_and_sockaddr *lsa; 797 len_and_sockaddr *lsa = host2sockaddr(p->p_hostname, 123);
797 798 if (lsa) {
798 again: 799 free(p->p_lsa);
799 lsa = host2sockaddr(p->p_hostname, 123); 800 free(p->p_dotted);
800 if (!lsa) { 801 p->p_lsa = lsa;
801 /* error message already emitted by host2sockaddr() */ 802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
802 if (!loop_on_fail) 803 } else {
803 return; 804 /* error message is emitted by host2sockaddr() */
804//FIXME: do this to avoid infinite looping on typo in a hostname? 805 set_next(p, HOSTNAME_INTERVAL);
805//well... in which case, what is a good value for loop_on_fail?
806 //if (--loop_on_fail == 0)
807 // xfunc_die();
808 sleep(5);
809 goto again;
810 } 806 }
811 free(p->p_lsa); 807 return lsa;
812 free(p->p_dotted);
813 p->p_lsa = lsa;
814 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
815} 808}
816 809
817static void 810static void
@@ -822,28 +815,28 @@ add_peers(const char *s)
822 815
823 p = xzalloc(sizeof(*p) + strlen(s)); 816 p = xzalloc(sizeof(*p) + strlen(s));
824 strcpy(p->p_hostname, s); 817 strcpy(p->p_hostname, s);
825 resolve_peer_hostname(p, /*loop_on_fail=*/ 1); 818 p->p_fd = -1;
819 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
820 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
821 reset_peer_stats(p, STEP_THRESHOLD);
826 822
827 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved 823 /* Names like N.<country2chars>.pool.ntp.org are randomly resolved
828 * to a pool of machines. Sometimes different N's resolve to the same IP. 824 * to a pool of machines. Sometimes different N's resolve to the same IP.
829 * It is not useful to have two peers with same IP. We skip duplicates. 825 * It is not useful to have two peers with same IP. We skip duplicates.
830 */ 826 */
831 for (item = G.ntp_peers; item != NULL; item = item->link) { 827 if (resolve_peer_hostname(p)) {
832 peer_t *pp = (peer_t *) item->data; 828 for (item = G.ntp_peers; item != NULL; item = item->link) {
833 if (strcmp(p->p_dotted, pp->p_dotted) == 0) { 829 peer_t *pp = (peer_t *) item->data;
834 bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted); 830 if (pp->p_dotted && strcmp(p->p_dotted, pp->p_dotted) == 0) {
835 free(p->p_lsa); 831 bb_error_msg("duplicate peer %s (%s)", s, p->p_dotted);
836 free(p->p_dotted); 832 free(p->p_lsa);
837 free(p); 833 free(p->p_dotted);
838 return; 834 free(p);
835 return;
836 }
839 } 837 }
840 } 838 }
841 839
842 p->p_fd = -1;
843 p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3);
844 p->next_action_time = G.cur_time; /* = set_next(p, 0); */
845 reset_peer_stats(p, STEP_THRESHOLD);
846
847 llist_add_to(&G.ntp_peers, p); 840 llist_add_to(&G.ntp_peers, p);
848 G.peer_cnt++; 841 G.peer_cnt++;
849} 842}
@@ -871,6 +864,11 @@ do_sendto(int fd,
871static void 864static void
872send_query_to_peer(peer_t *p) 865send_query_to_peer(peer_t *p)
873{ 866{
867 if (!p->p_lsa) {
868 if (!resolve_peer_hostname(p))
869 return;
870 }
871
874 /* Why do we need to bind()? 872 /* Why do we need to bind()?
875 * See what happens when we don't bind: 873 * See what happens when we don't bind:
876 * 874 *
@@ -2238,7 +2236,7 @@ static NOINLINE void ntp_init(char **argv)
2238 IF_FEATURE_NTPD_SERVER("I:") /* compat */ 2236 IF_FEATURE_NTPD_SERVER("I:") /* compat */
2239 "d" /* compat */ 2237 "d" /* compat */
2240 "46aAbgL", /* compat, ignored */ 2238 "46aAbgL", /* compat, ignored */
2241 &peers,&G.script_name, 2239 &peers, &G.script_name,
2242#if ENABLE_FEATURE_NTPD_SERVER 2240#if ENABLE_FEATURE_NTPD_SERVER
2243 &G.if_name, 2241 &G.if_name,
2244#endif 2242#endif
@@ -2263,9 +2261,6 @@ static NOINLINE void ntp_init(char **argv)
2263 if (opts & OPT_N) 2261 if (opts & OPT_N)
2264 setpriority(PRIO_PROCESS, 0, -15); 2262 setpriority(PRIO_PROCESS, 0, -15);
2265 2263
2266 /* add_peers() calls can retry DNS resolution (possibly forever).
2267 * Daemonize before them, or else boot can stall forever.
2268 */
2269 if (!(opts & OPT_n)) { 2264 if (!(opts & OPT_n)) {
2270 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); 2265 bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv);
2271 logmode = LOGMODE_NONE; 2266 logmode = LOGMODE_NONE;
@@ -2400,7 +2395,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
2400 2395
2401 /* What if don't see it because it changed its IP? */ 2396 /* What if don't see it because it changed its IP? */
2402 if (p->reachable_bits == 0) 2397 if (p->reachable_bits == 0)
2403 resolve_peer_hostname(p, /*loop_on_fail=*/ 0); 2398 resolve_peer_hostname(p);
2404 2399
2405 set_next(p, timeout); 2400 set_next(p, timeout);
2406 } 2401 }