Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-02-01 18:54:40 +0300
committerCorinna Vinschen <corinna@vinschen.de>2007-02-01 18:54:40 +0300
commit4815dd49bb1483af60dad347ff351db13178a21e (patch)
treea23c35f243dd38e078a7a649a896713c9ccb08f3 /winsup
parent328166424516fa793c932a9caa3305ad240490bf (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog18
-rw-r--r--winsup/cygwin/include/netdb.h4
-rw-r--r--winsup/cygwin/net.cc149
-rw-r--r--winsup/cygwin/wincap.cc13
-rw-r--r--winsup/cygwin/wincap.h2
5 files changed, 165 insertions, 21 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index bf45c600f..2873a6b4d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,23 @@
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.
2007-01-31 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/include/netdb.h b/winsup/cygwin/include/netdb.h
index 4f2ead1ae..ffa2f8792 100644
--- a/winsup/cygwin/include/netdb.h
+++ b/winsup/cygwin/include/netdb.h
@@ -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
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index ad99bc277..ddd9a88ac 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -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);
}
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 7e9f71069..b26c78f84 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -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));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index de5d9a8d4..381a0c209 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -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
};