about summary refs log tree commit diff
path: root/sysdeps/posix/getaddrinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/posix/getaddrinfo.c')
-rw-r--r--sysdeps/posix/getaddrinfo.c92
1 files changed, 38 insertions, 54 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 81a56a0794..b9819bfc0a 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -121,7 +121,8 @@ struct gaih
   {
     int family;
     int (*gaih)(const char *name, const struct gaih_service *service,
-		const struct addrinfo *req, struct addrinfo **pai);
+		const struct addrinfo *req, struct addrinfo **pai,
+		unsigned int *naddrs);
   };
 
 static const struct addrinfo default_hints =
@@ -363,7 +364,8 @@ extern service_user *__nss_hosts_database attribute_hidden;
 
 static int
 gaih_inet (const char *name, const struct gaih_service *service,
-	   const struct addrinfo *req, struct addrinfo **pai)
+	   const struct addrinfo *req, struct addrinfo **pai,
+	   unsigned int *naddrs)
 {
   const struct gaih_typeproto *tp = gaih_inet_typeproto;
   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
@@ -393,6 +395,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	}
     }
 
+  int port = 0;
   if (service != NULL)
     {
       if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
@@ -445,63 +448,41 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	}
       else
 	{
-	  if (req->ai_socktype || req->ai_protocol)
-	    {
-	      st = __alloca (sizeof (struct gaih_servtuple));
-	      st->next = NULL;
-	      st->socktype = tp->socktype;
-	      st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
-			      ? req->ai_protocol : tp->protocol);
-	      st->port = htons (service->num);
-	    }
-	  else
-	    {
-	      /* Neither socket type nor protocol is set.  Return all
-		 socket types we know about.  */
-	      struct gaih_servtuple **lastp = &st;
-	      for (tp = gaih_inet_typeproto + 1; tp->name[0]; ++tp)
-		if ((tp->protoflag & GAI_PROTO_NOSERVICE) == 0)
-		  {
-		    struct gaih_servtuple *newp;
-
-		    newp = __alloca (sizeof (struct gaih_servtuple));
-		    newp->next = NULL;
-		    newp->socktype = tp->socktype;
-		    newp->protocol = tp->protocol;
-		    newp->port = htons (service->num);
-
-		    *lastp = newp;
-		    lastp = &newp->next;
-		  }
-	    }
+	  port = htons (service->num);
+	  goto got_port;
 	}
     }
-  else if (req->ai_socktype || req->ai_protocol)
-    {
-      st = __alloca (sizeof (struct gaih_servtuple));
-      st->next = NULL;
-      st->socktype = tp->socktype;
-      st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
-		      ? req->ai_protocol : tp->protocol);
-      st->port = 0;
-    }
   else
     {
-      /* Neither socket type nor protocol is set.  Return all socket types
-	 we know about.  */
-      struct gaih_servtuple **lastp = &st;
-      for (++tp; tp->name[0]; ++tp)
+    got_port:
+
+      if (req->ai_socktype || req->ai_protocol)
 	{
-	  struct gaih_servtuple *newp;
+	  st = __alloca (sizeof (struct gaih_servtuple));
+	  st->next = NULL;
+	  st->socktype = tp->socktype;
+	  st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
+			  ? req->ai_protocol : tp->protocol);
+	  st->port = port;
+	}
+      else
+	{
+	  /* Neither socket type nor protocol is set.  Return all socket types
+	     we know about.  */
+	  struct gaih_servtuple **lastp = &st;
+	  for (++tp; tp->name[0]; ++tp)
+	    {
+	      struct gaih_servtuple *newp;
 
-	  newp = __alloca (sizeof (struct gaih_servtuple));
-	  newp->next = NULL;
-	  newp->socktype = tp->socktype;
-	  newp->protocol = tp->protocol;
-	  newp->port = 0;
+	      newp = __alloca (sizeof (struct gaih_servtuple));
+	      newp->next = NULL;
+	      newp->socktype = tp->socktype;
+	      newp->protocol = tp->protocol;
+	      newp->port = port;
 
-	  *lastp = newp;
-	  lastp = &newp->next;
+	      *lastp = newp;
+	      lastp = &newp->next;
+	    }
 	}
     }
 
@@ -1108,6 +1089,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
 	  }
 	*pai = NULL;
 
+	++*naddrs;
+
       ignore:
 	at2 = at2->next;
       }
@@ -1556,6 +1539,7 @@ getaddrinfo (const char *name, const char *service,
   else
     end = NULL;
 
+  unsigned int naddrs = 0;
   while (g->gaih)
     {
       if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
@@ -1564,7 +1548,7 @@ getaddrinfo (const char *name, const char *service,
 	  if (pg == NULL || pg->gaih != g->gaih)
 	    {
 	      pg = g;
-	      i = g->gaih (name, pservice, hints, end);
+	      i = g->gaih (name, pservice, hints, end, &naddrs);
 	      if (i != 0)
 		{
 		  /* EAI_NODATA is a more specific result as it says that
@@ -1596,7 +1580,7 @@ getaddrinfo (const char *name, const char *service,
   if (j == 0)
     return EAI_FAMILY;
 
-  if (nresults > 1)
+  if (naddrs > 1)
     {
       /* Sort results according to RFC 3484.  */
       struct sort_result results[nresults];