aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-07-03 11:51:44 +0000
committerEric Andersen <andersen@codepoet.org>2002-07-03 11:51:44 +0000
commit0b31586c7113b9b26ca0aeee9247a831b55b308c (patch)
tree7071145eeeea4dd92d18e05fce6d8e710dc67d52
parent51b8bd68bb22b1cc5d95e418813c2f08a194ec2b (diff)
downloadbusybox-0b31586c7113b9b26ca0aeee9247a831b55b308c.tar.gz
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!
-rw-r--r--libbb/xconnect.c78
-rw-r--r--networking/telnet.c96
-rw-r--r--networking/wget.c16
-rw-r--r--util-linux/rdate.c20
4 files changed, 93 insertions, 117 deletions
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
new file mode 100644
index 000000000..0d670f286
--- /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 53616c01d..86d672c2d 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 @@ 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"
diff --git a/networking/wget.c b/networking/wget.c
index 6974c70a8..c6200219b 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -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 $
*/
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 04a76129a..df7d7bbc4 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -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);