Index: net.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/net.cc,v
retrieving revision 1.322
diff -u -p -r1.322 net.cc
--- net.cc	20 Jan 2015 18:23:19 -0000	1.322
+++ net.cc	23 Jan 2015 00:03:45 -0000
@@ -72,6 +72,7 @@ extern "C"
   int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
 		      char *remuser, char *cmd, SOCKET * fd2p);
   int sscanf (const char *, const char *, ...);
+  int cygwin_inet_pton(int, const char *, void *);
   int cygwin_inet_aton(const char *, struct in_addr *);
   const char *cygwin_inet_ntop (int, const void *, char *, socklen_t);
   int dn_length1(const unsigned char *, const unsigned char *,
@@ -1168,6 +1169,97 @@ memcpy4to6 (char *dst, const u_char *src
   memcpy (dst + 12, src, NS_INADDRSZ);
 }
 
+/* gethostby_specials: RFC 6761 
+   Handles numerical addresses and special names for gethostbyname2 */ 
+static hostent *
+gethostby_specials (const char *name, const int af,
+		    const int addrsize_in, const int addrsize_out)
+{
+  int namelen = strlen (name);
+  /* Ignore a final '.' */
+  if ((namelen == 0) || ((namelen -= (name[namelen - 1] == '.')) == 0))  {
+    set_errno (EINVAL);
+    h_errno = NETDB_INTERNAL;
+    return NULL;
+  }
+
+  int res;
+  u_char address[NS_IN6ADDRSZ];
+  /* Test for numerical addresses */
+  res = cygwin_inet_pton(af, name, address);
+  /* Test for special domain names */
+  if (res != 1) {
+    {
+      char const match[] = "invalid";
+      int const matchlen = sizeof(match) - 1;
+      int start = namelen - matchlen;
+      if ((start >= 0) && ((start == 0) || (name[start-1] == '.'))
+	  && (strncasecmp (&name[start], match , matchlen) == 0)) {
+	h_errno = HOST_NOT_FOUND;
+	return NULL;
+      }
+    }
+    {
+      char const match[] = "localhost";
+      int const matchlen = sizeof(match) - 1;
+      int start = namelen - matchlen;
+      if ((start >= 0) && ((start == 0) || (name[start-1] == '.'))
+	  && (strncasecmp (&name[start], match , matchlen) == 0)) {
+	res = 1;
+	if (af == AF_INET) {
+	  address[0] = 127;
+	  address[1] = address[2] = 0;
+	  address[3] = 1;
+	}
+	else {
+	  memset (address, 0, NS_IN6ADDRSZ);
+	  address[NS_IN6ADDRSZ-1] = 1;
+	}
+      }
+    }
+  }
+  if (res != 1)
+    return NULL;  
+
+  int const alias_count = 0, address_count = 1;
+  char * string_ptr;
+  int sz = DWORD_round (sizeof(hostent))
+    + sizeof (char *) * (alias_count + address_count + 2)
+    + namelen + 1
+    + address_count * addrsize_out;
+  hostent *ret = realloc_ent (sz,  (hostent *) NULL);
+  if (!ret)
+    {
+      /* errno is already set */
+      h_errno = NETDB_INTERNAL;
+      return NULL;
+    }
+
+  ret->h_addrtype = af;
+  ret->h_length = addrsize_out;
+  ret->h_aliases = (char **) (((char *) ret) + DWORD_round (sizeof(hostent)));
+  ret->h_addr_list = ret->h_aliases + alias_count + 1;
+  string_ptr = (char *) (ret->h_addr_list + address_count + 1);
+  ret->h_name = string_ptr;
+
+  memcpy (string_ptr, name, namelen);
+  string_ptr[namelen] = 0;
+  string_ptr += namelen + 1;
+
+  ret->h_addr_list[0] = string_ptr;
+  if (addrsize_in != addrsize_out) {
+    memcpy4to6 (string_ptr, address);
+    ret->h_addrtype = AF_INET6;
+  }
+  else
+    memcpy (string_ptr, address, addrsize_out);
+
+  ret->h_aliases[alias_count] = NULL;
+  ret->h_addr_list[address_count] = NULL;
+
+  return ret;
+}
+
 static hostent *
 gethostby_helper (const char *name, const int af, const int type,
 		  const int addrsize_in, const int addrsize_out)
@@ -1352,8 +1444,10 @@ gethostby_helper (const char *name, cons
 	      string_ptr += curptr->namelen1;
 	    }
 	  ret->h_addr_list[address_count++] = string_ptr;
-	  if (addrsize_in != addrsize_out)
+	  if (addrsize_in != addrsize_out) {
 	    memcpy4to6 (string_ptr, curptr->data);
+	    ret->h_addrtype =  AF_INET6;
+	  }
 	  else
 	    memcpy (string_ptr, curptr->data, addrsize_in);
 	  string_ptr += addrsize_out;
@@ -1405,7 +1499,10 @@ gethostbyname2 (const char *name, int af
 	  __leave;
 	}
 
-      res = gethostby_helper (name, af, type, addrsize_in, addrsize_out);
+      h_errno = NETDB_SUCCESS;
+      res = gethostby_specials (name, af, addrsize_in, addrsize_out);
+      if ((res == NULL) && (h_errno == NETDB_SUCCESS))
+	  res = gethostby_helper (name, af, type, addrsize_in, addrsize_out);
     }
   __except (EFAULT) {}
   __endtry
