A patch from Bart Visscher <magick@linux-fan.com> to add an
xconnect helper routine which does:
        -address and port resolving
	-tries to connect to all resolved addresses until connected
	-uses getaddrinfo, so works for IPv6 too
This patch also ports rdate, telnet, and wget to use the new
xconnect function.  Thanks Bart!
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
new file mode 100644
index 0000000..0d670f2
--- /dev/null
+++ b/libbb/xconnect.c
@@ -0,0 +1,78 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Connect to host at port using address resolusion from getaddrinfo
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include "libbb.h"
+
+int xconnect(const char *host, const char *port)
+{
+#if CONFIG_FEATURE_IPV6
+	struct addrinfo hints;
+	struct addrinfo *res;
+	struct addrinfo *addr_info;
+	int error;
+	int s;
+
+	memset(&hints, 0, sizeof(hints));
+	/* set-up hints structure */
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	error = getaddrinfo(host, port, &hints, &res);
+	if (error||!res)
+		perror_msg_and_die(gai_strerror(error));
+	addr_info=res;
+	while (res) {
+		s=socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (s<0)
+		{
+			error=s;
+			res=res->ai_next;
+			continue;
+		}
+		/* try to connect() to res->ai_addr */
+		error = connect(s, res->ai_addr, res->ai_addrlen);
+		if (error >= 0)
+			break;
+		close(s);
+		res=res->ai_next;
+	}
+	freeaddrinfo(addr_info);
+	if (error < 0)
+	{
+		perror_msg_and_die("Unable to connect to remote host (%s)", host);
+	}
+	return s;
+#else
+	struct sockaddr_in s_addr;
+	int s = socket(AF_INET, SOCK_STREAM, 0);
+	struct servent *tserv;
+	int port_nr=atoi(port);
+	struct hostent * he;
+
+	if (port_nr==0 && (tserv = getservbyname(port, "tcp")) != NULL)
+		port_nr = tserv->s_port;
+
+	memset(&s_addr, 0, sizeof(struct sockaddr_in));
+	s_addr.sin_family = AF_INET;
+	s_addr.sin_port = htons(port_nr);
+
+	he = xgethostbyname(host);
+	memcpy(&s_addr.sin_addr, he->h_addr, sizeof s_addr.sin_addr);
+
+	if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0)
+	{
+		perror_msg_and_die("Unable to connect to remote host (%s)", host);
+	}
+	return s;
+#endif
+}
diff --git a/networking/telnet.c b/networking/telnet.c
index 53616c0..86d672c 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -36,13 +36,11 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <stdarg.h>
-#include <string.h>
 #include <signal.h>
 #include <arpa/telnet.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <netdb.h>
 #include "busybox.h"
 
 #ifdef CONFIG_FEATURE_AUTOWIDTH
@@ -122,19 +120,12 @@
 }
 
 /* Function prototypes */
-static int getport(char * p);
-static struct in_addr getserver(char * p);
-static void setup_sockaddr_in(struct sockaddr_in * addr, int port);
-static int remote_connect(struct in_addr addr, int port);
 static void rawmode(void);
 static void cookmode(void);
 static void do_linemode(void);
 static void will_charmode(void);
 static void telopt(byte c);
 static int subneg(byte c);
-#if 0
-static int local_bind(int port);
-#endif
 
 /* Some globals */
 static int one = 1;
@@ -584,8 +575,8 @@
 
 extern int telnet_main(int argc, char** argv)
 {
-	struct in_addr host;
-	int port;
+	char *host;
+	char *port;
 	int len;
 #ifdef USE_POLL
 	struct pollfd ufds[2];
@@ -615,11 +606,13 @@
 	cfmakeraw(&G.termios_raw);
 	
 	if (argc < 2)	show_usage();
-	port = (argc > 2)? getport(argv[2]): 23;
+	port = (argc > 2)? argv[2] : "23";
 	
-	host = getserver(argv[1]);
+	host = argv[1];
+	
+	G.netfd = xconnect(host, port);
 
-	G.netfd = remote_connect(host, port);
+	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);
 
 	signal(SIGINT, fgotsig);
 
@@ -691,81 +684,6 @@
 	}
 }
 
