/* Variables shared by bindport and acceptport: */
static int msock = -1;
-static struct sockaddr *addr;
+/*static struct sockaddr *addr;*/
-static ip_address bind_address;
-static int bind_address_resolved;
-
-static void
-resolve_bind_address (void)
+static int
+resolve_bind_address (int flags, ip_address *addr)
{
- struct address_list *al;
+ struct address_list *al = NULL;
+ int bind_address_resolved = 0;
- if (bind_address_resolved || opt.bind_address == NULL)
- /* Nothing to do. */
- return;
+ if (opt.bind_address != NULL)
+ {
+ al = lookup_host (opt.bind_address, flags | LH_SILENT | LH_PASSIVE);
+
+ if (al == NULL)
+ {
+ logprintf (LOG_NOTQUIET,
+ _("Unable to convert `%s' to a bind address. Reverting to ANY.\n"),
+ opt.bind_address);
+ }
+ else
+ bind_address_resolved = 1;
+ }
- al = lookup_host (opt.bind_address, 1);
- if (!al)
+ if (al == NULL)
{
- logprintf (LOG_NOTQUIET,
- _("Unable to convert `%s' to a bind address. Reverting to ANY.\n"),
- opt.bind_address);
- return;
+ const char *unspecified_address = "0.0.0.0";
+#ifdef ENABLE_IPV6
+ if (flags & BIND_ON_IPV6_ONLY)
+ unspecified_address = "::";
+#endif
+ al = lookup_host (unspecified_address, LH_SILENT | LH_PASSIVE);
}
- address_list_copy_one (al, 0, &bind_address);
+ assert (al != NULL);
+
+ address_list_copy_one (al, 0, addr);
address_list_release (al);
- bind_address_resolved = 1;
+
+ return bind_address_resolved;
}
\f
struct cwt_context {
int
connect_to_one (ip_address *addr, unsigned short port, int silent)
{
- wget_sockaddr sa;
+ struct sockaddr_storage ss;
+ struct sockaddr *sa = (struct sockaddr *)&ss;
int sock, save_errno;
/* Set port and protocol */
- wget_sockaddr_set_address (&sa, ip_default_family, port, addr);
+ sockaddr_set_address (sa, port, addr);
if (!silent)
{
- char *pretty_addr = pretty_print_address (addr);
+ const 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... "),
}
/* Make an internet socket, stream type. */
- sock = socket (ip_default_family, SOCK_STREAM, 0);
+ sock = socket (sa->sa_family, SOCK_STREAM, 0);
if (sock < 0)
goto out;
`--post-file', also set SO_SNDBUF here. */
}
- resolve_bind_address ();
- if (bind_address_resolved)
+ if (opt.bind_address)
{
/* Bind the client side to the requested address. */
- wget_sockaddr bsa;
- wget_sockaddr_set_address (&bsa, ip_default_family, 0, &bind_address);
- if (bind (sock, &bsa.sa, sockaddr_len ()))
- {
- CLOSE (sock);
- sock = -1;
- goto out;
+ ip_address bind_address;
+ if (resolve_bind_address (0, &bind_address))
+ {
+ struct sockaddr_storage bss;
+ struct sockaddr *bsa = (struct sockaddr *)&bss;
+ sockaddr_set_address (bsa, 0, &bind_address);
+ if (bind (sock, bsa, sockaddr_len (bsa)))
+ {
+ CLOSE (sock);
+ sock = -1;
+ goto out;
+ }
}
}
/* Connect the socket to the remote host. */
- if (connect_with_timeout (sock, &sa.sa, sockaddr_len (),
+ if (connect_with_timeout (sock, sa, sockaddr_len (sa),
opt.connect_timeout) < 0)
{
CLOSE (sock);
chosen by the system, and its value is stored to *PORT. The
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, int family)
+bindport (const ip_address *bind_address, unsigned short *port)
{
- int optval = 1;
- wget_sockaddr srv;
- memset (&srv, 0, sizeof (wget_sockaddr));
+ int family = AF_INET;
+ int optval;
+ struct sockaddr_storage ss;
+ struct sockaddr *sa = (struct sockaddr *)&ss;
+ memset (&ss, 0, sizeof (ss));
msock = -1;
+#ifdef ENABLE_IPV6
+ if (bind_address->type == IPv6_ADDRESS)
+ family = AF_INET6;
+#endif
+
if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
return CONSOCKERR;
#ifdef SO_REUSEADDR
+ optval = 1;
if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
(char *)&optval, sizeof (optval)) < 0)
return CONSOCKERR;
#endif
- resolve_bind_address ();
- wget_sockaddr_set_address (&srv, ip_default_family, htons (*port),
- bind_address_resolved ? &bind_address : NULL);
- if (bind (msock, &srv.sa, sockaddr_len ()) < 0)
+#ifdef ENABLE_IPV6
+# ifdef HAVE_IPV6_V6ONLY
+ if (family == AF_INET6)
+ {
+ optval = 1;
+ /* if setsockopt fails, go on anyway */
+ setsockopt (msock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&optval, sizeof (optval));
+ }
+# endif
+#endif
+
+ sockaddr_set_address (sa, htons (*port), bind_address);
+ if (bind (msock, sa, sockaddr_len (sa)) < 0)
{
CLOSE (msock);
msock = -1;
DEBUGP (("Master socket fd %d bound.\n", msock));
if (!*port)
{
- socklen_t sa_len = sockaddr_len ();
- if (getsockname (msock, &srv.sa, &sa_len) < 0)
+ socklen_t sa_len = sockaddr_len (sa);
+ if (getsockname (msock, sa, &sa_len) < 0)
{
CLOSE (msock);
msock = -1;
return CONPORTERR;
}
- *port = wget_sockaddr_get_port (&srv);
- DEBUGP (("using port %i.\n", *port));
+ *port = sockaddr_get_port (sa);
+ DEBUGP (("binding to address %s using port %i.\n",
+ pretty_print_address (bind_address), *port));
}
if (listen (msock, 1) < 0)
{
uerr_t
acceptport (int *sock)
{
- socklen_t addrlen = sockaddr_len ();
+ struct sockaddr_storage ss;
+ struct sockaddr *sa = (struct sockaddr *)&ss;
+ socklen_t addrlen = sizeof (ss);
#ifdef HAVE_SELECT
if (select_fd (msock, opt.connect_timeout, 0) <= 0)
return ACCEPTERR;
#endif
- if ((*sock = accept (msock, addr, &addrlen)) < 0)
+ if ((*sock = accept (msock, sa, &addrlen)) < 0)
return ACCEPTERR;
DEBUGP (("Created socket fd %d.\n", *sock));
return ACCEPTOK;
int
conaddr (int fd, ip_address *ip)
{
- wget_sockaddr mysrv;
- socklen_t addrlen = sizeof (mysrv);
- if (getsockname (fd, &mysrv.sa, &addrlen) < 0)
+ struct sockaddr_storage ss;
+ struct sockaddr *sa = (struct sockaddr *)&ss;
+ socklen_t addrlen = sizeof (ss);
+
+ if (getsockname (fd, sa, &addrlen) < 0)
return 0;
- switch (mysrv.sa.sa_family)
+ switch (sa->sa_family)
{
#ifdef ENABLE_IPV6
case AF_INET6:
- memcpy (ip, &mysrv.sin6.sin6_addr, 16);
+ ip->type = IPv6_ADDRESS;
+ ip->addr.ipv6.addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
+#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
+ ip->addr.ipv6.scope_id = ((struct sockaddr_in6 *)sa)->sin6_scope_id;
+#endif
+ DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
return 1;
#endif
case AF_INET:
- map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, ip);
+ ip->type = IPv4_ADDRESS;
+ ip->addr.ipv4.addr = ((struct sockaddr_in *)sa)->sin_addr;
+ DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
return 1;
default:
abort ();
}
+
return 0;
}