A patch from Bart Visscher <magick@linux-fan.com> to add an
authorEric Andersen <andersen@codepoet.org>
Wed, 3 Jul 2002 11:51:44 +0000 (11:51 -0000)
committerEric Andersen <andersen@codepoet.org>
Wed, 3 Jul 2002 11:51:44 +0000 (11:51 -0000)
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!

libbb/xconnect.c [new file with mode: 0644]
networking/telnet.c
networking/wget.c
util-linux/rdate.c

diff --git a/libbb/xconnect.c b/libbb/xconnect.c
new file mode 100644 (file)
index 0000000..0d670f2
--- /dev/null
@@ -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
+}
index 53616c01d2dc0eb040f9bae872246550dceab0fd..86d672c2d5fd6ec81971fcc2baa39c57df4508f3 100644 (file)
 #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 @@ static inline void iacflush(void)
 }
 
 /* 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 @@ static void cookmode(void)
 
 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 @@ extern int telnet_main(int argc, char** argv)
        cfmakeraw(&G.termios_raw);
        
        if (argc < 2)   show_usage();
-       port = (argc > 2)? getport(argv[2]): 23;
+       port = (argc > 2)? argv[2] : "23";
+       
+       host = argv[1];
        
-       host = getserver(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 @@ extern int telnet_main(int argc, char** argv)
        }
 }
 
-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"
index 6974c70a8f4ac238296da499970d1d7a75f94087..c6200219bf1242053d471d33913841d3b773a755 100644 (file)
@@ -563,24 +563,16 @@ void parse_url(char *url, struct host_info *h)
 
 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 @@ progressmeter(int flag)
  * 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 $
  */
 
 
index 04a76129a3f62d2e199ad042c8d412bc4313deb0..df7d7bbc413445cbc76e8851bc3fe2e68969d432 100644 (file)
@@ -39,26 +39,14 @@ static const int RFC_868_BIAS = 2208988800UL;
 
 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);