svn commit: trunk/busybox: include libbb networking util-linux

vda at busybox.net vda at busybox.net
Thu Jan 11 16:50:24 UTC 2007


Author: vda
Date: 2007-01-11 08:50:23 -0800 (Thu, 11 Jan 2007)
New Revision: 17250

Log:
ipv6-ization efforts continue. Few bugs are found,
unknown number likely introduced...


Modified:
   trunk/busybox/include/libbb.h
   trunk/busybox/libbb/xconnect.c
   trunk/busybox/networking/ftpgetput.c
   trunk/busybox/networking/tftp.c
   trunk/busybox/util-linux/rdate.c


Changeset:
Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2007-01-11 10:38:10 UTC (rev 17249)
+++ trunk/busybox/include/libbb.h	2007-01-11 16:50:23 UTC (rev 17250)
@@ -293,9 +293,20 @@
 extern int xconnect_tcp_v4(struct sockaddr_in *s_addr);
 extern struct hostent *xgethostbyname(const char *name);
 extern struct hostent *xgethostbyname2(const char *name, int af);
-
 extern int setsockopt_reuseaddr(int fd);
 extern int setsockopt_broadcast(int fd);
+
+/* "new" (ipv4+ipv6) API */
+typedef struct len_and_sockaddr {
+	int len;
+	union {
+		struct sockaddr sa;
+		struct sockaddr_in sin;
+#if ENABLE_FEATURE_IPV6
+		struct sockaddr_in6 sin6;
+#endif
+	};
+} len_and_sockaddr;
 /* Create server TCP socket bound to bindaddr:port. bindaddr can be NULL,
  * numeric IP ("N.N.N.N") or numeric IPv6 address,
  * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT").
@@ -306,21 +317,19 @@
  * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT").
  * If there is no suffix, port argument is used */
 extern int create_and_connect_stream_or_die(const char *peer, int port);
-typedef struct len_and_sockaddr {
-	int len;
-	union {
-		struct sockaddr sa;
-		struct sockaddr_in sin;
-#if ENABLE_FEATURE_IPV6
-		struct sockaddr_in6 sin6;
-#endif
-	};
-} len_and_sockaddr;
+/* Connect to peer identified by lsa */
+extern int xconnect_stream(const len_and_sockaddr *lsa);
 /* Return malloc'ed len_and_sockaddr with socket address of host:port
  * Currently will return IPv4 or IPv6 sockaddrs only
  * (depending on host), but in theory nothing prevents e.g.
  * UNIX socket address being returned, IPX sockaddr etc... */
 extern len_and_sockaddr* host2sockaddr(const char *host, int port);
+/* assign sin[6]_port member if the socket is of corresponding type,
+ * otherwise noop. Useful for ftp.
+ * NB: does NOT do htons() internally, just direct assignment. */
+extern void set_port(len_and_sockaddr *lsa, unsigned port);
+char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen);
+char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen);
 
 
 extern char *xstrdup(const char *s);

Modified: trunk/busybox/libbb/xconnect.c
===================================================================
--- trunk/busybox/libbb/xconnect.c	2007-01-11 10:38:10 UTC (rev 17249)
+++ trunk/busybox/libbb/xconnect.c	2007-01-11 16:50:23 UTC (rev 17250)
@@ -83,8 +83,20 @@
 /* "New" networking API */
 
 
-//extern int xsocket_stream_ip4or6(sa_family_t *fp);
-//extern len_and_sockaddr* dotted2sockaddr(const char *dotted, int def_port);
+void set_port(len_and_sockaddr *lsa, unsigned port)
+{
+#if ENABLE_FEATURE_IPV6
+	if (lsa->sa.sa_family == AF_INET6) {
+		lsa->sin6.sin6_port = port;
+		return;
+	}
+#endif
+	if (lsa->sa.sa_family == AF_INET) {
+		lsa->sin.sin_port = port;
+		return;
+	}
+	/* What? UNIX socket? IPX?? :) */
+}
 
 /* peer: "1.2.3.4[:port]", "www.google.com[:port]"
  * port: if neither of above specifies port #
@@ -96,7 +108,6 @@
 	struct addrinfo *result = NULL;
 	const char *org_host = host; /* only for error msg */
 	const char *cp;
