1
0
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:
hniksic 2003-10-29 15:13:25 -08:00
parent 8c19243974
commit 6f1250b1c6
9 changed files with 203 additions and 141 deletions

View File

@ -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

View File

@ -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 ();
}

View File

@ -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 */

View File

@ -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]));

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -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 */