mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Updated IPv6 code.
This commit is contained in:
parent
8c19243974
commit
6f1250b1c6
@ -1,3 +1,12 @@
|
||||
2003-10-29 Hrvoje Niksic <hniksic@xemacs.org>
|
||||
|
||||
* host.h: Defined accessors for elements of ip_address. Updated
|
||||
all callers.
|
||||
(address_list_match_all): Use memcmp in the non-IPv6 case.
|
||||
|
||||
* wget.h (CONNECT_ERROR): Don't retry connecting if connect()
|
||||
returned EAFNOSUPPORT.
|
||||
|
||||
2003-10-27 Mauro Tortonesi <mauro@deepspace6.net>
|
||||
|
||||
* host.c, connect.c, ftp.c, ...: Added support for dual-family
|
||||
|
@ -73,12 +73,11 @@ static int
|
||||
resolve_bind_address (int flags, ip_address *addr)
|
||||
{
|
||||
struct address_list *al = NULL;
|
||||
int bind_address_resolved = 0;
|
||||
int resolved = 0;
|
||||
|
||||
if (opt.bind_address != NULL)
|
||||
{
|
||||
al = lookup_host (opt.bind_address, flags | LH_SILENT | LH_PASSIVE);
|
||||
|
||||
if (al == NULL)
|
||||
{
|
||||
logprintf (LOG_NOTQUIET,
|
||||
@ -86,11 +85,14 @@ resolve_bind_address (int flags, ip_address *addr)
|
||||
opt.bind_address);
|
||||
}
|
||||
else
|
||||
bind_address_resolved = 1;
|
||||
resolved = 1;
|
||||
}
|
||||
|
||||
if (al == NULL)
|
||||
{
|
||||
/* #### Is there really a need for this? Shouldn't we simply
|
||||
return 0 and have the caller use sockaddr_set_address to
|
||||
specify INADDR_ANY/in6addr_any? */
|
||||
const char *unspecified_address = "0.0.0.0";
|
||||
#ifdef ENABLE_IPV6
|
||||
if (flags & BIND_ON_IPV6_ONLY)
|
||||
@ -104,7 +106,7 @@ resolve_bind_address (int flags, ip_address *addr)
|
||||
address_list_copy_one (al, 0, addr);
|
||||
address_list_release (al);
|
||||
|
||||
return bind_address_resolved;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
struct cwt_context {
|
||||
@ -182,7 +184,7 @@ connect_to_one (ip_address *addr, unsigned short port, int silent)
|
||||
pretty_addr, port);
|
||||
}
|
||||
|
||||
/* Make an internet socket, stream type. */
|
||||
/* Create the socket of the family appropriate for the address. */
|
||||
sock = socket (sa->sa_family, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
goto out;
|
||||
@ -327,7 +329,7 @@ bindport (const ip_address *bind_address, unsigned short *port)
|
||||
msock = -1;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
if (bind_address->type == IPv6_ADDRESS)
|
||||
if (bind_address->type == IPV6_ADDRESS)
|
||||
family = AF_INET6;
|
||||
#endif
|
||||
|
||||
@ -458,30 +460,36 @@ closeport (int sock)
|
||||
int
|
||||
conaddr (int fd, ip_address *ip)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr *sa = (struct sockaddr *)&ss;
|
||||
socklen_t addrlen = sizeof (ss);
|
||||
struct sockaddr_storage storage;
|
||||
struct sockaddr *sockaddr = (struct sockaddr *)&storage;
|
||||
socklen_t addrlen = sizeof (storage);
|
||||
|
||||
if (getsockname (fd, sa, &addrlen) < 0)
|
||||
if (getsockname (fd, sockaddr, &addrlen) < 0)
|
||||
return 0;
|
||||
|
||||
switch (sa->sa_family)
|
||||
switch (sockaddr->sa_family)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
case AF_INET6:
|
||||
ip->type = IPv6_ADDRESS;
|
||||
ip->addr.ipv6.addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
|
||||
ip->type = IPV6_ADDRESS;
|
||||
ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
ip->addr.ipv6.scope_id = ((struct sockaddr_in6 *)sa)->sin6_scope_id;
|
||||
ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
|
||||
#endif
|
||||
DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
|
||||
return 1;
|
||||
DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
case AF_INET:
|
||||
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;
|
||||
{
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
|
||||
ip->type = IPV4_ADDRESS;
|
||||
ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
|
||||
DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -30,13 +30,11 @@ so, delete this exception statement from your version. */
|
||||
#ifndef CONNECT_H
|
||||
#define CONNECT_H
|
||||
|
||||
#include "host.h"
|
||||
#include "host.h" /* for definition of ip_address */
|
||||
|
||||
/* bindport flags */
|
||||
#define BIND_ON_IPV4_ONLY LH_IPv4_ONLY
|
||||
#ifdef ENABLE_IPV6
|
||||
#define BIND_ON_IPV6_ONLY LH_IPv6_ONLY
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#define BIND_ON_IPV4_ONLY LH_IPV4_ONLY
|
||||
#define BIND_ON_IPV6_ONLY LH_IPV6_ONLY
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
|
@ -260,12 +260,12 @@ ip_address_to_port_repr (const ip_address *addr, unsigned short port, char *buf,
|
||||
unsigned char *ptr;
|
||||
|
||||
assert (addr != NULL);
|
||||
assert (addr->type == IPv4_ADDRESS);
|
||||
assert (addr->type == IPV4_ADDRESS);
|
||||
assert (buf != NULL);
|
||||
/* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
|
||||
assert (buflen >= 6 * 4);
|
||||
|
||||
ptr = (unsigned char *)(&addr->addr.ipv4.addr.s_addr);
|
||||
ptr = ADDRESS_IPV4_DATA (addr);
|
||||
snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
|
||||
ptr[2], ptr[3], (unsigned) (port & 0xff00) >> 8, port & 0xff);
|
||||
buf[buflen - 1] = '\0';
|
||||
@ -292,7 +292,7 @@ ftp_port (struct rbuf *rbuf)
|
||||
if (!conaddr (RBUF_FD (rbuf), &addr))
|
||||
return BINDERR;
|
||||
|
||||
assert (addr.type == IPv4_ADDRESS);
|
||||
assert (addr.type == IPV4_ADDRESS);
|
||||
|
||||
/* Setting port to 0 lets the system choose a free port. */
|
||||
port = 0;
|
||||
@ -342,7 +342,7 @@ ip_address_to_lprt_repr (const ip_address *addr, unsigned short port, char *buf,
|
||||
unsigned char *ptr;
|
||||
|
||||
assert (addr != NULL);
|
||||
assert (addr->type == IPv4_ADDRESS || addr->type == IPv6_ADDRESS);
|
||||
assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
|
||||
assert (buf != NULL);
|
||||
/* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
|
||||
assert (buflen >= 21 * 4);
|
||||
@ -350,15 +350,15 @@ ip_address_to_lprt_repr (const ip_address *addr, unsigned short port, char *buf,
|
||||
/* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
|
||||
switch (addr->type)
|
||||
{
|
||||
case IPv4_ADDRESS:
|
||||
ptr = (unsigned char *)(&addr->addr.ipv4.addr);
|
||||
case IPV4_ADDRESS:
|
||||
ptr = ADDRESS_IPV4_DATA (addr);
|
||||
snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], 2,
|
||||
(unsigned) (port & 0xff00) >> 8, port & 0xff);
|
||||
buf[buflen - 1] = '\0';
|
||||
break;
|
||||
case IPv6_ADDRESS:
|
||||
ptr = (unsigned char *)(&addr->addr.ipv6.addr);
|
||||
case IPV6_ADDRESS:
|
||||
ptr = ADDRESS_IPV6_DATA (addr);
|
||||
snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7],
|
||||
ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2,
|
||||
@ -389,7 +389,7 @@ ftp_lprt (struct rbuf *rbuf)
|
||||
if (!conaddr (RBUF_FD (rbuf), &addr))
|
||||
return BINDERR;
|
||||
|
||||
assert (addr.type == IPv4_ADDRESS || addr.type == IPv6_ADDRESS);
|
||||
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
|
||||
|
||||
/* Setting port to 0 lets the system choose a free port. */
|
||||
port = 0;
|
||||
@ -437,7 +437,7 @@ ip_address_to_eprt_repr (const ip_address *addr, unsigned short port, char *buf,
|
||||
int afnum;
|
||||
|
||||
assert (addr != NULL);
|
||||
assert (addr->type == IPv4_ADDRESS || addr->type == IPv6_ADDRESS);
|
||||
assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
|
||||
assert (buf != NULL);
|
||||
/* buf must contain the argument of EPRT (of the form |af|addr|port|).
|
||||
* 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr
|
||||
@ -445,7 +445,7 @@ ip_address_to_eprt_repr (const ip_address *addr, unsigned short port, char *buf,
|
||||
assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5);
|
||||
|
||||
/* Construct the argument of EPRT (of the form |af|addr|port|). */
|
||||
afnum = (addr->type == IPv4_ADDRESS ? 1 : 2);
|
||||
afnum = (addr->type == IPV4_ADDRESS ? 1 : 2);
|
||||
snprintf (buf, buflen, "|%d|%s|%d|", afnum, pretty_print_address (addr), port);
|
||||
buf[buflen - 1] = '\0';
|
||||
}
|
||||
@ -473,7 +473,7 @@ ftp_eprt (struct rbuf *rbuf)
|
||||
if (!conaddr (RBUF_FD (rbuf), &addr))
|
||||
return BINDERR;
|
||||
|
||||
assert (addr.type == IPv4_ADDRESS || addr.type == IPv6_ADDRESS);
|
||||
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
|
||||
|
||||
/* Setting port to 0 lets the system choose a free port. */
|
||||
port = 0;
|
||||
@ -527,7 +527,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
|
||||
unsigned char tmp[6];
|
||||
|
||||
assert (rbuf != NULL);
|
||||
assert (rbuf_initialized_p(rbuf));
|
||||
assert (rbuf_initialized_p (rbuf));
|
||||
assert (addr != NULL);
|
||||
assert (port != NULL);
|
||||
|
||||
@ -576,9 +576,8 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
|
||||
}
|
||||
xfree (respline);
|
||||
|
||||
addr->type = IPv4_ADDRESS;
|
||||
/* Mauro Tortonesi: is this safe and/or elegant enough? */
|
||||
memcpy (&addr->addr.ipv4.addr, tmp, 4);
|
||||
addr->type = IPV4_ADDRESS;
|
||||
memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
|
||||
*port = ((tmp[4] << 8) & 0xff00) + tmp[5];
|
||||
|
||||
return FTPOK;
|
||||
@ -727,8 +726,8 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
|
||||
|
||||
if (af == 4)
|
||||
{
|
||||
addr->type = IPv4_ADDRESS;
|
||||
memcpy (&addr->addr.ipv4.addr, tmp, 4);
|
||||
addr->type = IPV4_ADDRESS;
|
||||
memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
|
||||
*port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
|
||||
DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
|
||||
DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
|
||||
@ -738,8 +737,8 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
|
||||
else
|
||||
{
|
||||
assert (af == 6);
|
||||
addr->type = IPv6_ADDRESS;
|
||||
memcpy (&addr->addr.ipv6.addr, tmp, 16);
|
||||
addr->type = IPV6_ADDRESS;
|
||||
memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
|
||||
*port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
|
||||
DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
|
||||
DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
|
||||
|
@ -1242,7 +1242,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
|
||||
case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
|
||||
case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
|
||||
/* Fatal errors, give up. */
|
||||
return err;
|
||||
|
178
src/host.c
178
src/host.c
@ -114,7 +114,8 @@ address_list_get_bounds (const struct address_list *al, int *start, int *end)
|
||||
/* Copy address number INDEX to IP_STORE. */
|
||||
|
||||
void
|
||||
address_list_copy_one (const struct address_list *al, int index, ip_address *ip_store)
|
||||
address_list_copy_one (const struct address_list *al, int index,
|
||||
ip_address *ip_store)
|
||||
{
|
||||
assert (index >= al->faulty && index < al->count);
|
||||
memcpy (ip_store, al->addresses + index, sizeof (ip_address));
|
||||
@ -123,43 +124,57 @@ address_list_copy_one (const struct address_list *al, int index, ip_address *ip_
|
||||
/* Check whether two address lists have all their IPs in common. */
|
||||
|
||||
int
|
||||
address_list_match_all (const struct address_list *al1, const struct address_list *al2)
|
||||
address_list_match_all (const struct address_list *al1,
|
||||
const struct address_list *al2)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
int i;
|
||||
#endif
|
||||
if (al1 == al2)
|
||||
return 1;
|
||||
if (al1->count != al2->count)
|
||||
return 0;
|
||||
|
||||
/* For the comparison to be complete, we'd need to sort the IP
|
||||
addresses first. But that's not necessary because this is only
|
||||
used as an optimization. */
|
||||
|
||||
#ifndef ENABLE_IPV6
|
||||
/* In the non-IPv6 case, there is only one address type, so we can
|
||||
compare the whole array with memcmp. */
|
||||
return 0 == memcmp (al1->addresses, al2->addresses,
|
||||
al1->count * sizeof (ip_address));
|
||||
#else /* ENABLE_IPV6 */
|
||||
for (i = 0; i < al1->count; ++i)
|
||||
{
|
||||
#ifdef ENABLE_IPv6
|
||||
if (al1->addresses[i].type != al2->addresses[i].type)
|
||||
const ip_address *ip1 = &al1->addresses[i];
|
||||
const ip_address *ip2 = &al2->addresses[i];
|
||||
|
||||
if (ip1->type != ip2->type)
|
||||
return 0;
|
||||
if (al1->addresses[i].type == IPv6_ADDRESS)
|
||||
{
|
||||
const struct in6_addr *addr1 = &al1->addresses[i].addr.ipv6.addr;
|
||||
const struct in6_addr *addr2 = &al2->addresses[i].addr.ipv6.addr;
|
||||
|
||||
switch (ip1->type)
|
||||
{
|
||||
case IPV4_ADDRESS:
|
||||
if (ADDRESS_IPV4_IN_ADDR (ip1).s_addr
|
||||
!= ADDRESS_IPV4_IN_ADDR (ip2).s_addr)
|
||||
return 0;
|
||||
break;
|
||||
case IPV6_ADDRESS:
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
if ((al1->addresses[i].address.scope_id
|
||||
!= al2->addresses[i].address.scope_id)
|
||||
|| !IN6_ARE_ADDR_EQUAL (addr1, addr2))
|
||||
#else
|
||||
if (!IN6_ARE_ADDR_EQUAL (addr1, addr2))
|
||||
#endif
|
||||
if (ADDRESS_IPV6_SCOPE (ip1) != ADDRESS_IPV6_SCOPE (ip2))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
const struct in_addr *addr1 = (const struct in_addr *)&al1->addresses[i].addr.ipv4.addr;
|
||||
const struct in_addr *addr2 = (const struct in_addr *)&al2->addresses[i].addr.ipv4.addr;
|
||||
|
||||
if (addr1->s_addr != addr2->s_addr)
|
||||
#endif /* HAVE_SOCKADDR_IN6_SCOPE_ID */
|
||||
if (!IN6_ARE_ADDR_EQUAL (&ADDRESS_IPV6_IN6_ADDR (ip1),
|
||||
&ADDRESS_IPV6_IN6_ADDR (ip2)))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#endif /* ENABLE_IPV6 */
|
||||
}
|
||||
|
||||
/* Mark the INDEXth element of AL as faulty, so that the next time
|
||||
@ -199,9 +214,10 @@ address_list_from_addrinfo (const struct addrinfo *ai)
|
||||
{
|
||||
struct address_list *al;
|
||||
const struct addrinfo *ptr;
|
||||
int cnt = 0;
|
||||
int i;
|
||||
int cnt;
|
||||
ip_address *ip;
|
||||
|
||||
cnt = 0;
|
||||
for (ptr = ai; ptr != NULL ; ptr = ptr->ai_next)
|
||||
if (ptr->ai_family == AF_INET || ptr->ai_family == AF_INET6)
|
||||
++cnt;
|
||||
@ -214,27 +230,28 @@ address_list_from_addrinfo (const struct addrinfo *ai)
|
||||
al->faulty = 0;
|
||||
al->refcount = 1;
|
||||
|
||||
for (i = 0, ptr = ai; ptr != NULL; ptr = ptr->ai_next)
|
||||
ip = al->addresses;
|
||||
for (ptr = ai; ptr != NULL; ptr = ptr->ai_next)
|
||||
if (ptr->ai_family == AF_INET6)
|
||||
{
|
||||
const struct sockaddr_in6 *sin6 =
|
||||
(const struct sockaddr_in6 *)ptr->ai_addr;
|
||||
al->addresses[i].addr.ipv6.addr = sin6->sin6_addr;
|
||||
al->addresses[i].type = IPv6_ADDRESS;
|
||||
ip->type = IPV6_ADDRESS;
|
||||
ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
al->addresses[i].addr.ipv6.scope_id = sin6->sin6_scope_id;
|
||||
ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
|
||||
#endif
|
||||
++i;
|
||||
++ip;
|
||||
}
|
||||
else if (ptr->ai_family == AF_INET)
|
||||
{
|
||||
const struct sockaddr_in *sin =
|
||||
(const struct sockaddr_in *)ptr->ai_addr;
|
||||
al->addresses[i].addr.ipv4.addr = sin->sin_addr;
|
||||
al->addresses[i].type = IPv4_ADDRESS;
|
||||
++i;
|
||||
ip->type = IPV4_ADDRESS;
|
||||
ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
|
||||
++ip;
|
||||
}
|
||||
assert (i == cnt);
|
||||
assert (ip - al->addresses == cnt);
|
||||
return al;
|
||||
}
|
||||
#else
|
||||
@ -243,23 +260,25 @@ address_list_from_addrinfo (const struct addrinfo *ai)
|
||||
static struct address_list *
|
||||
address_list_from_vector (char **h_addr_list)
|
||||
{
|
||||
int count = 0, i;
|
||||
|
||||
int count, i;
|
||||
struct address_list *al = xmalloc (sizeof (struct address_list));
|
||||
|
||||
count = 0;
|
||||
while (h_addr_list[count])
|
||||
++count;
|
||||
assert (count > 0);
|
||||
|
||||
al->count = count;
|
||||
al->faulty = 0;
|
||||
al->addresses = xmalloc (count * sizeof (ip_address));
|
||||
al->refcount = 1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Mauro Tortonesi: is this safe? */
|
||||
memcpy (&((al->addresses + i)->addr.ipv4.addr.s_addr), h_addr_list[i], 4);
|
||||
(al->addresses + i)->type = IPv4_ADDRESS;
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ip_address *ip = &al->addresses[i];
|
||||
ip->type = IPV4_ADDRESS;
|
||||
memcpy (ADDRESS_IPV4_DATA (ip), h_addr_list[i], 4);
|
||||
}
|
||||
|
||||
return al;
|
||||
}
|
||||
@ -323,7 +342,7 @@ void
|
||||
sockaddr_set_address (struct sockaddr *sa, unsigned short port,
|
||||
const ip_address *addr)
|
||||
{
|
||||
if (addr->type == IPv4_ADDRESS)
|
||||
if (addr->type == IPV4_ADDRESS)
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
|
||||
@ -332,22 +351,29 @@ sockaddr_set_address (struct sockaddr *sa, unsigned short port,
|
||||
if (addr == NULL)
|
||||
sin->sin_addr.s_addr = INADDR_ANY;
|
||||
else
|
||||
sin->sin_addr = addr->addr.ipv4.addr;
|
||||
sin->sin_addr = ADDRESS_IPV4_IN_ADDR (addr);
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
else if (addr->type == IPv6_ADDRESS)
|
||||
else if (addr->type == IPV6_ADDRESS)
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons (port);
|
||||
/* #### How can ADDR be NULL? We have dereferenced it above by
|
||||
accessing addr->type! */
|
||||
if (addr == NULL)
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
{
|
||||
sin6->sin6_addr = in6addr_any;
|
||||
/* #### Should we set the scope_id here? */
|
||||
}
|
||||
else
|
||||
sin6->sin6_addr = addr->addr.ipv6.addr;
|
||||
{
|
||||
sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (addr);
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
sin6->sin6_scope_id = addr->addr.ipv6.scope_id;
|
||||
#endif /* HAVE_SOCKADDR_IN6_SCOPE_ID */
|
||||
sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (addr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
else
|
||||
@ -362,8 +388,8 @@ sockaddr_get_address (const struct sockaddr *sa, unsigned short *port,
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
|
||||
addr->type = IPv4_ADDRESS;
|
||||
addr->addr.ipv4.addr = sin->sin_addr;
|
||||
addr->type = IPV4_ADDRESS;
|
||||
ADDRESS_IPV4_IN_ADDR (addr) = sin->sin_addr;
|
||||
if (port != NULL)
|
||||
*port = ntohs (sin->sin_port);
|
||||
}
|
||||
@ -372,10 +398,10 @@ sockaddr_get_address (const struct sockaddr *sa, unsigned short *port,
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
|
||||
|
||||
addr->type = IPv6_ADDRESS;
|
||||
addr->addr.ipv6.addr = sin6->sin6_addr;
|
||||
addr->type = IPV6_ADDRESS;
|
||||
ADDRESS_IPV6_IN6_ADDR (addr) = sin6->sin6_addr;
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
addr->addr.ipv6.scope_id = sin6->sin6_scope_id;
|
||||
ADDRESS_IPV6_SCOPE (addr) = sin6->sin6_scope_id;
|
||||
#endif
|
||||
if (port != NULL)
|
||||
*port = ntohs (sin6->sin6_port);
|
||||
@ -578,21 +604,23 @@ pretty_print_address (const ip_address *addr)
|
||||
{
|
||||
switch (addr->type)
|
||||
{
|
||||
case IPv4_ADDRESS:
|
||||
return inet_ntoa (addr->addr.ipv4.addr);
|
||||
case IPV4_ADDRESS:
|
||||
return inet_ntoa (ADDRESS_IPV4_IN_ADDR (addr));
|
||||
#ifdef ENABLE_IPV6
|
||||
case IPv6_ADDRESS:
|
||||
case IPV6_ADDRESS:
|
||||
{
|
||||
int len;
|
||||
static char buf[128];
|
||||
inet_ntop (AF_INET6, &addr->addr.ipv6.addr, buf, sizeof (buf));
|
||||
inet_ntop (AF_INET6, &ADDRESS_IPV6_IN6_ADDR (addr), buf, sizeof (buf));
|
||||
#if 0
|
||||
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
/* print also scope_id for all ?non-global? addresses */
|
||||
snprintf (buf + len, sizeof (buf) - len, "%%%d", addr->addr.ipv6.scope_id);
|
||||
{
|
||||
/* append "%SCOPE_ID" for all ?non-global? addresses */
|
||||
char *p = buf + strlen (buf);
|
||||
*p++ = '%';
|
||||
number_to_string (p, ADDRESS_IPV6_SCOPE (addr));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
len = strlen (buf);
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
@ -636,20 +664,23 @@ lookup_host (const char *host, int flags)
|
||||
int err, family;
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
/* This ip_default_family+flags business looks like bad design to
|
||||
me. This function should rather accept a FAMILY argument. */
|
||||
if (flags & LH_IPv4_ONLY)
|
||||
/* Is this necessary? Should this function be changed to accept a
|
||||
FAMILY argument? */
|
||||
if (flags & LH_IPV4_ONLY)
|
||||
family = AF_INET;
|
||||
else if (flags & LH_IPv6_ONLY)
|
||||
else if (flags & LH_IPV6_ONLY)
|
||||
family = AF_INET6;
|
||||
else
|
||||
family = ip_default_family;
|
||||
#endif
|
||||
|
||||
/* First, try to check whether the address is already a numeric
|
||||
address. Where getaddrinfo is available, we do it using the
|
||||
AI_NUMERICHOST flag. Without IPv6, we check whether inet_addr
|
||||
succeeds. */
|
||||
address, in which case we don't need to cache it or bother with
|
||||
setting up timeouts. Plus, if memory serves me right, Ultrix's
|
||||
gethostbyname can't handle numeric addresses (!).
|
||||
|
||||
Where getaddrinfo is available, we do it using the AI_NUMERICHOST
|
||||
flag. Without IPv6, we use inet_addr succeeds. */
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
@ -675,14 +706,11 @@ lookup_host (const char *host, int flags)
|
||||
if (addr_ipv4 != (uint32_t) -1)
|
||||
{
|
||||
/* The return value of inet_addr is in network byte order, so
|
||||
we can just copy it to ADDR. */
|
||||
ip_address addr;
|
||||
/* This has a huge number of dereferences because C doesn't
|
||||
support anonymous unions and because struct in_addr adds a
|
||||
cast. */
|
||||
addr.addr.ipv4.addr.s_addr = addr_ipv4;
|
||||
addr.type = IPv4_ADDRESS;
|
||||
return address_list_from_single (&addr);
|
||||
we can just copy it to IP. */
|
||||
ip_address ip;
|
||||
ip.type = IPV4_ADDRESS;
|
||||
memcpy (ADDRESS_IPV4_DATA (&ip), &addr_ipv4, 4);
|
||||
return address_list_from_single (&ip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
36
src/host.h
36
src/host.h
@ -46,13 +46,19 @@ struct address_list;
|
||||
|
||||
extern int ip_default_family; /* defined in host.c */
|
||||
|
||||
/* This struct defines an IP address, tagged with family type. */
|
||||
|
||||
typedef struct {
|
||||
/* Address type. */
|
||||
enum {
|
||||
IPv4_ADDRESS,
|
||||
IPV4_ADDRESS,
|
||||
#ifdef ENABLE_IPV6
|
||||
IPv6_ADDRESS
|
||||
IPV6_ADDRESS
|
||||
#endif /* ENABLE_IPV6 */
|
||||
} type;
|
||||
|
||||
/* Address data union: ipv6 contains IPv6-related data (address and
|
||||
scope), and ipv4 contains IPv4 address. */
|
||||
union {
|
||||
#ifdef ENABLE_IPV6
|
||||
struct {
|
||||
@ -65,24 +71,30 @@ typedef struct {
|
||||
struct {
|
||||
struct in_addr addr;
|
||||
} ipv4;
|
||||
} addr;
|
||||
} u;
|
||||
} ip_address;
|
||||
|
||||
/* Because C doesn't support anonymous unions, access to ip_address
|
||||
elements is clunky. Hence the accessors. */
|
||||
|
||||
#define ADDRESS_IPV6_IN6_ADDR(x) ((x)->u.ipv6.addr)
|
||||
#define ADDRESS_IPV6_DATA(x) ((void *)&(x)->u.ipv6.addr.s6_addr)
|
||||
#define ADDRESS_IPV6_SCOPE(x) ((x)->u.ipv6.scope_id)
|
||||
|
||||
#define ADDRESS_IPV4_IN_ADDR(x) ((x)->u.ipv4.addr)
|
||||
#define ADDRESS_IPV4_DATA(x) ((void *)&(x)->u.ipv4.addr.s_addr)
|
||||
|
||||
#ifndef ENABLE_IPV6
|
||||
|
||||
#ifndef HAVE_SOCKADDR_STORAGE
|
||||
#define sockaddr_storage sockaddr_in
|
||||
#endif
|
||||
|
||||
# ifndef HAVE_SOCKADDR_STORAGE
|
||||
# define sockaddr_storage sockaddr_in
|
||||
# endif
|
||||
#endif /* ENABLE_IPV6 */
|
||||
|
||||
/* Flags for lookup_host */
|
||||
#define LH_SILENT 0x0001
|
||||
#define LH_PASSIVE 0x0002
|
||||
#define LH_IPv4_ONLY 0x0004
|
||||
#ifdef ENABLE_IPV6
|
||||
#define LH_IPv6_ONLY 0x0008
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#define LH_IPV4_ONLY 0x0004
|
||||
#define LH_IPV6_ONLY 0x0008
|
||||
|
||||
/* Function declarations */
|
||||
struct address_list *lookup_host PARAMS ((const char *, int));
|
||||
|
@ -1789,7 +1789,7 @@ File `%s' already there, will not retrieve.\n"), *hstat.local_file);
|
||||
printwhat (count, opt.ntry);
|
||||
continue;
|
||||
break;
|
||||
case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED:
|
||||
case HOSTERR: case CONIMPOSSIBLE: case PROXERR: case AUTHFAILED:
|
||||
case SSLERRCTXCREATE: case CONTNOTSUPPORTED:
|
||||
/* Fatal errors just return from the function. */
|
||||
free_hstat (&hstat);
|
||||
|
14
src/wget.h
14
src/wget.h
@ -276,7 +276,7 @@ enum
|
||||
typedef enum
|
||||
{
|
||||
NOCONERROR, HOSTERR, CONSOCKERR, CONERROR, CONSSLERR,
|
||||
CONREFUSED, NEWLOCATION, NOTENOUGHMEM, CONPORTERR,
|
||||
CONIMPOSSIBLE, NEWLOCATION, NOTENOUGHMEM, CONPORTERR,
|
||||
BINDERR, BINDOK, LISTENERR, ACCEPTERR, ACCEPTOK,
|
||||
CONCLOSED, FTPOK, FTPLOGINC, FTPLOGREFUSED, FTPPORTERR,
|
||||
FTPNSFOD, FTPRETROK, FTPUNKNOWNTYPE, FTPRERR,
|
||||
@ -310,7 +310,15 @@ typedef unsigned char boolean;
|
||||
retrieve the requisites of a single document. */
|
||||
#define INFINITE_RECURSION -1
|
||||
|
||||
#define CONNECT_ERROR(x) ((x) == ECONNREFUSED && !opt.retry_connrefused \
|
||||
? CONREFUSED : CONERROR)
|
||||
/* In case old systems don't have EAFNOSUPPORT, which we use below. */
|
||||
#ifndef EAFNOSUPPORT
|
||||
# define EAFNOSUPPORT EINVAL
|
||||
#endif
|
||||
|
||||
#define CONNECT_ERROR(err) (( (err) == EAFNOSUPPORT \
|
||||
|| (err) == EINVAL \
|
||||
|| ((err) == ECONNREFUSED \
|
||||
&& !opt.retry_connrefused)) \
|
||||
? CONIMPOSSIBLE : CONERROR)
|
||||
|
||||
#endif /* WGET_H */
|
||||
|
Loading…
Reference in New Issue
Block a user