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