-	char service[sizeof(int)*3 + 1];
 	struct addrinfo hint;
 
 	/* Ugly parsing of host:addr */
@@ -119,9 +130,7 @@
 		if (ENABLE_FEATURE_IPV6 && *cp != ':')
 			cp++; /* skip ']' */
 		cp++; /* skip ':' */
-	} else {
-		utoa_to_buf(port, service, sizeof(service));
-		cp = service;
+		port = xatou16(cp);
 	}
 
 	memset(&hint, 0 , sizeof(hint));
@@ -132,13 +141,14 @@
 	/* Needed. Or else we will get each address thrice (or more)
 	 * for each possible socket type (tcp,udp,raw...): */
 	hint.ai_socktype = SOCK_STREAM;
-	hint.ai_flags = ai_flags | AI_NUMERICSERV;
-	rc = getaddrinfo(host, cp, &hint, &result);
+	hint.ai_flags = ai_flags;
+	rc = getaddrinfo(host, NULL, &hint, &result);
 	if (rc || !result)
 		bb_error_msg_and_die("bad address '%s'", org_host);
 	r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
 	r->len = result->ai_addrlen;
 	memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
+	set_port(r, port);
 	freeaddrinfo(result);
 	return r;
 }
@@ -153,7 +163,7 @@
 	return str2sockaddr(host, port, NI_NUMERICHOST);
 }
 
-static int xsocket_stream_ip4or6(len_and_sockaddr *lsa)
+static int xsocket_stream(len_and_sockaddr *lsa)
 {
 	int fd;
 #if ENABLE_FEATURE_IPV6
@@ -186,7 +196,7 @@
 			USE_FEATURE_IPV6(sizeof(struct sockaddr_in6))
 			SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in))
 		);
-		fd = xsocket_stream_ip4or6(lsa);
+		fd = xsocket_stream(lsa);
 	}
 	setsockopt_reuseaddr(fd);
 	xbind(fd, &lsa->sa, lsa->len);
@@ -209,3 +219,33 @@
 	free(lsa);
 	return fd;
 }
+
+int xconnect_stream(const len_and_sockaddr *lsa)
+{
+	int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
+	xconnect(fd, &lsa->sa, lsa->len);
+	return fd;
+}
+
+static char* sockaddr2str(const struct sockaddr *sa, socklen_t salen, int flags)
+{
+	char host[128];
+	char serv[16];
+	int rc = getnameinfo(sa, salen,
+			host, sizeof(host),
+			serv, sizeof(serv),
+			flags | NI_NUMERICSERV /* do not resolve port# */
+	);
+	if (rc) return NULL;
+	return xasprintf("%s:%s", host, serv);
+}
+
+char* xmalloc_sockaddr2host(const struct sockaddr *sa, socklen_t salen)
+{
+	return sockaddr2str(sa, salen, 0);
+}
+
+char* xmalloc_sockaddr2dotted(const struct sockaddr *sa, socklen_t salen)
+{
+	return sockaddr2str(sa, salen, NI_NUMERICHOST);
+}

Modified: trunk/busybox/networking/ftpgetput.c
===================================================================
--- trunk/busybox/networking/ftpgetput.c	2007-01-11 10:38:10 UTC (rev 17249)
+++ trunk/busybox/networking/ftpgetput.c	2007-01-11 16:50:23 UTC (rev 17250)
@@ -19,7 +19,7 @@
 typedef struct ftp_host_info_s {
 	char *user;
 	char *password;
-	struct sockaddr_in *s_in;
+	struct len_and_sockaddr *lsa;
 } ftp_host_info_t;
 
 static char verbose_flag;
@@ -88,8 +88,8 @@
 	*buf_ptr = '\0';
 	port_num += xatoul_range(buf_ptr + 1, 0, 255) * 256;
 
-	server->s_in->sin_port = htons(port_num);
-	return xconnect_tcp_v4(server->s_in);
+	set_port(server->lsa, htons(port_num));
+	return xconnect_stream(server->lsa);
 }
 
 static FILE *ftp_login(ftp_host_info_t *server)
@@ -98,9 +98,9 @@
 	char buf[512];
 
 	/* Connect to the command socket */
