1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Simplify the ip_address data union. Always use inet_ntop for printing

IP addresses when IPv6 is enabled.
This commit is contained in:
hniksic 2005-08-10 06:50:08 -07:00
parent 254ed12b8f
commit 481443d337
6 changed files with 102 additions and 136 deletions

View File

@ -1,3 +1,10 @@
2005-08-10 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (print_address): Always use inet_ntop when IPv6 is
enabled.
* host.h (ip_address): Simplify the data union.
2005-08-09 Hrvoje Niksic <hniksic@xemacs.org>
* mswindows.c (inet_ntop): Also handle IPv4 addresses for

View File

@ -73,27 +73,27 @@ so, delete this exception statement from your version. */
static void
sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
{
switch (ip->type)
switch (ip->family)
{
case IPV4_ADDRESS:
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
xzero (*sin);
sin->sin_family = AF_INET;
sin->sin_port = htons (port);
sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
sin->sin_addr = ip->data.d4;
break;
}
#ifdef ENABLE_IPV6
case IPV6_ADDRESS:
case AF_INET6:
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
xzero (*sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons (port);
sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
sin6->sin6_addr = ip->data.d6;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
sin6->sin6_scope_id = ip->ipv6_scope;
#endif
break;
}
@ -117,8 +117,8 @@ sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (ip)
{
ip->type = IPV4_ADDRESS;
ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
ip->family = AF_INET;
ip->data.d4 = sin->sin_addr;
}
if (port)
*port = ntohs (sin->sin_port);
@ -130,10 +130,10 @@ sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (ip)
{
ip->type = IPV6_ADDRESS;
ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
ip->family = AF_INET6;
ip->data.d6 = sin6->sin6_addr;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
ip->ipv6_scope = sin6->sin6_scope_id;
#endif
}
if (port)
@ -415,7 +415,6 @@ int
bind_local (const ip_address *bind_address, int *port)
{
int sock;
int family = AF_INET;
struct sockaddr_storage ss;
struct sockaddr *sa = (struct sockaddr *)&ss;
@ -424,12 +423,7 @@ bind_local (const ip_address *bind_address, int *port)
void *setopt_ptr = (void *)&setopt_val;
socklen_t setopt_size = sizeof (setopt_val);
#ifdef ENABLE_IPV6
if (bind_address->type == IPV6_ADDRESS)
family = AF_INET6;
#endif
sock = socket (family, SOCK_STREAM, 0);
sock = socket (bind_address->family, SOCK_STREAM, 0);
if (sock < 0)
return -1;
@ -529,16 +523,16 @@ socket_ip_address (int sock, ip_address *ip, int endpoint)
if (ret < 0)
return false;
ip->family = sockaddr->sa_family;
switch (sockaddr->sa_family)
{
#ifdef ENABLE_IPV6
case AF_INET6:
{
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
ip->type = IPV6_ADDRESS;
ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
ip->data.d6 = sa6->sin6_addr;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
ip->ipv6_scope = sa6->sin6_scope_id;
#endif
DEBUGP (("conaddr is: %s\n", print_address (ip)));
return true;
@ -547,8 +541,7 @@ socket_ip_address (int sock, ip_address *ip, int endpoint)
case AF_INET:
{
struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
ip->type = IPV4_ADDRESS;
ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
ip->data.d4 = sa->sin_addr;
DEBUGP (("conaddr is: %s\n", print_address (ip)));
return true;
}

View File

@ -250,13 +250,11 @@ ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
{
unsigned char *ptr;
assert (addr != NULL);
assert (addr->type == IPV4_ADDRESS);
assert (buf != NULL);
assert (addr->family == AF_INET);
/* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
assert (buflen >= 6 * 4);
ptr = ADDRESS_IPV4_DATA (addr);
ptr = IP_INADDR_DATA (addr);
snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
buf[buflen - 1] = '\0';
@ -280,7 +278,7 @@ ftp_port (int csock, int *local_sock)
if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS);
assert (addr.family == AF_INET);
/* Setting port to 0 lets the system choose a free port. */
port = 0;
@ -326,32 +324,29 @@ static void
ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf,
size_t buflen)
{
unsigned char *ptr;
unsigned char *ptr = IP_INADDR_DATA (addr);
assert (addr != NULL);
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);
/* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
switch (addr->type)
switch (addr->family)
{
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,
(port & 0xff00) >> 8, port & 0xff);
buf[buflen - 1] = '\0';
break;
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,
(port & 0xff00) >> 8, port & 0xff);
buf[buflen - 1] = '\0';
break;
case AF_INET:
snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4,
ptr[0], ptr[1], ptr[2], ptr[3], 2,
(port & 0xff00) >> 8, port & 0xff);
break;
case AF_INET6:
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, (port & 0xff00) >> 8, port & 0xff);
break;
default:
abort ();
}
}
@ -373,7 +368,7 @@ ftp_lprt (int csock, int *local_sock)
if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
return FTPSYSERR;
assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
assert (addr.family == AF_INET || addr.family == AF_INET6);
/* Setting port to 0 lets the system choose a free port. */
port = 0;
@ -425,7 +420,7 @@ ip_address_to_eprt_repr (const ip_address *addr, int 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->family == AF_INET ? 1 : 2);
snprintf (buf, buflen, "|%d|%s|%d|", afnum, print_address (addr), port);
buf[buflen - 1] = '\0';
}
@ -546,8 +541,8 @@ ftp_pasv (int csock, ip_address *addr, int *port)
}
xfree (respline);
addr->type = IPV4_ADDRESS;
memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
addr->family = AF_INET;
memcpy (IP_INADDR_DATA (addr), tmp, 4);
*port = ((tmp[4] << 8) & 0xff00) + tmp[5];
return FTPOK;
@ -692,8 +687,8 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
if (af == 4)
{
addr->type = IPV4_ADDRESS;
memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
addr->family = AF_INET;
memcpy (IP_INADDR_DATA (addr), tmp, 4);
*port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@ -703,8 +698,8 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
else
{
assert (af == 6);
addr->type = IPV6_ADDRESS;
memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
addr->family = AF_INET6;
memcpy (IP_INADDR_DATA (addr), tmp, 16);
*port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@ -735,7 +730,7 @@ ftp_epsv (int csock, ip_address *ip, int *port)
/* Form the request. */
/* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
request = ftp_request ("EPSV", (ip->family == AF_INET ? "1" : "2"));
/* And send it. */
nwritten = fd_write (csock, request, strlen (request), -1);

View File

@ -116,14 +116,14 @@ ftp_do_pasv (int csock, ip_address *addr, int *port)
/* If our control connection is over IPv6, then we first try EPSV and then
* LPSV if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PASV request. */
switch (addr->type)
switch (addr->family)
{
case IPV4_ADDRESS:
case AF_INET:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PASV ... ");
err = ftp_pasv (csock, addr, port);
break;
case IPV6_ADDRESS:
case AF_INET6:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPSV ... ");
err = ftp_epsv (csock, addr, port);
@ -159,14 +159,14 @@ ftp_do_port (int csock, int *local_sock)
/* If our control connection is over IPv6, then we first try EPRT and then
* LPRT if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PORT request. */
switch (cip.type)
switch (cip.family)
{
case IPV4_ADDRESS:
case AF_INET:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PORT ... ");
err = ftp_port (csock, local_sock);
break;
case IPV6_ADDRESS:
case AF_INET6:
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> EPRT ... ");
err = ftp_eprt (csock, local_sock);

View File

@ -98,30 +98,27 @@ bool
address_list_contains (const struct address_list *al, const ip_address *ip)
{
int i;
switch (ip->type)
switch (ip->family)
{
case IPV4_ADDRESS:
case AF_INET:
for (i = 0; i < al->count; i++)
{
ip_address *cur = al->addresses + i;
if (cur->type == IPV4_ADDRESS
&& (ADDRESS_IPV4_IN_ADDR (cur).s_addr
==
ADDRESS_IPV4_IN_ADDR (ip).s_addr))
if (cur->family == AF_INET
&& (cur->data.d4.s_addr == ip->data.d4.s_addr))
return true;
}
return false;
#ifdef ENABLE_IPV6
case IPV6_ADDRESS:
case AF_INET6:
for (i = 0; i < al->count; i++)
{
ip_address *cur = al->addresses + i;
if (cur->type == IPV6_ADDRESS
if (cur->family == AF_INET6
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
&& ADDRESS_IPV6_SCOPE (cur) == ADDRESS_IPV6_SCOPE (ip)
&& cur->ipv6_scope == ip->ipv6_scope
#endif
&& IN6_ARE_ADDR_EQUAL (&ADDRESS_IPV6_IN6_ADDR (cur),
&ADDRESS_IPV6_IN6_ADDR (ip)))
&& IN6_ARE_ADDR_EQUAL (&cur->data.d6, &ip->data.d6))
return true;
}
return false;
@ -199,10 +196,10 @@ address_list_from_addrinfo (const struct addrinfo *ai)
{
const struct sockaddr_in6 *sin6 =
(const struct sockaddr_in6 *)ptr->ai_addr;
ip->type = IPV6_ADDRESS;
ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
ip->family = AF_INET6;
ip->data.d6 = sin6->sin6_addr;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
ip->ipv6_scope = sin6->sin6_scope_id;
#endif
++ip;
}
@ -210,17 +207,17 @@ address_list_from_addrinfo (const struct addrinfo *ai)
{
const struct sockaddr_in *sin =
(const struct sockaddr_in *)ptr->ai_addr;
ip->type = IPV4_ADDRESS;
ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
ip->family = AF_INET;
ip->data.d4 = sin->sin_addr;
++ip;
}
assert (ip - al->addresses == cnt);
return al;
}
#define IS_IPV4(addr) (((const ip_address *) addr)->type == IPV4_ADDRESS)
#define IS_IPV4(addr) (((const ip_address *) addr)->family == AF_INET)
/* Compare two IP addresses by type, giving preference to the IPv4
/* Compare two IP addresses by family, giving preference to the IPv4
address (sorting it first). In other words, return -1 if ADDR1 is
IPv4 and ADDR2 is IPv6, +1 if ADDR1 is IPv6 and ADDR2 is IPv4, and
0 otherwise.
@ -234,7 +231,7 @@ cmp_prefer_ipv4 (const void *addr1, const void *addr2)
return !IS_IPV4 (addr1) - !IS_IPV4 (addr2);
}
#define IS_IPV6(addr) (((const ip_address *) addr)->type == IPV6_ADDRESS)
#define IS_IPV6(addr) (((const ip_address *) addr)->family == AF_INET6)
/* Like the above, but give preference to the IPv6 address. */
@ -267,7 +264,7 @@ address_list_from_ipv4_addresses (char **vec)
for (i = 0; i < count; i++)
{
ip_address *ip = &al->addresses[i];
ip->type = IPV4_ADDRESS;
ip->family = AF_INET;
memcpy (ADDRESS_IPV4_DATA (ip), vec[i], 4);
}
@ -406,26 +403,18 @@ getaddrinfo_with_timeout (const char *node, const char *service,
const char *
print_address (const ip_address *addr)
{
switch (addr->type)
{
case IPV4_ADDRESS:
return inet_ntoa (ADDRESS_IPV4_IN_ADDR (addr));
#ifdef ENABLE_IPV6
case IPV6_ADDRESS:
{
static char buf[64];
if (!inet_ntop (AF_INET6, &ADDRESS_IPV6_IN6_ADDR (addr),
buf, sizeof (buf)))
snprintf (buf, sizeof buf, "<error: %s>", strerror (errno));
buf[sizeof (buf) - 1] = '\0';
return buf;
}
static char buf[64];
if (!inet_ntop (addr->family, IP_INADDR_DATA (addr), buf, sizeof buf))
snprintf (buf, sizeof buf, "<error: %s>", strerror (errno));
return buf;
#else
return inet_ntoa (addr->data.d4);
#endif
}
abort ();
}
/* The following two functions were adapted from glibc. */
/* The following two functions were adapted from glibc's
implementation of inet_pton, written by Paul Vixie. */
static bool
is_valid_ipv4_address (const char *str, const char *end)

View File

@ -47,48 +47,30 @@ struct address_list;
/* This struct defines an IP address, tagged with family type. */
typedef struct {
/* Address type. */
enum {
IPV4_ADDRESS
#ifdef ENABLE_IPV6
, IPV6_ADDRESS
#endif /* ENABLE_IPV6 */
} type;
/* Address family, one of AF_INET or AF_INET6. */
int family;
/* Address data union: ipv6 contains IPv6-related data (address and
scope), and ipv4 contains the IPv4 address. */
/* The actual data, in the form of struct in_addr or in6_addr: */
union {
struct in_addr d4; /* IPv4 address */
#ifdef ENABLE_IPV6
struct {
struct in6_addr addr;
# ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
unsigned int scope_id;
# endif
} ipv6;
#endif /* ENABLE_IPV6 */
struct {
struct in_addr addr;
} ipv4;
} u;
struct in6_addr d6; /* IPv6 address */
#endif
} data;
/* Under IPv6 getaddrinfo also returns scope_id. Since it's
IPv6-specific it strictly belongs in the above union, but we put
it here for simplicity. */
#if defined ENABLE_IPV6 && defined HAVE_SOCKADDR_IN6_SCOPE_ID
int ipv6_scope;
#endif
} ip_address;
/* Because C doesn't support anonymous unions, access to ip_address
elements is unwieldy. Hence the accessors.
The _ADDR accessors return the address as the struct in_addr or
in6_addr. The _DATA accessor returns a pointer to the address data
-- pretty much the same as the above, but cast to void*. The
_SCOPE accessor returns the address's scope_id, and makes sense
only when IPv6 and HAVE_SOCKADDR_IN6_SCOPE_ID are both defined. */
#define ADDRESS_IPV4_IN_ADDR(x) ((x)->u.ipv4.addr)
/* Don't use &x->u.ipv4.addr.s_addr because it can be #defined to a
bitfield, which you can't take an address of. */
#define ADDRESS_IPV4_DATA(x) ((void *)&(x)->u.ipv4.addr)
#define ADDRESS_IPV6_IN6_ADDR(x) ((x)->u.ipv6.addr)
#define ADDRESS_IPV6_DATA(x) ((void *)&(x)->u.ipv6.addr)
#define ADDRESS_IPV6_SCOPE(x) ((x)->u.ipv6.scope_id)
/* IP_INADDR_DATA macro returns a void pointer that can be interpreted
as a pointer to struct in_addr in IPv4 context or a pointer to
struct in6_addr in IPv4 context. This pointer can be passed to
functions that work on either, such as inet_ntop. */
#define IP_INADDR_DATA(x) ((void *) &(x)->data)
enum {
LH_SILENT = 1,