* net.cc (ga_dup): New function, taken from ga_clone with v4-in-v6
mapping addition. (ga_clone): Just call ga_dup from here. (ga_duplist): New function to duplicate list of struct addrinfo. (ga_echeck): Don't check a_flags, it already happened in cygwin_getaddrinfo. (cygwin_freeaddrinfo): Always call ipv4_freeaddrinfo. (cygwin_getaddrinfo): Use new wincap.supports_all_posix_ai_flags flag rather than wincap.has_gaa_on_link_prefix. Always duplicate WinSock's addrinfo list to a self-allocated list. Handle AI_V4MAPPED for pre-Vista platforms supporting getaddrinfo. * wincap.h (wincapc::supports_all_posix_ai_flags): New element. * wincap.cc: Implement above element throughout. * include/netdb.h: Note how AI_ADDRCONFIG is not supported pre-Vista. Remove superfluous comment.
This commit is contained in:
parent
3281664245
commit
4815dd49bb
|
@ -1,3 +1,21 @@
|
|||
2007-02-01 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* net.cc (ga_dup): New function, taken from ga_clone with v4-in-v6
|
||||
mapping addition.
|
||||
(ga_clone): Just call ga_dup from here.
|
||||
(ga_duplist): New function to duplicate list of struct addrinfo.
|
||||
(ga_echeck): Don't check a_flags, it already happened in
|
||||
cygwin_getaddrinfo.
|
||||
(cygwin_freeaddrinfo): Always call ipv4_freeaddrinfo.
|
||||
(cygwin_getaddrinfo): Use new wincap.supports_all_posix_ai_flags
|
||||
flag rather than wincap.has_gaa_on_link_prefix. Always duplicate
|
||||
WinSock's addrinfo list to a self-allocated list. Handle AI_V4MAPPED
|
||||
for pre-Vista platforms supporting getaddrinfo.
|
||||
* wincap.h (wincapc::supports_all_posix_ai_flags): New element.
|
||||
* wincap.cc: Implement above element throughout.
|
||||
* include/netdb.h: Note how AI_ADDRCONFIG is not supported pre-Vista.
|
||||
Remove superfluous comment.
|
||||
|
||||
2007-02-01 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* include/cygwin/socket.h: Add IPv6 socket options.
|
||||
|
|
|
@ -148,9 +148,9 @@ extern __declspec(dllimport) int h_errno;
|
|||
#define AI_CANONNAME 2
|
||||
#define AI_NUMERICHOST 4
|
||||
#define AI_NUMERICSERV 8
|
||||
/* Only available since Vista. Ignored on older systems. */
|
||||
#define AI_ALL 256
|
||||
#define AI_ADDRCONFIG 1024
|
||||
#define AI_ADDRCONFIG 1024 /* Only available on Vista. Unchangable default
|
||||
on older systems. */
|
||||
#define AI_V4MAPPED 2048
|
||||
|
||||
#define NI_NOFQDN 1
|
||||
|
|
|
@ -3013,28 +3013,92 @@ ga_aistruct (struct addrinfo ***paipnext, const struct addrinfo *hintsp,
|
|||
*/
|
||||
|
||||
/* include ga_clone */
|
||||
|
||||
/* Cygwin specific: The ga_clone function is split up to allow an easy
|
||||
duplication of addrinfo structs. This is used to duplicate the
|
||||
structures from Winsock, so that we have the allocation of the structs
|
||||
returned to the application under control. This is especially helpful
|
||||
for the AI_V4MAPPED case prior to Vista. */
|
||||
static struct addrinfo *
|
||||
ga_clone (struct addrinfo *ai)
|
||||
ga_dup (struct addrinfo *ai, bool v4mapped)
|
||||
{
|
||||
struct addrinfo *nai;
|
||||
|
||||
if ((nai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
nai->ai_next = ai->ai_next;
|
||||
ai->ai_next = nai;
|
||||
|
||||
nai->ai_flags = 0; /* make sure AI_CLONE is off */
|
||||
nai->ai_family = ai->ai_family;
|
||||
nai->ai_family = v4mapped ? AF_INET6 : ai->ai_family;
|
||||
nai->ai_socktype = ai->ai_socktype;
|
||||
nai->ai_protocol = ai->ai_protocol;
|
||||
nai->ai_canonname = NULL;
|
||||
nai->ai_addrlen = ai->ai_addrlen;
|
||||
if ((nai->ai_addr = (struct sockaddr *) malloc (ai->ai_addrlen)) == NULL)
|
||||
return (NULL);
|
||||
memcpy (nai->ai_addr, ai->ai_addr, ai->ai_addrlen);
|
||||
if (!(ai->ai_flags & AI_CLONE) && ai->ai_canonname
|
||||
&& !(nai->ai_canonname = strdup (ai->ai_canonname)))
|
||||
{
|
||||
free (nai);
|
||||
return NULL;
|
||||
}
|
||||
nai->ai_addrlen = v4mapped ? sizeof (struct sockaddr_in6) : ai->ai_addrlen;
|
||||
if ((nai->ai_addr = (struct sockaddr *) malloc (v4mapped
|
||||
? sizeof (struct sockaddr_in6)
|
||||
: ai->ai_addrlen)) == NULL)
|
||||
{
|
||||
if (nai->ai_canonname)
|
||||
free (nai->ai_canonname);
|
||||
free (nai);
|
||||
return NULL;
|
||||
}
|
||||
if (v4mapped)
|
||||
{
|
||||
struct sockaddr_in6 *in = (struct sockaddr_in6 *) nai->ai_addr;
|
||||
in->sin6_family = AF_INET6;
|
||||
in->sin6_port = ((struct sockaddr_in *) ai->ai_addr)->sin_port;
|
||||
in->sin6_flowinfo = 0;
|
||||
in->sin6_addr.s6_addr32[0] = 0;
|
||||
in->sin6_addr.s6_addr32[1] = 0;
|
||||
in->sin6_addr.s6_addr32[2] = htonl (0xffff);
|
||||
in->sin6_addr.s6_addr32[3] = ((struct sockaddr_in *) ai->ai_addr)->sin_addr.s_addr;
|
||||
in->sin6_scope_id = 0;
|
||||
}
|
||||
else
|
||||
memcpy (nai->ai_addr, ai->ai_addr, ai->ai_addrlen);
|
||||
|
||||
return (nai);
|
||||
return nai;
|
||||
}
|
||||
|
||||
static struct addrinfo *
|
||||
ga_clone (struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *nai;
|
||||
|
||||
if ((nai = ga_dup (ai, false)))
|
||||
{
|
||||
nai->ai_next = ai->ai_next;
|
||||
ai->ai_next = nai;
|
||||
}
|
||||
return nai;
|
||||
}
|
||||
|
||||
static struct addrinfo *
|
||||
ga_duplist (struct addrinfo *ai, bool v4mapped)
|
||||
{
|
||||
void ipv4_freeaddrinfo (struct addrinfo *aihead);
|
||||
struct addrinfo *tmp, *nai = NULL, *nai0 = NULL;
|
||||
|
||||
for (; ai; ai = ai->ai_next, nai = tmp)
|
||||
{
|
||||
if (!(tmp = ga_dup (ai, v4mapped)))
|
||||
goto bad;
|
||||
if (!nai0)
|
||||
nai0 = tmp;
|
||||
if (nai)
|
||||
nai->ai_next = tmp;
|
||||
}
|
||||
return nai0;
|
||||
|
||||
bad:
|
||||
ipv4_freeaddrinfo (nai0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* end ga_clone */
|
||||
|
@ -3048,9 +3112,10 @@ static int
|
|||
ga_echeck (const char *hostname, const char *servname,
|
||||
int flags, int family, int socktype, int protocol)
|
||||
{
|
||||
#if 0
|
||||
if (flags & ~(AI_PASSIVE | AI_CANONNAME))
|
||||
return (EAI_BADFLAGS); /* unknown flag bits */
|
||||
|
||||
#endif
|
||||
if (hostname == NULL || hostname[0] == '\0')
|
||||
{
|
||||
if (servname == NULL || servname[0] == '\0')
|
||||
|
@ -3861,11 +3926,7 @@ cygwin_freeaddrinfo (struct addrinfo *addr)
|
|||
myfault efault;
|
||||
if (efault.faulted (EFAULT))
|
||||
return;
|
||||
load_ipv6 ();
|
||||
if (freeaddrinfo)
|
||||
freeaddrinfo (addr);
|
||||
else
|
||||
ipv4_freeaddrinfo (addr);
|
||||
ipv4_freeaddrinfo (addr);
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
|
@ -3894,21 +3955,71 @@ cygwin_getaddrinfo (const char *hostname, const char *servname,
|
|||
load_ipv6 ();
|
||||
if (getaddrinfo)
|
||||
{
|
||||
struct addrinfo nhints;
|
||||
struct addrinfo nhints, *dupres;
|
||||
|
||||
/* AI_ADDRCONFIG is not supported prior to Vista. Rather it's
|
||||
the default and only possible setting.
|
||||
On Vista, the default behaviour is as if AI_ADDRCONFIG is set,
|
||||
apparently for performance reasons. To get the POSIX default
|
||||
behaviour, the AI_ALL flag has to be set. */
|
||||
if (wincap.has_gaa_on_link_prefix ()
|
||||
if (wincap.supports_all_posix_ai_flags ()
|
||||
&& hints && hints->ai_family == PF_UNSPEC)
|
||||
{
|
||||
nhints = *hints;
|
||||
hints = &nhints;
|
||||
nhints.ai_flags |= AI_ALL;
|
||||
}
|
||||
return w32_to_gai_err (getaddrinfo (hostname, servname, hints, res));
|
||||
int ret = w32_to_gai_err (getaddrinfo (hostname, servname, hints, res));
|
||||
/* Always copy over to self-allocated memory. */
|
||||
if (!ret)
|
||||
{
|
||||
dupres = ga_duplist (*res, false);
|
||||
freeaddrinfo (*res);
|
||||
*res = dupres;
|
||||
if (!dupres)
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
/* AI_V4MAPPED and AI_ALL are not supported prior to Vista. So, what
|
||||
we do here is to emulate AI_V4MAPPED. If no IPv6 addresses are
|
||||
returned, or the AI_ALL flag is set, we try with AF_INET again, and
|
||||
convert the returned IPv4 addresses into v4-in-v6 entries. This
|
||||
is done in ga_dup if the v4mapped flag is set. */
|
||||
if (!wincap.supports_all_posix_ai_flags ()
|
||||
&& hints->ai_family == AF_INET6
|
||||
&& (hints->ai_flags & AI_V4MAPPED)
|
||||
&& (ret == EAI_NODATA || ret == EAI_NONAME
|
||||
|| (hints->ai_flags & AI_ALL)))
|
||||
{
|
||||
struct addrinfo *v4res;
|
||||
nhints = *hints;
|
||||
nhints.ai_family = AF_INET;
|
||||
int ret2 = w32_to_gai_err (getaddrinfo (hostname, servname,
|
||||
&nhints, &v4res));
|
||||
if (!ret2)
|
||||
{
|
||||
dupres = ga_duplist (v4res, true);
|
||||
freeaddrinfo (v4res);
|
||||
if (!dupres)
|
||||
{
|
||||
if (!ret)
|
||||
ipv4_freeaddrinfo (*res);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
/* If a list of v6 addresses exists, append the v4-in-v6 address
|
||||
list. Otherwise just return the v4-in-v6 address list. */
|
||||
if (!ret)
|
||||
{
|
||||
struct addrinfo *ptr;
|
||||
for (ptr = *res; ptr->ai_next; ptr = ptr->ai_next)
|
||||
;
|
||||
ptr->ai_next = dupres;
|
||||
}
|
||||
else
|
||||
*res = dupres;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ipv4_getaddrinfo (hostname, servname, hints, res);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ static NO_COPY wincaps wincap_unknown = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_95 = {
|
||||
|
@ -139,6 +140,7 @@ static NO_COPY wincaps wincap_95 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_95osr2 = {
|
||||
|
@ -204,6 +206,7 @@ static NO_COPY wincaps wincap_95osr2 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_98 = {
|
||||
|
@ -269,6 +272,7 @@ static NO_COPY wincaps wincap_98 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_98se = {
|
||||
|
@ -334,6 +338,7 @@ static NO_COPY wincaps wincap_98se = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_me = {
|
||||
|
@ -399,6 +404,7 @@ static NO_COPY wincaps wincap_me = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt3 = {
|
||||
|
@ -464,6 +470,7 @@ static NO_COPY wincaps wincap_nt3 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt4 = {
|
||||
|
@ -529,6 +536,7 @@ static NO_COPY wincaps wincap_nt4 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_nt4sp4 = {
|
||||
|
@ -594,6 +602,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_2000 = {
|
||||
|
@ -659,6 +668,7 @@ static NO_COPY wincaps wincap_2000 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:false,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_xp = {
|
||||
|
@ -724,6 +734,7 @@ static NO_COPY wincaps wincap_xp = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:true,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_2003 = {
|
||||
|
@ -789,6 +800,7 @@ static NO_COPY wincaps wincap_2003 = {
|
|||
has_recycle_dot_bin:false,
|
||||
has_gaa_prefixes:true,
|
||||
has_gaa_on_link_prefix:false,
|
||||
supports_all_posix_ai_flags:false,
|
||||
};
|
||||
|
||||
static NO_COPY wincaps wincap_vista = {
|
||||
|
@ -854,6 +866,7 @@ static NO_COPY wincaps wincap_vista = {
|
|||
has_recycle_dot_bin:true,
|
||||
has_gaa_prefixes:true,
|
||||
has_gaa_on_link_prefix:true,
|
||||
supports_all_posix_ai_flags:true,
|
||||
};
|
||||
|
||||
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
|
||||
|
|
|
@ -75,6 +75,7 @@ struct wincaps
|
|||
unsigned has_recycle_dot_bin : 1;
|
||||
unsigned has_gaa_prefixes : 1;
|
||||
unsigned has_gaa_on_link_prefix : 1;
|
||||
unsigned supports_all_posix_ai_flags : 1;
|
||||
};
|
||||
|
||||
class wincapc
|
||||
|
@ -156,6 +157,7 @@ public:
|
|||
bool IMPLEMENT (has_recycle_dot_bin)
|
||||
bool IMPLEMENT (has_gaa_prefixes)
|
||||
bool IMPLEMENT (has_gaa_on_link_prefix)
|
||||
bool IMPLEMENT (supports_all_posix_ai_flags)
|
||||
|
||||
#undef IMPLEMENT
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue