|SUPPORTED_IDN_FLAGS|AI_ALL))
|AI_ALL))
getaddrinfo (const char *name, const char *service,	     const struct addrinfo *hints, struct addrinfo **pai){  int i = 0, j = 0, last_i = 0;  int nresults = 0;  struct addrinfo *p = NULL, **end;  struct gaih *g = gaih, *pg = NULL;  struct gaih_service gaih_service, *pservice;  struct addrinfo local_hints;  if (name != NULL && name[0] == '*' && name[1] == 0)    name = NULL;  if (service != NULL && service[0] == '*' && service[1] == 0)    service = NULL;  if (name == NULL && service == NULL)    return EAI_NONAME;  if (hints == NULL)    hints = &default_hints;  if (hints->ai_flags      & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED	  |SUPPORTED_IDN_FLAGS|AI_ALL))    return EAI_BADFLAGS;  if ((hints->ai_flags & (AI_CANONNAME|AI_CANONIDN)) && name == NULL)    return EAI_BADFLAGS;  if (hints->ai_flags & AI_ADDRCONFIG)    {      /* Determine whether we have IPv4 or IPv6 interfaces or both.	 We cannot cache the results since new interfaces could be	 added at any time.  */      bool seen_ipv4;      bool seen_ipv6;      __check_pf (&seen_ipv4, &seen_ipv6);      /* Now make a decision on what we return, if anything.  */      if (hints->ai_family == PF_UNSPEC)	{	  /* If we haven't seen both IPv4 and IPv6 interfaces we can	     narrow down the search.  */	  if (! seen_ipv4 || ! seen_ipv6)	    {	      local_hints = *hints;	      local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;	      hints = &local_hints;	    }	}      else if ((hints->ai_family == PF_INET && ! seen_ipv4)	       || (hints->ai_family == PF_INET6 && ! seen_ipv6))	/* We cannot possibly return a valid answer.  */	return EAI_NONAME;    }  if (service && service[0])    {      char *c;      gaih_service.name = service;      gaih_service.num = strtoul (gaih_service.name, &c, 10);      if (*c)	gaih_service.num = -1;      else	/* Can't specify a numerical socket unless a protocol family was	   given. */        if (hints->ai_socktype == 0 && hints->ai_protocol == 0)          return EAI_SERVICE;      pservice = &gaih_service;    }  else    pservice = NULL;  if (pai)    end = &p;  else    end = NULL;  while (g->gaih)    {      if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)	{	  j++;	  if (pg == NULL || pg->gaih != g->gaih)	    {	      pg = g;	      i = g->gaih (name, pservice, hints, end);	      if (i != 0)		{		  /* EAI_NODATA is a more specific result as it says that		     we found a result but it is not usable.  */		  if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))		    last_i = i;		  if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))		    {		      ++g;		      continue;		    }		  freeaddrinfo (p);		  return -(i & GAIH_EAI);		}	      if (end)		while (*end)		  {		    end = &((*end)->ai_next);		    ++nresults;		  }	    }	}      ++g;    }  if (j == 0)    return EAI_FAMILY;  if (nresults > 1)    {      /* Sort results according to RFC 3484.  */      struct sort_result results[nresults];      struct addrinfo *q;      for (i = 0, q = p; q != NULL; ++i, q = q->ai_next)	{	  results[i].dest_addr = q;	  results[i].got_source_addr = false;	  /* We overwrite the type with SOCK_DGRAM since we do not	     want connect() to connect to the other side.  If we	     cannot determine the source address remember this	     fact.  */	  int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);	  if (fd != -1)	    {	      socklen_t sl = sizeof (results[i].source_addr);	      if (__connect (fd, q->ai_addr, q->ai_addrlen) == 0		  && __getsockname (fd,				    (struct sockaddr *) &results[i].source_addr,				    &sl) == 0)		results[i].got_source_addr = true;	      close_not_cancel_no_status (fd);	    }	}      /* We got all the source addresses we can get, now sort using	 the information.  */      qsort (results, nresults, sizeof (results[0]), rfc3484_sort);      /* Queue the results up as they come out of sorting.  */      q = p = results[0].dest_addr;      for (i = 1; i < nresults; ++i)	q = q->ai_next = results[i].dest_addr;      q->ai_next = NULL;    }  if (p)    {      *pai = p;      return 0;    }  if (pai == NULL && last_i == 0)    return 0;  freeaddrinfo (p);  return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;}