On Saturday 21 November 2009 18:26, Adam Tkac wrote:
> Hi all,
> 
> I just finished the NTP client/server applet. Would it be possible to
> merge it to the main repository, please?

I did some changes - see the attached patch. Some
of these simplififications are quite obvious,
please do similar ones next time yourself.

I did a VERY limited testing and found one bug. Fix
(on top of attached):

-       bb_signals(SIGTERM|SIGINT, record_signo);
-       bb_signals(SIGPIPE|SIGHUP, SIG_IGN);
+       bb_signals((1 << SIGTERM) | (1 << SIGINT), record_signo);
+       bb_signals((1 << SIGPIPE) | (1 << SIGHUP), SIG_IGN);

I also changed the options to make them resemble upstream ntpd:

# ./busybox ntpd --help
BusyBox v1.16.0.git (2009-11-22 00:03:34 CET) multi-call binary.

Usage: ntpd [-dngl] [-p PEER]...

NTP client/server

Options:
        -d      Verbose
        -n      Do not daemonize
        -g      Set system time even if offset is > 1000 sec
        -l      Run as server on port 123
        -p PEER Obtain time from PEER (may be repeated)

The applet definitely needs more testing.

Please git pull and do a few run tests. When you research
a problem, add

                if (G.verbose > SOME_NUMBER)
                        bb_error_msg(...debug printout...);

so that in future other users may use -d[dddd] to get
the same info.

--
vda
diff -d -urpN busybox.1/networking/ntpd.c busybox.2/networking/ntpd.c
--- busybox.1/networking/ntpd.c	2009-11-22 02:44:21.000000000 +0100
+++ busybox.2/networking/ntpd.c	2009-11-22 02:45:12.000000000 +0100
@@ -159,14 +159,14 @@ typedef struct {
 	llist_t		*ntp_peers;
 	ntp_status_t	status;
 	uint8_t		settime;
-	uint8_t		foreground;
 	uint32_t	scale;
 	uint8_t		firstadj;
 	smallint	peer_cnt;
 } ntpd_conf_t;
 
-static ntpd_conf_t *G;
-volatile sig_atomic_t	 quit = 0;
+static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
+
+#define G (*ptr_to_globals)
 
 static void
 set_next(ntp_peer_t *p, time_t t)
@@ -178,50 +178,21 @@ set_next(ntp_peer_t *p, time_t t)
 static void
 add_peers(const char *s)
 {
-	struct addrinfo		 hints, *res0, *res;
-	int			 error;
-	ntp_peer_t		*p;
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_family = PF_UNSPEC;
-	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
-	error = getaddrinfo(s, NULL, &hints, &res0);
-	if (error)
-		bb_error_msg_and_die("DNS resolution failed for "
-				     "peer %s", optarg);
-
-	for (res = res0; res != NULL; res = res->ai_next) {
-		if (res->ai_family != AF_INET
-#if ENABLE_FEATURE_IPV6
-		    && res->ai_family != AF_INET6
-#endif
-		   )
-			continue;
-
-		p = xzalloc(sizeof(*p));
-		p->lsa = xzalloc(sizeof(*p->lsa));
-		p->lsa->len =
-#if ENABLE_FEATURE_IPV6
-			res->ai_family == AF_INET6 ?
-				sizeof(struct sockaddr_in6) :
-#endif
-				sizeof(struct sockaddr_in);
-
-		memcpy(&p->lsa->u.sa, res->ai_addr, p->lsa->len);
-		p->lsa->u.sa.sa_family = res->ai_family;
-		set_nport(p->lsa, htons(123));
+	ntp_peer_t *p;
 
-		p->query.fd = -1;
-		p->query.msg.status = MODE_CLIENT | (NTP_VERSION << 3);
+	p = xzalloc(sizeof(*p));
+//TODO: big ntpd uses all IPs, not just 1st, do we need to mimic that?
+	p->lsa = xhost2sockaddr(s, 123);
+	p->query.fd = -1;
+	p->query.msg.status = MODE_CLIENT | (NTP_VERSION << 3);
+	if (STATE_NONE != 0)
 		p->state = STATE_NONE;
-		p->trustlevel = TRUSTLEVEL_PATHETIC;
-		p->query.fd = -1;
-		set_next(p, 0);
+	p->trustlevel = TRUSTLEVEL_PATHETIC;
+	p->query.fd = -1;
+	set_next(p, 0);
 
-		llist_add_to(&G->ntp_peers, p);
-		G->peer_cnt++;
-	}
-	freeaddrinfo(res0);
+	llist_add_to(&G->ntp_peers, p);
+	G->peer_cnt++;
 }
 
 static double
