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:
parent
254ed12b8f
commit
481443d337
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
12
src/ftp.c
12
src/ftp.c
@ -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);
|
||||
|
61
src/host.c
61
src/host.c
@ -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)
|
||||
|
56
src/host.h
56
src/host.h
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user