-	control_stream = fdopen(xconnect_tcp_v4(server->s_in), "r+");
+	control_stream = fdopen(xconnect_stream(server->lsa), "r+");
 	if (control_stream == NULL) {
-		/* Extremely unlikely */
+		/* fdopen failed - extremely unlikely */
 		bb_perror_nomsg_and_die();
 	}
 
@@ -304,7 +304,6 @@
 	const char *port = "ftp";
 	/* socket to ftp server */
 	FILE *control_stream;
-	struct sockaddr_in s_in;
 	/* continue previous transfer (-c) */
 	ftp_host_info_t *server;
 
@@ -347,12 +346,10 @@
 	/* We want to do exactly _one_ DNS lookup, since some
 	 * sites (i.e. ftp.us.debian.org) use round-robin DNS
 	 * and we want to connect to only one IP... */
-	server->s_in = &s_in;
-	bb_lookup_host(&s_in, argv[0]);
-	s_in.sin_port = bb_lookup_port(port, "tcp", 21);
+	server->lsa = host2sockaddr(argv[0], bb_lookup_port(port, "tcp", 21));
 	if (verbose_flag) {
-		printf("Connecting to %s[%s]:%d\n",
-			argv[0], inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port));
+		printf("Connecting to %s [%s]\n", argv[0],
+			xmalloc_sockaddr2dotted(&server->lsa->sa, server->lsa->len));
 	}
 
 	/*  Connect/Setup/Configure the FTP session */

Modified: trunk/busybox/networking/tftp.c
===================================================================
--- trunk/busybox/networking/tftp.c	2007-01-11 10:38:10 UTC (rev 17249)
+++ trunk/busybox/networking/tftp.c	2007-01-11 16:50:23 UTC (rev 17250)
@@ -26,12 +26,6 @@
 #define TFTP_TIMEOUT 5	/* seconds */
 #define TFTP_NUM_RETRIES 5 /* number of retries */
 
-static const char * const MODE_OCTET = "octet";
-#define MODE_OCTET_LEN 6 /* sizeof(MODE_OCTET)*/
-
-static const char * const OPTION_BLOCKSIZE = "blksize";
-#define OPTION_BLOCKSIZE_LEN 8 /* sizeof(OPTION_BLOCKSIZE) */
-
 /* opcodes we support */
 #define TFTP_RRQ   1
 #define TFTP_WRQ   2
@@ -51,13 +45,23 @@
 	"No such user"
 };
 
-#define tftp_cmd_get ENABLE_FEATURE_TFTP_GET
-
-#if ENABLE_FEATURE_TFTP_PUT
-# define tftp_cmd_put (tftp_cmd_get+ENABLE_FEATURE_TFTP_PUT)
+#if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
+#define USE_GETPUT(a)
+#define CMD_GET(cmd) 1
+#define CMD_PUT(cmd) 0
+#elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
+#define USE_GETPUT(a)
+#define CMD_GET(cmd) 0
+#define CMD_PUT(cmd) 1
 #else
-# define tftp_cmd_put 0
+#define USE_GETPUT(a) a
+/* masks coming from getpot32 */
+#define CMD_GET(cmd) (cmd & 1)
+#define CMD_PUT(cmd) (cmd & 2)
 #endif
+/* NB: in the code below
+ * CMD_GET(cmd) and CMD_GET(cmd) are mutually exclusive
+ */
 
 
 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
@@ -70,8 +74,9 @@
 	 * to use blocksizes smaller than 22 octets.
 	 */
 
