diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-07-03 11:51:44 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-07-03 11:51:44 +0000 |
commit | 0b31586c7113b9b26ca0aeee9247a831b55b308c (patch) | |
tree | 7071145eeeea4dd92d18e05fce6d8e710dc67d52 | |
parent | 51b8bd68bb22b1cc5d95e418813c2f08a194ec2b (diff) | |
download | busybox-w32-0b31586c7113b9b26ca0aeee9247a831b55b308c.tar.gz busybox-w32-0b31586c7113b9b26ca0aeee9247a831b55b308c.tar.bz2 busybox-w32-0b31586c7113b9b26ca0aeee9247a831b55b308c.zip |
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.c | 78 | ||||
-rw-r--r-- | networking/telnet.c | 96 | ||||
-rw-r--r-- | networking/wget.c | 16 | ||||
-rw-r--r-- | util-linux/rdate.c | 20 |
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 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Connect to host at port using address resolusion from getaddrinfo | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <unistd.h> | ||
10 | #include <string.h> | ||
11 | #include <sys/types.h> | ||
12 | #include <sys/socket.h> | ||
13 | #include <netdb.h> | ||
14 | #include <stdlib.h> | ||
15 | #include "libbb.h" | ||
16 | |||
17 | int xconnect(const char *host, const char *port) | ||
18 | { | ||
19 | #if CONFIG_FEATURE_IPV6 | ||
20 | struct addrinfo hints; | ||
21 | struct addrinfo *res; | ||
22 | struct addrinfo *addr_info; | ||
23 | int error; | ||
24 | int s; | ||
25 | |||
26 | memset(&hints, 0, sizeof(hints)); | ||
27 | /* set-up hints structure */ | ||
28 | hints.ai_family = PF_UNSPEC; | ||
29 | hints.ai_socktype = SOCK_STREAM; | ||
30 | error = getaddrinfo(host, port, &hints, &res); | ||
31 | if (error||!res) | ||
32 | perror_msg_and_die(gai_strerror(error)); | ||
33 | addr_info=res; | ||
34 | while (res) { | ||
35 | s=socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
36 | if (s<0) | ||
37 | { | ||
38 | error=s; | ||
39 | res=res->ai_next; | ||
40 | continue; | ||
41 | } | ||
42 | /* try to connect() to res->ai_addr */ | ||
43 | error = connect(s, res->ai_addr, res->ai_addrlen); | ||
44 | if (error >= 0) | ||
45 | break; | ||
46 | close(s); | ||
47 | res=res->ai_next; | ||
48 | } | ||
49 | freeaddrinfo(addr_info); | ||
50 | if (error < 0) | ||
51 | { | ||
52 | perror_msg_and_die("Unable to connect to remote host (%s)", host); | ||
53 | } | ||
54 | return s; | ||
55 | #else | ||
56 | struct sockaddr_in s_addr; | ||
57 | int s = socket(AF_INET, SOCK_STREAM, 0); | ||
58 | struct servent *tserv; | ||
59 | int port_nr=atoi(port); | ||
60 | struct hostent * he; | ||
61 | |||
62 | if (port_nr==0 && (tserv = getservbyname(port, "tcp")) != NULL) | ||
63 | port_nr = tserv->s_port; | ||
64 | |||
65 | memset(&s_addr, 0, sizeof(struct sockaddr_in)); | ||
66 | s_addr.sin_family = AF_INET; | ||
67 | s_addr.sin_port = htons(port_nr); | ||
68 | |||
69 | he = xgethostbyname(host); | ||
70 | memcpy(&s_addr.sin_addr, he->h_addr, sizeof s_addr.sin_addr); | ||
71 | |||
72 | if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0) | ||
73 | { | ||
74 | perror_msg_and_die("Unable to connect to remote host (%s)", host); | ||
75 | } | ||
76 | return s; | ||
77 | #endif | ||
78 | } | ||
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 @@ | |||
36 | #include <errno.h> | 36 | #include <errno.h> |
37 | #include <stdlib.h> | 37 | #include <stdlib.h> |
38 | #include <stdarg.h> | 38 | #include <stdarg.h> |
39 | #include <string.h> | ||
40 | #include <signal.h> | 39 | #include <signal.h> |
41 | #include <arpa/telnet.h> | 40 | #include <arpa/telnet.h> |
42 | #include <sys/types.h> | 41 | #include <sys/types.h> |
43 | #include <sys/socket.h> | 42 | #include <sys/socket.h> |
44 | #include <netinet/in.h> | 43 | #include <netinet/in.h> |
45 | #include <netdb.h> | ||
46 | #include "busybox.h" | 44 | #include "busybox.h" |
47 | 45 | ||
48 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 46 | #ifdef CONFIG_FEATURE_AUTOWIDTH |
@@ -122,19 +120,12 @@ static inline void iacflush(void) | |||
122 | } | 120 | } |
123 | 121 | ||
124 | /* Function prototypes */ | 122 | /* Function prototypes */ |
125 | static int getport(char * p); | ||
126 | static struct in_addr getserver(char * p); | ||
127 | static void setup_sockaddr_in(struct sockaddr_in * addr, int port); | ||
128 | static int remote_connect(struct in_addr addr, int port); | ||
129 | static void rawmode(void); | 123 | static void rawmode(void); |
130 | static void cookmode(void); | 124 | static void cookmode(void); |
131 | static void do_linemode(void); | 125 | static void do_linemode(void); |
132 | static void will_charmode(void); | 126 | static void will_charmode(void); |
133 | static void telopt(byte c); | 127 | static void telopt(byte c); |
134 | static int subneg(byte c); | 128 | static int subneg(byte c); |
135 | #if 0 | ||
136 | static int local_bind(int port); | ||
137 | #endif | ||
138 | 129 | ||
139 | /* Some globals */ | 130 | /* Some globals */ |
140 | static int one = 1; | 131 | static int one = 1; |
@@ -584,8 +575,8 @@ static void cookmode(void) | |||
584 | 575 | ||
585 | extern int telnet_main(int argc, char** argv) | 576 | extern int telnet_main(int argc, char** argv) |
586 | { | 577 | { |
587 | struct in_addr host; | 578 | char *host; |
588 | int port; | 579 | char *port; |
589 | int len; | 580 | int len; |
590 | #ifdef USE_POLL | 581 | #ifdef USE_POLL |
591 | struct pollfd ufds[2]; | 582 | struct pollfd ufds[2]; |
@@ -615,11 +606,13 @@ extern int telnet_main(int argc, char** argv) | |||
615 | cfmakeraw(&G.termios_raw); | 606 | cfmakeraw(&G.termios_raw); |
616 | 607 | ||
617 | if (argc < 2) show_usage(); | 608 | if (argc < 2) show_usage(); |
618 | port = (argc > 2)? getport(argv[2]): 23; | 609 | port = (argc > 2)? argv[2] : "23"; |
610 | |||
611 | host = argv[1]; | ||
619 | 612 | ||
620 | host = getserver(argv[1]); | 613 | G.netfd = xconnect(host, port); |
621 | 614 | ||
622 | G.netfd = remote_connect(host, port); | 615 | setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one); |
623 | 616 | ||
624 | signal(SIGINT, fgotsig); | 617 | signal(SIGINT, fgotsig); |
625 | 618 | ||
@@ -691,81 +684,6 @@ extern int telnet_main(int argc, char** argv) | |||
691 | } | 684 | } |
692 | } | 685 | } |
693 | 686 | ||
694 | static int getport(char * p) | ||
695 | { | ||
696 | unsigned int port = atoi(p); | ||
697 | |||
698 | if ((unsigned)(port - 1 ) > 65534) | ||
699 | { | ||
700 | error_msg_and_die("%s: bad port number", p); | ||
701 | } | ||
702 | return port; | ||
703 | } | ||
704 | |||
705 | static struct in_addr getserver(char * host) | ||
706 | { | ||
707 | struct in_addr addr; | ||
708 | |||
709 | struct hostent * he; | ||
710 | he = xgethostbyname(host); | ||
711 | memcpy(&addr, he->h_addr, sizeof addr); | ||
712 | |||
713 | TRACE(1, ("addr: %s\n", inet_ntoa(addr))); | ||
714 | |||
715 | return addr; | ||
716 | } | ||
717 | |||
718 | static int create_socket(void) | ||
719 | { | ||
720 | return socket(AF_INET, SOCK_STREAM, 0); | ||
721 | } | ||
722 | |||
723 | static void setup_sockaddr_in(struct sockaddr_in * addr, int port) | ||
724 | { | ||
725 | memset(addr, 0, sizeof(struct sockaddr_in)); | ||
726 | addr->sin_family = AF_INET; | ||
727 | addr->sin_port = htons(port); | ||
728 | } | ||
729 | |||
730 | #if 0 | ||
731 | static int local_bind(int port) | ||
732 | { | ||
733 | struct sockaddr_in s_addr; | ||
734 | int s = create_socket(); | ||
735 | |||
736 | setup_sockaddr_in(&s_addr, port); | ||
737 | |||
738 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); | ||
739 | |||
740 | if (bind(s, &s_addr, sizeof s_addr) < 0) | ||
741 | { | ||
742 | char * e = sys_errlist[errno]; | ||
743 | syserrorexit("bind"); | ||
744 | exit(1); | ||
745 | } | ||
746 | listen(s, 1); | ||
747 | |||
748 | return s; | ||
749 | } | ||
750 | #endif | ||
751 | |||
752 | static int remote_connect(struct in_addr addr, int port) | ||
753 | { | ||
754 | struct sockaddr_in s_addr; | ||
755 | int s = create_socket(); | ||
756 | |||
757 | setup_sockaddr_in(&s_addr, port); | ||
758 | s_addr.sin_addr = addr; | ||
759 | |||
760 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one); | ||
761 | |||
762 | if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0) | ||
763 | { | ||
764 | perror_msg_and_die("Unable to connect to remote host"); | ||
765 | } | ||
766 | return s; | ||
767 | } | ||
768 | |||
769 | /* | 687 | /* |
770 | Local Variables: | 688 | Local Variables: |
771 | c-file-style: "linux" | 689 | 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) | |||
563 | 563 | ||
564 | FILE *open_socket(char *host, int port) | 564 | FILE *open_socket(char *host, int port) |
565 | { | 565 | { |
566 | struct sockaddr_in s_in; | ||
567 | struct hostent *hp; | ||
568 | int fd; | 566 | int fd; |
569 | FILE *fp; | 567 | FILE *fp; |
568 | char port_str[10]; | ||
570 | 569 | ||
571 | memset(&s_in, 0, sizeof(s_in)); | 570 | snprintf(port_str, sizeof(port_str), "%d", port); |
572 | s_in.sin_family = AF_INET; | 571 | fd=xconnect(host, port_str); |
573 | hp = xgethostbyname(host); | ||
574 | memcpy(&s_in.sin_addr, hp->h_addr_list[0], hp->h_length); | ||
575 | s_in.sin_port = htons(port); | ||
576 | 572 | ||
577 | /* | 573 | /* |
578 | * Get the server onto a stdio stream. | 574 | * Get the server onto a stdio stream. |
579 | */ | 575 | */ |
580 | if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) | ||
581 | perror_msg_and_die("socket()"); | ||
582 | if (connect(fd, (struct sockaddr *) &s_in, sizeof(s_in)) < 0) | ||
583 | perror_msg_and_die("connect(%s)", host); | ||
584 | if ((fp = fdopen(fd, "r+")) == NULL) | 576 | if ((fp = fdopen(fd, "r+")) == NULL) |
585 | perror_msg_and_die("fdopen()"); | 577 | perror_msg_and_die("fdopen()"); |
586 | 578 | ||
@@ -826,7 +818,7 @@ progressmeter(int flag) | |||
826 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 818 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
827 | * SUCH DAMAGE. | 819 | * SUCH DAMAGE. |
828 | * | 820 | * |
829 | * $Id: wget.c,v 1.49 2002/05/14 23:36:45 sandman Exp $ | 821 | * $Id: wget.c,v 1.50 2002/07/03 11:51:44 andersen Exp $ |
830 | */ | 822 | */ |
831 | 823 | ||
832 | 824 | ||
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; | |||
39 | 39 | ||
40 | static time_t askremotedate(const char *host) | 40 | static time_t askremotedate(const char *host) |
41 | { | 41 | { |
42 | struct hostent *h; | ||
43 | struct sockaddr_in s_in; | ||
44 | struct servent *tserv; | ||
45 | unsigned long int nett, localt; | 42 | unsigned long int nett, localt; |
43 | const char *port="37"; | ||
46 | int fd; | 44 | int fd; |
47 | 45 | ||
48 | h = xgethostbyname(host); /* get the IP addr */ | 46 | if (getservbyname("time", "tcp") != NULL) |
49 | memcpy(&s_in.sin_addr, h->h_addr, sizeof(s_in.sin_addr)); | 47 | port="time"; |
50 | 48 | ||
51 | s_in.sin_port = htons(37); /* find port # */ | 49 | fd = xconnect(host, port); |
52 | if ((tserv = getservbyname("time", "tcp")) != NULL) | ||
53 | s_in.sin_port = tserv->s_port; | ||
54 | |||
55 | s_in.sin_family = AF_INET; | ||
56 | |||
57 | if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* get net connection */ | ||
58 | perror_msg_and_die("socket"); | ||
59 | |||
60 | if (connect(fd, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) /* connect to time server */ | ||
61 | perror_msg_and_die("%s", host); | ||
62 | 50 | ||
63 | if (read(fd, (void *)&nett, 4) != 4) /* read time from server */ | 51 | if (read(fd, (void *)&nett, 4) != 4) /* read time from server */ |
64 | error_msg_and_die("%s did not send the complete time", host); | 52 | error_msg_and_die("%s did not send the complete time", host); |