-static int getport(char * p)
-{
-	unsigned int port = atoi(p);
-
-	if ((unsigned)(port - 1 ) > 65534)
-	{
-		error_msg_and_die("%s: bad port number", p);
-	}
-	return port;
-}
-
-static struct in_addr getserver(char * host)
-{
-	struct in_addr addr;
-
-	struct hostent * he;
-	he = xgethostbyname(host);
-	memcpy(&addr, he->h_addr, sizeof addr);
-
-	TRACE(1, ("addr: %s\n", inet_ntoa(addr)));
-
-	return addr;
-}
-
-static int create_socket(void)
-{
-	return socket(AF_INET, SOCK_STREAM, 0);
-}
-
-static void setup_sockaddr_in(struct sockaddr_in * addr, int port)
-{
-	memset(addr, 0, sizeof(struct sockaddr_in));
-	addr->sin_family = AF_INET;
-	addr->sin_port = htons(port);
-}
-  
-#if 0
-static int local_bind(int port)
-{
-	struct sockaddr_in s_addr;
-	int s = create_socket();
-  
-	setup_sockaddr_in(&s_addr, port);
-  
-	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
-  
-	if (bind(s, &s_addr, sizeof s_addr) < 0)
-	{
-		char * e = sys_errlist[errno];
-		syserrorexit("bind");
-		exit(1);
-	}
-	listen(s, 1);
-	
-	return s;
-}
-#endif
-
-static int remote_connect(struct in_addr addr, int port)
-{
-	struct sockaddr_in s_addr;
-	int s = create_socket();
-
-	setup_sockaddr_in(&s_addr, port);
-	s_addr.sin_addr = addr;
-
-	setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);
-
-	if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0)
-	{
-		perror_msg_and_die("Unable to connect to remote host");
-	}
-	return s;
-}
-
 /*
 Local Variables:
 c-file-style: "linux"
diff --git a/networking/wget.c b/networking/wget.c
index 6974c70..c620021 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -563,24 +563,16 @@
 
 FILE *open_socket(char *host, int port)
 {
-	struct sockaddr_in s_in;
-	struct hostent *hp;
 	int fd;
 	FILE *fp;
+	char port_str[10];
 
-	memset(&s_in, 0, sizeof(s_in));
-	s_in.sin_family = AF_INET;
-	hp = xgethostbyname(host);
-	memcpy(&s_in.sin_addr, hp->h_addr_list[0], hp->h_length);
-	s_in.sin_port = htons(port);
+	snprintf(port_str, sizeof(port_str), "%d", port);
+	fd=xconnect(host, port_str);
 
 	/*
 	 * Get the server onto a stdio stream.
 	 */
-	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-		perror_msg_and_die("socket()");
-	if (connect(fd, (struct sockaddr *) &s_in, sizeof(s_in)) < 0)
-		perror_msg_and_die("connect(%s)", host);
 	if ((fp = fdopen(fd, "r+")) == NULL)
 		perror_msg_and_die("fdopen()");
 
@@ -826,7 +818,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$Id: wget.c,v 1.49 2002/05/14 23:36:45 sandman Exp $
+ *	$Id: wget.c,v 1.50 2002/07/03 11:51:44 andersen Exp $
  */
 
 
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 04a7612..df7d7bb 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -39,26 +39,14 @@
 
 static time_t askremotedate(const char *host)
 {
-	struct hostent *h;
-	struct sockaddr_in s_in;
-	struct servent *tserv;
 	unsigned long int nett, localt;
+	const char *port="37";
 	int fd;
 
-	h = xgethostbyname(host);         /* get the IP addr */
-	memcpy(&s_in.sin_addr, h->h_addr, sizeof(s_in.sin_addr));
+	if (getservbyname("time", "tcp") != NULL)
+		port="time";
 
-	s_in.sin_port = htons(37);		  /* find port # */
-	if ((tserv = getservbyname("time", "tcp")) != NULL)
-		s_in.sin_port = tserv->s_port;
-
-	s_in.sin_family = AF_INET;
-
-	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)    /* get net connection */
-		perror_msg_and_die("socket");
-
-	if (connect(fd, (struct sockaddr *)&s_in, sizeof(s_in)) < 0)      /* connect to time server */
-		perror_msg_and_die("%s", host);
+	fd = xconnect(host, port);
 
 	if (read(fd, (void *)&nett, 4) != 4)    /* read time from server */
 		error_msg_and_die("%s did not send the complete time", host);