-	if ((bufsize && (blocksize > bufsize)) ||
-		(blocksize < 8) || (blocksize > 65564)) {
+	if ((bufsize && (blocksize > bufsize))
+	 || (blocksize < 8) || (blocksize > 65564)
+	) {
 		bb_error_msg("bad blocksize");
 		return 0;
 	}
@@ -86,7 +91,6 @@
 	int k;
 
 	while (len > 0) {
-
 		/* Make sure the options are terminated correctly */
 
 		for (k = 0; k < len; k++) {
@@ -122,22 +126,23 @@
 
 #endif
 
-static int tftp(const int cmd, const struct hostent *host,
-		   const char *remotefile, const int localfd,
-		   const unsigned short port, int tftp_bufsize)
+static int tftp(
+#if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
+		const int cmd,
+#endif
+		const len_and_sockaddr *peer_lsa,
+		const char *remotefile, const int localfd,
+		const unsigned port, int tftp_bufsize)
 {
-	struct sockaddr_in sa;
-	struct sockaddr_in from;
 	struct timeval tv;
-	socklen_t fromlen;
 	fd_set rfds;
 	int socketfd;
 	int len;
 	int opcode = 0;
 	int finished = 0;
 	int timeout = TFTP_NUM_RETRIES;
-	unsigned short block_nr = 1;
-	unsigned short tmp;
+	uint16_t block_nr = 1;
+	uint16_t tmp;
 	char *cp;
 
 	USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;)
@@ -149,42 +154,24 @@
 	char *xbuf = xmalloc(tftp_bufsize += 4);
 	char *rbuf = xmalloc(tftp_bufsize);
 
-	if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
-		/* need to unlink the localfile, so don't use xsocket here. */
-		bb_perror_msg("socket");
-		return EXIT_FAILURE;
-	}
+	socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0);
 
-	len = sizeof(sa);
-
-	memset(&sa, 0, len);
-	xbind(socketfd, (struct sockaddr *)&sa, len);
-
-	sa.sin_family = host->h_addrtype;
-	sa.sin_port = port;
-	memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr,
-		   sizeof(sa.sin_addr));
-
 	/* build opcode */