@@ -229,9 +200,7 @@ gettime(void)
 {
 	struct timeval	tv;
 
-	if (gettimeofday(&tv, NULL) == -1)
-		bb_error_msg_and_die("gettimeofday");
-
+	gettimeofday(&tv, NULL); /* never fails */
 	return (tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec);
 }
 
@@ -314,38 +283,34 @@ error_interval(void)
 }
 
 static int
-sendmsg_wrap(int fd, const len_and_sockaddr *from, const len_and_sockaddr *to,
-	     ntp_msg_t *msg, ssize_t len)
+sendmsg_wrap(int fd,
+		const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen,
+		ntp_msg_t *msg, ssize_t len)
 {
 	ssize_t ret;
 
-	if (from == NULL) {
-		ret = sendto(fd, msg, len, 0, &to->u.sa, to->len);
+	errno = 0;
+	if (!from) {
+		ret = sendto(fd, msg, len, 0, to, addrlen);
 	} else {
-		ret = send_to_from(fd, msg, len, 0, &to->u.sa, &from->u.sa,
-				   to->len);
+		ret = send_to_from(fd, msg, len, 0, to, from, addrlen);
 	}
-
 	if (ret != len) {
-		bb_error_msg("ntp_sendmsg failed");
+		bb_perror_msg("send failed");
 		return -1;
 	}
-
 	return 0;
 }
 
 static int
 client_query(ntp_peer_t *p)
 {
-	int	tos = IPTOS_LOWDELAY;
-
 	if (p->query.fd == -1) {
 		p->query.fd = xsocket(p->lsa->u.sa.sa_family, SOCK_DGRAM, 0);
 #if ENABLE_FEATURE_IPV6
 		if (p->lsa->u.sa.sa_family == AF_INET)
 #endif
-			setsockopt(p->query.fd, IPPROTO_IP, IP_TOS, &tos,
-				   sizeof(tos));
+			setsockopt(p->query.fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
 	}
 
 	/*
@@ -366,7 +331,7 @@ client_query(ntp_peer_t *p)
 	p->query.msg.xmttime.fractionl = random();
 	p->query.xmttime = gettime();
 
-	if (sendmsg_wrap(p->query.fd, NULL, p->lsa,
+	if (sendmsg_wrap(p->query.fd, /*from:*/ NULL, /*to:*/ &p->lsa->u.sa, /*addrlen:*/ p->lsa->len,
 			&p->query.msg, NTP_MSGSIZE_NOAUTH) == -1) {
 		set_next(p, INTERVAL_QUERY_PATHETIC);
 		return -1;
@@ -389,37 +354,35 @@ offset_compare(const void *aa, const voi
 
 	if ((*a)->update.offset < (*b)->update.offset)
 		return -1;
-	if ((*a)->update.offset > (*b)->update.offset)
-		return 1;
-	return 0;
+	return ((*a)->update.offset > (*b)->update.offset);
 }
 
-static void
-update_scale(double offset)
+static uint32_t
+updated_scale(double offset)
 {
 	if (offset < 0)
 		offset = -offset;
 
 	if (offset > QSCALE_OFF_MAX)
-		G->scale = 1;
-	else if (offset < QSCALE_OFF_MIN)
-		G->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN;
-	else
-		G->scale = QSCALE_OFF_MAX / offset;
+		return 1;
+	if (offset < QSCALE_OFF_MIN)
+		return QSCALE_OFF_MAX / QSCALE_OFF_MIN;
+	return QSCALE_OFF_MAX / offset;
 }
 
 static void
 adjtime_wrap(void)
 {
 	ntp_peer_t	 *p;
-	int		  offset_cnt = 0, i = 0;
+	unsigned	  offset_cnt;
+	int		  i = 0;
 	ntp_peer_t	**peers;
 	double		  offset_median;
 	llist_t		 *item;
 	len_and_sockaddr *lsa;
 	struct timeval	  tv, olddelta;
 
-
+	offset_cnt = 0;
 	for (item = G->ntp_peers; item != NULL; item = item->link) {
 		p = (ntp_peer_t *) item->data;
 		if (p->trustlevel < TRUSTLEVEL_BADPEER)
@@ -439,8 +402,9 @@ adjtime_wrap(void)
 
 	qsort(peers, offset_cnt, sizeof(ntp_peer_t *), offset_compare);
 
-	if (offset_cnt > 0) {
-		if (offset_cnt > 1 && offset_cnt % 2 == 0) {
+	if (offset_cnt != 0) {
+		if ((offset_cnt & 1) == 0) {
+//TODO: try offset_cnt /= 2...
 			offset_median =
 			    (peers[offset_cnt / 2 - 1]->update.offset +
 			    peers[offset_cnt / 2]->update.offset) / 2;
@@ -452,10 +416,8 @@ adjtime_wrap(void)
 			    peers[offset_cnt / 2]->update.status.stratum);
 		} else {
 			offset_median = peers[offset_cnt / 2]->update.offset;
-			G->status.rootdelay =
-			    peers[offset_cnt / 2]->update.delay;
-			G->status.stratum =
-			    peers[offset_cnt / 2]->update.status.stratum;
+			G->status.rootdelay = peers[offset_cnt / 2]->update.delay;
+			G->status.stratum = peers[offset_cnt / 2]->update.status.stratum;
 		}
 		G->status.leap = peers[offset_cnt / 2]->update.status.leap;
 
@@ -479,15 +441,14 @@ adjtime_wrap(void)
 		G->firstadj = 0;
 		G->status.reftime = gettime();
 		G->status.stratum++;	/* one more than selected peer */
-		update_scale(offset_median);
+		G->scale = updated_scale(offset_median);
 
-		G->status.refid4 =
-		    peers[offset_cnt / 2]->update.status.refid4;
+		G->status.refid4 = peers[offset_cnt / 2]->update.status.refid4;
 
 		lsa = peers[offset_cnt / 2]->lsa;
 		G->status.refid =
 #if ENABLE_FEATURE_IPV6
-			lsa->u.sa.sa_family == AF_INET6 ?
+			lsa->u.sa.sa_family != AF_INET ?
 				G->status.refid4 :
 #endif
 				lsa->u.sin.sin_addr.s_addr;
@@ -519,10 +480,7 @@ settime(double offset)
 	if (offset < SETTIME_MIN_OFFSET && offset > -SETTIME_MIN_OFFSET)
 		return;
 
-	if (gettimeofday(&curtime, NULL) == -1) {
-		bb_error_msg("gettimeofday");
-		return;
-	}
+	gettimeofday(&curtime, NULL); /* never fails */
 
 	d_to_tv(offset, &tv);
 	curtime.tv_usec += tv.tv_usec + 1000000;
@@ -611,16 +569,18 @@ client_dispatch(ntp_peer_t *p)
 
 	addr = xmalloc_sockaddr2dotted_noport(&p->lsa->u.sa);
 
-	if ((size = recvfrom(p->query.fd, &msg, sizeof(msg), 0,
-	    NULL, NULL)) == -1) {
-		if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
-		    errno == ENETUNREACH || errno == ENETDOWN ||
-		    errno == ECONNREFUSED || errno == EADDRNOTAVAIL) {
-			bb_error_msg("recvfrom failed %s", addr);
+	size = recvfrom(p->query.fd, &msg, sizeof(msg), 0, NULL, NULL);
+	if (size == -1) {
+		bb_perror_msg("recvfrom(%s) error", addr);
+		if (errno == EHOSTUNREACH || errno == EHOSTDOWN
+		 || errno == ENETUNREACH || errno == ENETDOWN
+		 || errno == ECONNREFUSED || errno == EADDRNOTAVAIL
+		) {
+//TODO: always do this?
 			set_next(p, error_interval());
-			return;
-		} else
-			bb_error_msg_and_die("recvfrom");
+			goto bail;
+		}
+		xfunc_die();
 	}
 
 	T4 = gettime();
@@ -726,36 +686,27 @@ client_dispatch(ntp_peer_t *p)
 static void
 server_dispatch(int fd)
 {
-	ssize_t			 size;
-	uint8_t			 version;
-	double			 rectime;
-	len_and_sockaddr	*from, *to;
-	ntp_msg_t		 query, reply;
-	char			 *addr;
+	ssize_t			size;
+	uint8_t			version;
+	double			rectime;
+	len_and_sockaddr	*to;
+	struct sockaddr		*from;
+	ntp_msg_t		query, reply;
 
 	to = get_sock_lsa(G->listen_fd);
-	from = xzalloc(LSA_LEN_SIZE + to->len);
+	from = xzalloc(to->len);
 
-	if ((size = recv_from_to(fd, &query, sizeof(query), 0,
-	    &from->u.sa, &to->u.sa, to->len)) == -1)
+	size = recv_from_to(fd, &query, sizeof(query), 0, from, &to->u.sa, to->len);
+	if (size == -1)
 		bb_error_msg_and_die("recv_from_to");
-
-	rectime = gettime();
-
-	from->len =
-#if ENABLE_FEATURE_IPV6
-		(from->u.sa.sa_family == AF_INET6) ?
-			sizeof(struct sockaddr_in6) :
-#endif
-			sizeof(struct sockaddr_in);
-
-	addr = xmalloc_sockaddr2dotted_noport(&from->u.sa);
-
 	if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) {
+		char *addr = xmalloc_sockaddr2dotted_noport(from);
 		bb_error_msg("malformed packet received from %s", addr);
+		free(addr);
 		goto bail;
 	}
 
+	rectime = gettime();
 	version = (query.status & VERSION_MASK) >> 3;
 
 	memset(&reply, 0, sizeof(reply));
@@ -773,67 +724,63 @@ server_dispatch(int fd)
 	reply.rootdelay = d_to_sfp(G->status.rootdelay);
 	reply.refid = (version > 3) ? G->status.refid4 : G->status.refid;
 
-	sendmsg_wrap(fd, to, from, &reply, size);
+	/* We reply from the address packet was sent to,
+	 * this makes to/from look swapped here: */
+	sendmsg_wrap(fd, /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len,
+			&reply, size);
 
  bail:
 	free(to);
 	free(from);
-	free(addr);
 }
 #endif
 
-static void
-sighdlr(int sig)
-{
-	switch (sig) {
-	case SIGINT:
-	case SIGTERM:
-		quit = 1;
-		break;
-	}
-}
-
+static void ntp_main(void) NORETURN;
 static void
 ntp_main(void)
 {
-	int			 a, b, nfds, i, j, idx_peers, timeout;
-	uint			 new_cnt, sent_cnt, trial_cnt;
-	struct pollfd		*pfd = NULL;
-	ntp_peer_t		*p, **idx2peer = NULL;
-	time_t			 nextaction;
-	llist_t			*item;
+	unsigned		 new_cnt;
+	struct pollfd		*pfd;
+	ntp_peer_t		**idx2peer;
 
-	bb_signals(SIGTERM|SIGINT, sighdlr);
+	bb_signals(SIGTERM|SIGINT, record_signo);
 	bb_signals(SIGPIPE|SIGHUP, SIG_IGN);
 
+	{
+		int prec = 0;
+		int b;
 #if 0
-	struct timespec		 tp;
-
-	We can use sys_clock_getres but assuming 10ms tick should be fine.
-	clock_getres(CLOCK_REALTIME, &tp);
-	tp.tv_sec = 0;
-	tp.tv_nsec = 10000000;
-
-	b = 1000000000 / tp.tv_nsec;	/* convert to Hz */
+		struct timespec	tp;
+		/* We can use sys_clock_getres but assuming 10ms tick should be fine */
+		clock_getres(CLOCK_REALTIME, &tp);
+		tp.tv_sec = 0;
+		tp.tv_nsec = 10000000;
+		b = 1000000000 / tp.tv_nsec;	/* convert to Hz */
 #else
-	b = 100; /* b = 1000000000/10000000 = 100 */
+		b = 100; /* b = 1000000000/10000000 = 100 */
 #endif
-	for (a = 0; b > 1; a--, b >>= 1)
-		;
-	G->status.precision = a;
+		while (b > 1)
+			prec--, b >>= 1;
+		G->status.precision = prec;
+	}
 	G->scale = 1;
 
 	idx2peer = xzalloc(sizeof(void *) * G->peer_cnt);
 	new_cnt = G->peer_cnt;
-
 #if ENABLE_FEATURE_NTPD_SERVER
 	if (G->listen_fd != -1)
 		new_cnt++;
 #endif
 
-	pfd = xzalloc(sizeof(struct pollfd) * new_cnt);
+	pfd = xzalloc(sizeof(pfd[0]) * new_cnt);
+
+	while (!bb_got_signal) {
+		llist_t *item;
+		unsigned i, j, idx_peers;
+		unsigned sent_cnt, trial_cnt;
+		int nfds, timeout;
+		time_t nextaction;
 
-	while (quit == 0) {
 		nextaction = time(NULL) + 3600;
 
 		i = 0;
@@ -847,7 +794,7 @@ ntp_main(void)
 		idx_peers = i;
 		sent_cnt = trial_cnt = 0;
 		for (item = G->ntp_peers; item != NULL; item = item->link) {
-			p = (ntp_peer_t *) item->data;
+			ntp_peer_t *p = (ntp_peer_t *) item->data;
 
 			if (p->next > 0 && p->next <= time(NULL)) {
 				trial_cnt++;
@@ -900,8 +847,9 @@ ntp_main(void)
 		} while (nfds == -1 && errno == ENOMEM);
 #endif
 
+		j = 0;
 #if ENABLE_FEATURE_NTPD_SERVER
-		for (j = 0; nfds > 0 && j < idx_peers; j++) {
+		for (; nfds > 0 && j < idx_peers; j++) {
 			if (pfd[j].revents & (POLLIN|POLLERR)) {
 				nfds--;
 				server_dispatch(pfd[j].fd);
@@ -914,9 +862,9 @@ ntp_main(void)
 				client_dispatch(idx2peer[j - idx_peers]);
 			}
 		}
-	}
+	} /* while (!bb_got_signal) */
 
-	_exit(0);
+	kill_myself_with_sig(bb_got_signal);
 }
 
 /* Upstream ntpd's options:
@@ -1004,21 +952,16 @@ ntp_main(void)
  *      Note: The kernel time discipline is disabled with this option.
 */
 
-int ntpd_main(int argc UNUSED_PARAM, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
-int ntpd_main(int argc UNUSED_PARAM, char *argv[])
+int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ntpd_main(int argc UNUSED_PARAM, char **argv)
 {
 	ntpd_conf_t	conf;
-#if ENABLE_FEATURE_NTPD_SERVER
-	int		tos = IPTOS_LOWDELAY;
-#endif
 	smallint	opts;
 	llist_t		*peers = NULL;
 
-	G = &conf;
-
 	memset(&conf, 0, sizeof(conf));
+	SET_PTR_TO_GLOBALS(&conf);
 
-	logmode = LOGMODE_STDIO;
 	tzset();
 
 #if ENABLE_FEATURE_NTPD_SERVER
@@ -1028,15 +971,11 @@ int ntpd_main(int argc UNUSED_PARAM, cha
 
 	opt_complementary = "p::";
 	opts = getopt32(argv, "f" IF_FEATURE_NTPD_SERVER("l") "p:s", &peers);
-
-	if (opts & OPT_f)
-		conf.foreground = 1;
 #if ENABLE_FEATURE_NTPD_SERVER
 	if (opts & OPT_l) {
 		conf.listen_fd = create_and_bind_dgram_or_die("0.0.0.0", 123);
 		socket_want_pktinfo(conf.listen_fd);
-		setsockopt(conf.listen_fd, IPPROTO_IP, IP_TOS, &tos,
-			   sizeof(tos));
+		setsockopt(conf.listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY));
 	}
 #endif
 	while (peers)
@@ -1045,16 +984,13 @@ int ntpd_main(int argc UNUSED_PARAM, cha
 		conf.settime = 1;
 
 	if (getuid()) {
-		fprintf(stderr, "ntpd: need root privileges\n");
-		exit(1);
+		bb_error_msg_and_die("need root privileges");
 	}
 
-	if (!conf.foreground) {
+	if (!(opts & OPT_f)) {
 		logmode = LOGMODE_NONE;
 		bb_daemonize(DAEMON_DEVNULL_STDIO);
 	}
 
 	ntp_main();
-
-	return 0;
 }
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to