X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fconnect.c;h=43ed0083512c06364365116c89dc968ea9b2e3ab;hp=3e676b42a5ac39605f0275d7ad671f3421482953;hb=cb4003403509b46d2f6ef6936baf969906ff1430;hpb=d60b54cba08a26f5fc886a7e9597b6790da252cc diff --git a/src/connect.c b/src/connect.c index 3e676b42..43ed0083 100644 --- a/src/connect.c +++ b/src/connect.c @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_UNISTD_H # include #endif +#include #ifdef WINDOWS # include @@ -58,55 +59,111 @@ extern int errno; static int msock = -1; static struct sockaddr *addr; +/* A kludge, but still better than passing the host name all the way + to connect_to_one. */ +static const char *connection_host_name; -/* Create an internet connection to HOSTNAME on PORT. The created - socket will be stored to *SOCK. */ -uerr_t -make_connection (int *sock, char *hostname, unsigned short port) +void +set_connection_host_name (const char *host) { - struct sockaddr_in sock_name; - /* struct hostent *hptr; */ - - /* Get internet address of the host. We can do it either by calling - ngethostbyname, or by calling store_hostaddress, from host.c. - storehostaddress is better since it caches calls to - gethostbyname. */ -#if 1 - if (!store_hostaddress ((unsigned char *)&sock_name.sin_addr, hostname)) - return HOSTERR; -#else /* never */ - if (!(hptr = ngethostbyname (hostname))) - return HOSTERR; - /* Copy the address of the host to socket description. */ - memcpy (&sock_name.sin_addr, hptr->h_addr, hptr->h_length); -#endif /* never */ + if (host) + assert (connection_host_name == NULL); + else + assert (connection_host_name != NULL); + + connection_host_name = host; +} + +/* Connect to a remote host whose address has been resolved. */ +int +connect_to_one (ip_address *addr, unsigned short port, int silent) +{ + wget_sockaddr sa; + int sock, save_errno; /* Set port and protocol */ - sock_name.sin_family = AF_INET; - sock_name.sin_port = htons (port); + wget_sockaddr_set_address (&sa, ip_default_family, port, addr); + + if (!silent) + { + char *pretty_addr = pretty_print_address (addr); + if (connection_host_name + && 0 != strcmp (connection_host_name, pretty_addr)) + logprintf (LOG_VERBOSE, _("Connecting to %s[%s]:%hu... "), + connection_host_name, pretty_addr, port); + else + logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), + pretty_addr, port); + } /* Make an internet socket, stream type. */ - if ((*sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) - return CONSOCKERR; + sock = socket (ip_default_family, SOCK_STREAM, 0); + if (sock < 0) + goto out; - if (opt.bind_address != NULL) + if (opt.bind_address) { /* Bind the client side to the requested address. */ - if (bind (*sock, (struct sockaddr *) opt.bind_address, - sizeof (*opt.bind_address))) - return CONSOCKERR; + if (bind (sock, (struct sockaddr *)opt.bind_address, sockaddr_len ())) + { + close (sock); + sock = -1; + goto out; + } } /* Connect the socket to the remote host. */ - if (connect (*sock, (struct sockaddr *) &sock_name, sizeof (sock_name))) + if (connect (sock, &sa.sa, sockaddr_len ()) < 0) { - if (errno == ECONNREFUSED) - return CONREFUSED; - else - return CONERROR; + close (sock); + sock = -1; + goto out; + } + + out: + if (sock >= 0) + { + /* Success. */ + if (!silent) + logprintf (LOG_VERBOSE, _("connected.\n")); + DEBUGP (("Created socket %d.\n", sock)); + } + else + { + save_errno = errno; + if (!silent) + logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno)); + errno = save_errno; + } + + return sock; +} + +/* Connect to a remote host whose address has been resolved. */ +int +connect_to_many (struct address_list *al, unsigned short port, int silent) +{ + int i, start, end; + + address_list_get_bounds (al, &start, &end); + for (i = start; i < end; i++) + { + ip_address addr; + int sock; + address_list_copy_one (al, i, &addr); + + sock = connect_to_one (&addr, port, silent); + if (sock >= 0) + /* Success. */ + return sock; + + address_list_set_faulty (al, i); + + /* The attempt to connect has failed. Continue with the loop + and try next address. */ } - DEBUGP (("Created fd %d.\n", *sock)); - return NOCONERROR; + + return -1; } int @@ -147,29 +204,26 @@ test_socket_open (int sock) internal variable MPORT is set to the value of the ensuing master socket. Call acceptport() to block for and accept a connection. */ uerr_t -bindport (unsigned short *port) +bindport (unsigned short *port, int family) { int optval = 1; - static struct sockaddr_in srv; + wget_sockaddr srv; + memset (&srv, 0, sizeof (wget_sockaddr)); msock = -1; - addr = (struct sockaddr *) &srv; - if ((msock = socket (AF_INET, SOCK_STREAM, 0)) < 0) + + if ((msock = socket (family, SOCK_STREAM, 0)) < 0) return CONSOCKERR; if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof (optval)) < 0) return CONSOCKERR; if (opt.bind_address == NULL) - { - srv.sin_family = AF_INET; - srv.sin_addr.s_addr = htonl (INADDR_ANY); - } + wget_sockaddr_set_address (&srv, ip_default_family, htons (*port), NULL); else srv = *opt.bind_address; - - srv.sin_port = htons (*port); - if (bind (msock, addr, sizeof (struct sockaddr_in)) < 0) + wget_sockaddr_set_port (&srv, *port); + if (bind (msock, &srv.sa, sockaddr_len ()) < 0) { CLOSE (msock); msock = -1; @@ -181,14 +235,15 @@ bindport (unsigned short *port) /* #### addrlen should be a 32-bit type, which int is not guaranteed to be. Oh, and don't try to make it a size_t, because that can be 64-bit. */ - int addrlen = sizeof (struct sockaddr_in); - if (getsockname (msock, addr, &addrlen) < 0) + int sa_len = sockaddr_len (); + if (getsockname (msock, &srv.sa, &sa_len) < 0) { CLOSE (msock); msock = -1; return CONPORTERR; } - *port = ntohs (srv.sin_port); + *port = wget_sockaddr_get_port (&srv); + DEBUGP (("using port %i.\n", *port)); } if (listen (msock, 1) < 0) { @@ -232,7 +287,7 @@ select_fd (int fd, int maxtime, int writep) uerr_t acceptport (int *sock) { - int addrlen = sizeof (struct sockaddr_in); + int addrlen = sockaddr_len (); #ifdef HAVE_SELECT if (select_fd (msock, opt.timeout, 0) <= 0) @@ -257,22 +312,33 @@ closeport (int sock) msock = -1; } -/* Return the local IP address associated with the connection on FD. - It is returned in a static buffer. */ -unsigned char * -conaddr (int fd) +/* Return the local IP address associated with the connection on FD. */ + +int +conaddr (int fd, ip_address *ip) { - static unsigned char res[4]; - struct sockaddr_in mysrv; - struct sockaddr *myaddr; - int addrlen = sizeof (mysrv); /* see bindport() for discussion of - using `int' here. */ - - myaddr = (struct sockaddr *) (&mysrv); - if (getsockname (fd, myaddr, (int *)&addrlen) < 0) - return NULL; - memcpy (res, &mysrv.sin_addr, 4); - return res; + wget_sockaddr mysrv; + + /* see bindport() for discussion of using `int' here. */ + int addrlen = sizeof (mysrv); + + if (getsockname (fd, &mysrv.sa, (int *)&addrlen) < 0) + return 0; + + switch (mysrv.sa.sa_family) + { +#ifdef INET6 + case AF_INET6: + memcpy (ip, &mysrv.sin6.sin6_addr, 16); + return 1; +#endif + case AF_INET: + map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, ip); + return 1; + default: + abort (); + } + return 0; } /* Read at most LEN bytes from FD, storing them to BUF. This is