-	if (cmd & tftp_cmd_get) {
+	opcode = TFTP_WRQ;
+	if (CMD_GET(cmd)) {
 		opcode = TFTP_RRQ;
 	}
-	if (cmd & tftp_cmd_put) {
-		opcode = TFTP_WRQ;
-	}
 
 	while (1) {
 
 		cp = xbuf;
 
 		/* first create the opcode part */
-		*((unsigned short *) cp) = htons(opcode);
+		*((uint16_t*)cp) = htons(opcode);
 		cp += 2;
 
 		/* add filename and mode */
-		if (((cmd & tftp_cmd_get) && (opcode == TFTP_RRQ)) ||
-			((cmd & tftp_cmd_put) && (opcode == TFTP_WRQ)))
-		{
+		if (CMD_GET(cmd) ? (opcode == TFTP_RRQ) : (opcode == TFTP_WRQ)) {
 			int too_long = 0;
 
 			/* see if the filename fits into xbuf
@@ -198,14 +185,14 @@
 				cp += len;
 			}
 
-			if (too_long || ((&xbuf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) {
+			if (too_long || (&xbuf[tftp_bufsize - 1] - cp) < sizeof("octet")) {
 				bb_error_msg("remote filename too long");
 				break;
 			}
 
 			/* add "mode" part of the package */
-			memcpy(cp, MODE_OCTET, MODE_OCTET_LEN);
-			cp += MODE_OCTET_LEN;
+			memcpy(cp, "octet", sizeof("octet"));
+			cp += sizeof("octet");
 
 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
 
@@ -219,8 +206,8 @@
 				}
 
 				/* add "blksize" + number of blocks  */
-				memcpy(cp, OPTION_BLOCKSIZE, OPTION_BLOCKSIZE_LEN);
-				cp += OPTION_BLOCKSIZE_LEN;
+				memcpy(cp, "blksize", sizeof("blksize"));
+				cp += sizeof("blksize");
 				cp += snprintf(cp, 6, "%d", len) + 1;
 
 				want_option_ack = 1;
@@ -230,16 +217,12 @@
 
 		/* add ack and data */
 
-		if (((cmd & tftp_cmd_get) && (opcode == TFTP_ACK)) ||
-			((cmd & tftp_cmd_put) && (opcode == TFTP_DATA))) {
-
-			*((unsigned short *) cp) = htons(block_nr);
-
+		if (CMD_GET(cmd) ? (opcode == TFTP_ACK) : (opcode == TFTP_DATA)) {
+			*((uint16_t*)cp) = htons(block_nr);
 			cp += 2;
-
 			block_nr++;
 
-			if ((cmd & tftp_cmd_put) && (opcode == TFTP_DATA)) {
+			if (CMD_PUT(cmd) && (opcode == TFTP_DATA)) {
 				len = full_read(localfd, cp, tftp_bufsize - 4);
 
 				if (len < 0) {
@@ -261,9 +244,7 @@
 
 		timeout = TFTP_NUM_RETRIES;	/* re-initialize */
 		do {
-
 			len = cp - xbuf;
-
 #if ENABLE_DEBUG_TFTP
 			fprintf(stderr, "sending %u bytes\n", len);
 			for (cp = xbuf; cp < &xbuf[len]; cp++)
@@ -271,7 +252,7 @@
 			fprintf(stderr, "\n");
 #endif
 			if (sendto(socketfd, xbuf, len, 0,
-					   (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+					&peer_lsa->sa, peer_lsa->len) < 0) {
 				bb_perror_msg("send");
 				len = -1;
 				break;
@@ -284,9 +265,6 @@
 
 			/* receive packet */
 
-			memset(&from, 0, sizeof(from));
-			fromlen = sizeof(from);
-
 			tv.tv_sec = TFTP_TIMEOUT;
 			tv.tv_usec = 0;
 
@@ -294,30 +272,41 @@
 			FD_SET(socketfd, &rfds);
 
 			switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) {
+				struct sockaddr *from;
+				socklen_t fromlen;
+
 			case 1:
-				len = recvfrom(socketfd, rbuf, tftp_bufsize, 0,
-							   (struct sockaddr *) &from, &fromlen);
+				fromlen = peer_lsa->len;
+				from = alloca(fromlen);
+				memset(from, 0, fromlen);
 
+				len = recvfrom(socketfd, rbuf, tftp_bufsize, 0,
+							from, &fromlen);
 				if (len < 0) {
 					bb_perror_msg("recvfrom");
 					break;
 				}
-
 				timeout = 0;
-
-				if (sa.sin_port == port) {
-					sa.sin_port = from.sin_port;
+				if (from->sa_family == peer_lsa->sa.sa_family) {
+#if ENABLE_FEATURE_IPV6
+					if (from->sa_family == AF_INET6
+					 && ((struct sockaddr_in6*)from)->sin6_port == port
+					)
+						break;
+#endif
+					/* Non-internet sockets are ok */
+					if (from->sa_family != AF_INET)
+						break;
+					if (((struct sockaddr_in*)from)->sin_port == port)
+						break;
 				}
-				if (sa.sin_port == from.sin_port) {
-					break;
-				}
-
-				/* fall-through for bad packets! */
-				/* discard the packet - treat as timeout */
+				/* family doesn't match, or
+				 * it is INET[v6] and port doesn't match -
+				 * fall-through for bad packets!
+				 * (discard the packet - treat as timeout) */
 				timeout = TFTP_NUM_RETRIES;
 			case 0:
 				bb_error_msg("timeout");
-
 				timeout--;
 				if (timeout == 0) {
 					len = -1;
@@ -331,14 +320,14 @@
 
 		} while (timeout && (len >= 0));
 
-		if ((finished) || (len < 0)) {
+		if (finished || (len < 0)) {
 			break;
 		}
 
 		/* process received packet */
 
-		opcode = ntohs(*((unsigned short *) rbuf));
-		tmp = ntohs(*((unsigned short *) &rbuf[2]));
+		opcode = ntohs( ((uint16_t*)rbuf)[0] );
+		tmp = ntohs( ((uint16_t*)rbuf)[1] );
 
 #if ENABLE_DEBUG_TFTP
 		fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp);
@@ -352,7 +341,6 @@
 				rbuf[tftp_bufsize - 1] = '\0';
 			} else if (tmp < (sizeof(tftp_bb_error_msg)
 							  / sizeof(char *))) {
-
 				msg = tftp_bb_error_msg[tmp];
 			}
 
@@ -368,25 +356,22 @@
 			want_option_ack = 0;
 
 			if (opcode == TFTP_OACK) {
-
 				/* server seems to support options */
-
 				char *res;
 
-				res = tftp_option_get(&rbuf[2], len - 2, OPTION_BLOCKSIZE);
+				res = tftp_option_get(&rbuf[2], len - 2, "blksize");
 
 				if (res) {
 					int blksize = xatoi_u(res);
 
 					if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) {
-
-						if (cmd & tftp_cmd_put) {
+						if (CMD_PUT(cmd)) {
 							opcode = TFTP_DATA;
 						} else {
 							opcode = TFTP_ACK;
 						}
 #if ENABLE_DEBUG_TFTP
-						fprintf(stderr, "using %s %u\n", OPTION_BLOCKSIZE,
+						fprintf(stderr, "using blksize %u\n",
 								blksize);
 #endif
 						tftp_bufsize = blksize + 4;
@@ -407,10 +392,8 @@
 		}
 #endif
 
-		if ((cmd & tftp_cmd_get) && (opcode == TFTP_DATA)) {
-
+		if (CMD_GET(cmd) && (opcode == TFTP_DATA)) {
 			if (tmp == block_nr) {
-
 				len = full_write(localfd, &rbuf[4], len - 4);
 
 				if (len < 0) {
@@ -430,6 +413,7 @@
 				--block_nr;
 				opcode = TFTP_ACK;
 				continue;
+// tmp==(block_nr-1) and (tmp+1)==block_nr is always same, I think. wtf?
 			} else if (tmp + 1 == block_nr) {
 				/* Server lost our TFTP_ACK.  Resend it */
 				block_nr = tmp;
@@ -438,9 +422,8 @@
 			}
 		}
 
-		if ((cmd & tftp_cmd_put) && (opcode == TFTP_ACK)) {
-
-			if (tmp == (unsigned short) (block_nr - 1)) {
+		if (CMD_PUT(cmd) && (opcode == TFTP_ACK)) {
+			if (tmp == (uint16_t) (block_nr - 1)) {
 				if (finished) {
 					break;
 				}
@@ -462,61 +445,32 @@
 
 int tftp_main(int argc, char **argv)
 {
-	struct hostent *host = NULL;
+	len_and_sockaddr *peer_lsa;
 	const char *localfile = NULL;
 	const char *remotefile = NULL;
+#if ENABLE_FEATURE_TFTP_BLOCKSIZE
+	const char *sblocksize = NULL;
+#endif
 	int port;
-	int cmd = 0;
+	USE_GETPUT(int cmd;)
 	int fd = -1;
 	int flags = 0;
 	int result;
 	int blocksize = TFTP_BLOCKSIZE_DEFAULT;
 
-	/* figure out what to pass to getopt */
+	/* -p or -g is mandatory, and they are mutually exclusive */
+	opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:")
+			USE_GETPUT("?g--p:p--g");
 
-#if ENABLE_FEATURE_TFTP_BLOCKSIZE
-	char *sblocksize = NULL;
+	USE_GETPUT(cmd =) getopt32(argc, argv,
+			USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p")
+				"l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"),
+			&localfile, &remotefile
+			USE_FEATURE_TFTP_BLOCKSIZE(, &sblocksize));
 
-#define BS "b:"
-#define BS_ARG , &sblocksize
-#else
-#define BS
-#define BS_ARG
-#endif
-
-#if ENABLE_FEATURE_TFTP_GET
-#define GET "g"
-#define GET_COMPL ":g"
-#else
-#define GET
-#define GET_COMPL
-#endif
-
-#if ENABLE_FEATURE_TFTP_PUT
-#define PUT "p"
-#define PUT_COMPL ":p"
-#else
-#define PUT
-#define PUT_COMPL
-#endif
-
-#if defined(CONFIG_FEATURE_TFTP_GET) && defined(CONFIG_FEATURE_TFTP_PUT)
-	opt_complementary = GET_COMPL PUT_COMPL ":?g--p:p--g";
-#elif defined(CONFIG_FEATURE_TFTP_GET) || defined(CONFIG_FEATURE_TFTP_PUT)
-	opt_complementary = GET_COMPL PUT_COMPL;
-#endif
-
-	cmd = getopt32(argc, argv, GET PUT "l:r:" BS, &localfile, &remotefile BS_ARG);
-
-	cmd &= (tftp_cmd_get | tftp_cmd_put);
-#if ENABLE_FEATURE_TFTP_GET
-	if (cmd == tftp_cmd_get)
+	flags = O_RDONLY;
+	if (CMD_GET(cmd))
 		flags = O_WRONLY | O_CREAT | O_TRUNC;
-#endif
-#if ENABLE_FEATURE_TFTP_PUT
-	if (cmd == tftp_cmd_put)
-		flags = O_RDONLY;
-#endif
 
 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
 	if (sblocksize) {
@@ -535,30 +489,31 @@
 		bb_show_usage();
 
 	if (localfile == NULL || LONE_DASH(localfile)) {
-		fd = (cmd == tftp_cmd_get) ? STDOUT_FILENO : STDIN_FILENO;
+		fd = CMD_GET(cmd) ? STDOUT_FILENO : STDIN_FILENO;
 	} else {
-		fd = open(localfile, flags, 0644); /* fail below */
+		fd = xopen3(localfile, flags, 0644);
 	}
-	if (fd < 0) {
-		bb_perror_msg_and_die("local file");
-	}
 
-	host = xgethostbyname(argv[optind]);
 	port = bb_lookup_port(argv[optind + 1], "udp", 69);
+	peer_lsa = host2sockaddr(argv[optind], port);
 
 #if ENABLE_DEBUG_TFTP
-	fprintf(stderr, "using server \"%s\", remotefile \"%s\", "
-			"localfile \"%s\".\n",
-			inet_ntoa(*((struct in_addr *) host->h_addr)),
+	fprintf(stderr, "using server \"%s\", "
+			"remotefile \"%s\", localfile \"%s\".\n",
+			xmalloc_sockaddr2dotted(&peer_lsa->sa, peer_lsa->len),
 			remotefile, localfile);
 #endif
 
-	result = tftp(cmd, host, remotefile, fd, port, blocksize);
+	result = tftp(
+#if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
+		cmd,
+#endif
+		peer_lsa, remotefile, fd, port, blocksize);
 
-	if (!(fd == STDOUT_FILENO || fd == STDIN_FILENO)) {
+	if (fd > 1) {
 		if (ENABLE_FEATURE_CLEAN_UP)
 			close(fd);
-		if (cmd == tftp_cmd_get && result != EXIT_SUCCESS)
+		if (CMD_GET(cmd) && result != EXIT_SUCCESS)
 			unlink(localfile);
 	}
 	return result;

Modified: trunk/busybox/util-linux/rdate.c
===================================================================
--- trunk/busybox/util-linux/rdate.c	2007-01-11 10:38:10 UTC (rev 17249)
+++ trunk/busybox/util-linux/rdate.c	2007-01-11 16:50:23 UTC (rev 17250)
@@ -8,21 +8,15 @@
  * Licensed under GPL v2 or later, see file License for details.
 */
 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
+//#include <sys/socket.h>
+//#include <netinet/in.h>
+//#include <netdb.h>
+//#include <signal.h>
 
 #include "busybox.h"
 
 
-static const int RFC_868_BIAS = 2208988800UL;
+enum { RFC_868_BIAS = 2208988800UL };
 
 static void socket_timeout(int sig)
 {
@@ -31,18 +25,14 @@
 
 static time_t askremotedate(const char *host)
 {
-	unsigned long nett;
-	struct sockaddr_in s_in;
+	uint32_t nett;
 	int fd;
 
-	bb_lookup_host(&s_in, host);
-	s_in.sin_port = bb_lookup_port("time", "tcp", 37);
-
 	/* Add a timeout for dead or inaccessible servers */
 	alarm(10);
 	signal(SIGALRM, socket_timeout);
 
-	fd = xconnect_tcp_v4(&s_in);
+	fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37));
 
 	if (safe_read(fd, (void *)&nett, 4) != 4)    /* read time from server */
 		bb_error_msg_and_die("%s did not send the complete time", host);
@@ -50,9 +40,9 @@
 
 	/* convert from network byte order to local byte order.
 	 * RFC 868 time is the number of seconds
-	 *  since 00:00 (midnight) 1 January 1900 GMT
-	 *  the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
-	 * Subtract the RFC 868 time  to get Linux epoch
+	 * since 00:00 (midnight) 1 January 1900 GMT
+	 * the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
+	 * Subtract the RFC 868 time to get Linux epoch
 	 */
 
 	return ntohl(nett) - RFC_868_BIAS;




More information about the busybox-cvs mailing list