diff options
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/inet/getaddrinfo.c | 1368 | 
1 files changed, 630 insertions, 738 deletions
| diff --git a/libc/inet/getaddrinfo.c b/libc/inet/getaddrinfo.c index b4f49607b..3af422b72 100644 --- a/libc/inet/getaddrinfo.c +++ b/libc/inet/getaddrinfo.c @@ -120,886 +120,778 @@ struct BUG_too_small {  			) <= 127 ? 1 : -1];  }; -struct gaih_service -{ -    const char *name; -    int num; +struct gaih_service { +	const char *name; +	int num;  }; -struct gaih_servtuple -{ -    struct gaih_servtuple *next; -    int socktype; -    int protocol; -    int port; +struct gaih_servtuple { +	struct gaih_servtuple *next; +	int socktype; +	int protocol; +	int port;  }; -struct gaih_addrtuple -{ -    struct gaih_addrtuple *next; -    int family; -    char addr[16]; -    uint32_t scopeid; +struct gaih_addrtuple { +	struct gaih_addrtuple *next; +	int family; +	char addr[16]; +	uint32_t scopeid;  }; -struct gaih_typeproto -{ -    socktype_t socktype; -    protocol_t protocol; -    int8_t protoflag; -    char name[4]; +struct gaih_typeproto { +	socktype_t socktype; +	protocol_t protocol; +	int8_t protoflag; +	char name[4];  };  /* Values for `protoflag'.  */ -#define GAI_PROTO_NOSERVICE	1 -#define GAI_PROTO_PROTOANY	2 - -static const struct gaih_typeproto gaih_inet_typeproto[] = -{ -    { 0          , 0          , 0                                     , ""    }, -    { SOCK_STREAM, IPPROTO_TCP, 0                                     , "tcp" }, -    { SOCK_DGRAM , IPPROTO_UDP, 0                                     , "udp" }, -    { SOCK_RAW   , 0          , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" }, -    { 0          , 0          , 0                                     , ""    }, +#define GAI_PROTO_NOSERVICE 1 +#define GAI_PROTO_PROTOANY  2 + +static const struct gaih_typeproto gaih_inet_typeproto[] = { +	{ 0          , 0          , 0, ""    }, +	{ SOCK_STREAM, IPPROTO_TCP, 0, "tcp" }, +	{ SOCK_DGRAM , IPPROTO_UDP, 0, "udp" }, +	{ SOCK_RAW   , 0          , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" }, +	{ 0          , 0          , 0, ""    },  }; -struct gaih -{ -    int family; -    int (*gaih)(const char *name, const struct gaih_service *service, -		const struct addrinfo *req, struct addrinfo **pai); +struct gaih { +	int family; +	int (*gaih)(const char *name, const struct gaih_service *service, +			const struct addrinfo *req, struct addrinfo **pai);  };  #define SEEN_IPV4 1  #define SEEN_IPV6 2 -static unsigned __check_pf (void) +static unsigned __check_pf(void)  { -  unsigned seen = 0; +	unsigned seen = 0;  #if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__ -  { -    /* Get the interface list via getifaddrs.  */ -    struct ifaddrs *ifa = NULL; -    struct ifaddrs *runp; -    if (getifaddrs (&ifa) != 0) -    { -      /* We cannot determine what interfaces are available.  Be -      optimistic.  */ +	{ +		/* Get the interface list via getifaddrs.  */ +		struct ifaddrs *ifa = NULL; +		struct ifaddrs *runp; +		if (getifaddrs(&ifa) != 0) { +			/* We cannot determine what interfaces are available. +			 * Be optimistic.  */  #if defined __UCLIBC_HAS_IPV4__ -      seen |= SEEN_IPV4; +			seen |= SEEN_IPV4;  #endif /* __UCLIBC_HAS_IPV4__ */  #if defined __UCLIBC_HAS_IPV6__ -      seen |= SEEN_IPV6; +			seen |= SEEN_IPV6;  #endif /* __UCLIBC_HAS_IPV6__ */ -      return seen; -    } +			return seen; +		} -    for (runp = ifa; runp != NULL; runp = runp->ifa_next) +		for (runp = ifa; runp != NULL; runp = runp->ifa_next)  #if defined __UCLIBC_HAS_IPV4__ -      if (runp->ifa_addr->sa_family == PF_INET) -        seen |= SEEN_IPV4; +			if (runp->ifa_addr->sa_family == PF_INET) +				seen |= SEEN_IPV4;  #endif /* __UCLIBC_HAS_IPV4__ */  #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ -      else /* can't be both at once */ +			else /* can't be both at once */  #endif /* __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ */  #if defined __UCLIBC_HAS_IPV6__ -      if (runp->ifa_addr->sa_family == PF_INET6) -        seen |= SEEN_IPV6; +			if (runp->ifa_addr->sa_family == PF_INET6) +				seen |= SEEN_IPV6;  #endif /* __UCLIBC_HAS_IPV6__ */ -    (void) freeifaddrs (ifa); -  } +		freeifaddrs(ifa); +	}  #else -  /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */ +	/* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */  #if defined __UCLIBC_HAS_IPV4__ -  seen |= SEEN_IPV4; +	seen |= SEEN_IPV4;  #endif /* __UCLIBC_HAS_IPV4__ */  #if defined __UCLIBC_HAS_IPV6__ -  seen |= SEEN_IPV6; +	seen |= SEEN_IPV6;  #endif /* __UCLIBC_HAS_IPV6__ */  #endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ -  return seen; +	return seen;  } -static int addrconfig (sa_family_t af) +static int addrconfig(sa_family_t af)  { -    int s; -    int ret; -    int saved_errno = errno; -    unsigned seen; +	int s; +	int ret; +	int saved_errno = errno; +	unsigned seen; -    seen = __check_pf(); +	seen = __check_pf();  #if defined __UCLIBC_HAS_IPV4__ -    if (af == AF_INET) -	ret = seen & SEEN_IPV4; -    else +	if (af == AF_INET) +		ret = seen & SEEN_IPV4; +	else  #endif  #if defined __UCLIBC_HAS_IPV6__ -    if (af == AF_INET6) -	ret = seen & SEEN_IPV6; -    else +	if (af == AF_INET6) +		ret = seen & SEEN_IPV6; +	else  #endif -    { -	s = socket(af, SOCK_DGRAM, 0); -	ret = 1; /* Assume PF_UNIX. */ -	if (s < 0) { -	    if (errno != EMFILE) -	        ret = 0; +	{ +		s = socket(af, SOCK_DGRAM, 0); +		ret = 1; /* Assume PF_UNIX. */ +		if (s < 0) { +			if (errno != EMFILE) +	        		ret = 0; +		} else +			close(s);  	} -	else -	    close(s); -    } -    __set_errno (saved_errno); -    return ret; +	__set_errno(saved_errno); +	return ret;  }  #if 0  /* Using Unix sockets this way is a security risk.  */  static int -gaih_local (const char *name, const struct gaih_service *service, +gaih_local(const char *name, const struct gaih_service *service,  	    const struct addrinfo *req, struct addrinfo **pai)  { -    struct utsname utsname; - -    if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) -	return GAIH_OKIFUNSPEC | -EAI_NONAME; - -    if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) -	if (uname (&utsname) < 0) -	    return -EAI_SYSTEM; - -    if (name != NULL) -    { -	if (strcmp(name, "localhost") && -	    strcmp(name, "local") && -	    strcmp(name, "unix") && -	    strcmp(name, utsname.nodename)) -	    return GAIH_OKIFUNSPEC | -EAI_NONAME; -    } - -    if (req->ai_protocol || req->ai_socktype) -    { -	const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; - -	while (tp->name[0] -	       && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 -		   || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) -		   || (req->ai_protocol != 0 -		       && !(tp->protoflag & GAI_PROTO_PROTOANY) -		       && req->ai_protocol != tp->protocol))) -	    ++tp; - -	if (! tp->name[0]) -	{ -	    if (req->ai_socktype) -		return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); -	    return (GAIH_OKIFUNSPEC | -EAI_SERVICE); -	} -    } - -    *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un) -		   + ((req->ai_flags & AI_CANONNAME) -		      ? (strlen(utsname.nodename) + 1): 0)); -    if (*pai == NULL) -	return -EAI_MEMORY; - -    (*pai)->ai_next = NULL; -    (*pai)->ai_flags = req->ai_flags; -    (*pai)->ai_family = AF_LOCAL; -    (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; -    (*pai)->ai_protocol = req->ai_protocol; -    (*pai)->ai_addrlen = sizeof (struct sockaddr_un); -    (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo); +	struct utsname utsname; + +	if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) +		return GAIH_OKIFUNSPEC | -EAI_NONAME; + +	if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) +		if (uname(&utsname) < 0) +			return -EAI_SYSTEM; + +	if (name != NULL) { +		if (strcmp(name, "localhost") && +		    strcmp(name, "local") && +		    strcmp(name, "unix") && +		    strcmp(name, utsname.nodename)) +			return (GAIH_OKIFUNSPEC | -EAI_NONAME); +		} + +		if (req->ai_protocol || req->ai_socktype) { +			const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; + +			while (tp->name[0] +			    && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 +			       || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) +			       || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)) +			) { +				++tp; +			} +			if (! tp->name[0]) { +				if (req->ai_socktype) +					return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); +				return (GAIH_OKIFUNSPEC | -EAI_SERVICE); +			} +		} + +		*pai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) +			+ ((req->ai_flags & AI_CANONNAME) +			    ? (strlen(utsname.nodename) + 1): 0)); +		if (*pai == NULL) +			return -EAI_MEMORY; + +		(*pai)->ai_next = NULL; +		(*pai)->ai_flags = req->ai_flags; +		(*pai)->ai_family = AF_LOCAL; +		(*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; +		(*pai)->ai_protocol = req->ai_protocol; +		(*pai)->ai_addrlen = sizeof(struct sockaddr_un); +		(*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo);  #if SALEN -    ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len = -	sizeof (struct sockaddr_un); +		((struct sockaddr_un *)(*pai)->ai_addr)->sun_len = sizeof(struct sockaddr_un);  #endif /* SALEN */ -    ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; -    memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); +		((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; +		memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); -    if (service) -    { -	struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr; +		if (service) { +			struct sockaddr_un *sunp = (struct sockaddr_un *)(*pai)->ai_addr; -	if (strchr (service->name, '/') != NULL) -	{ -	    if (strlen (service->name) >= sizeof (sunp->sun_path)) -		return GAIH_OKIFUNSPEC | -EAI_SERVICE; +			if (strchr(service->name, '/') != NULL) { +				if (strlen(service->name) >= sizeof(sunp->sun_path)) +					return GAIH_OKIFUNSPEC | -EAI_SERVICE; -	    strcpy (sunp->sun_path, service->name); +			strcpy(sunp->sun_path, service->name); +		} else { +			if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path)) +				return (GAIH_OKIFUNSPEC | -EAI_SERVICE); +			stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name); +		} +	} else { +		/* This is a dangerous use of the interface since there is a time +		   window between the test for the file and the actual creation +		   (done by the caller) in which a file with the same name could +		   be created.  */ +		char *buf = ((struct sockaddr_un *)(*pai)->ai_addr)->sun_path; + +		if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0 +		 || __gen_tempname(buf, __GT_NOCREATE) != 0 +		) { +			return -EAI_SYSTEM; +		}  	} -	else -	{ -	    if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >= -		sizeof (sunp->sun_path)) -		return GAIH_OKIFUNSPEC | -EAI_SERVICE; -	    stpcpy (stpcpy (sunp->sun_path, P_tmpdir "/"), service->name); -	} -    } -    else -    { -	/* This is a dangerous use of the interface since there is a time -	   window between the test for the file and the actual creation -	   (done by the caller) in which a file with the same name could -	   be created.  */ -	char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path; - -	if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0), -			      0) != 0 -	    || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0) -	    return -EAI_SYSTEM; -    } - -    if (req->ai_flags & AI_CANONNAME) -	(*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo) -				       + sizeof (struct sockaddr_un), -				       utsname.nodename); -    else -	(*pai)->ai_canonname = NULL; -    return 0; +	if (req->ai_flags & AI_CANONNAME) +		(*pai)->ai_canonname = strcpy((char *) *pai + sizeof(struct addrinfo) + sizeof(struct sockaddr_un), +				utsname.nodename); +	else +		(*pai)->ai_canonname = NULL; +	return 0;  }  #endif	/* 0 */  static int -gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, +gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp,  		const struct addrinfo *req, struct gaih_servtuple *st)  { -    struct servent *s; -    size_t tmpbuflen = 1024; -    struct servent ts; -    char *tmpbuf; -    int r; - -    do -    { -	tmpbuf = alloca (tmpbuflen); - -	r = getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, -			     &s); -	if (r != 0 || s == NULL) -	{ -	    if (r == ERANGE) +	struct servent *s; +	size_t tmpbuflen = 1024; +	struct servent ts; +	char *tmpbuf; +	int r; + +	while (1) { +		tmpbuf = alloca(tmpbuflen); +		r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s); +		if (r == 0 && s != NULL) +			break; +		if (r != ERANGE) +			return (GAIH_OKIFUNSPEC | -EAI_SERVICE);  		tmpbuflen *= 2; -	    else -		return GAIH_OKIFUNSPEC | -EAI_SERVICE;  	} -    } -    while (r); - -    st->next = NULL; -    st->socktype = tp->socktype; -    st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) -		    ? req->ai_protocol : tp->protocol); -    st->port = s->s_port; - -    return 0; +	st->next = NULL; +	st->socktype = tp->socktype; +	st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); +	st->port = s->s_port; +	return 0;  } -#define gethosts(_family, _type)					\ -{									\ -    int i, herrno;							\ -    size_t tmpbuflen;							\ -    struct hostent th;							\ -    char *tmpbuf;							\ -    tmpbuflen = 512;							\ -    no_data = 0;							\ -    do {								\ -	tmpbuflen *= 2;							\ -	tmpbuf = alloca (tmpbuflen);					\ -	rc = gethostbyname2_r (name, _family, &th, tmpbuf,		\ -			       tmpbuflen, &h, &herrno);			\ -    } while (rc == ERANGE && herrno == NETDB_INTERNAL);			\ -    if (rc != 0)							\ -    {									\ -	if (herrno == NETDB_INTERNAL)					\ -	{								\ -	    __set_h_errno (herrno);					\ -		return -EAI_SYSTEM;					\ -	}								\ -	if (herrno == TRY_AGAIN)					\ -	    no_data = EAI_AGAIN;					\ -	else								\ -	    no_data = herrno == NO_DATA;				\ -    }									\ -    else if (h != NULL)							\ -    {									\ -	for (i = 0; h->h_addr_list[i]; i++)				\ -	{								\ -	    if (*pat == NULL) {						\ -		*pat = alloca (sizeof(struct gaih_addrtuple));		\ -		    (*pat)->scopeid = 0;				\ -	    }								\ -	    (*pat)->next = NULL;					\ -		(*pat)->family = _family;				\ -		memcpy ((*pat)->addr, h->h_addr_list[i],		\ -			sizeof(_type));					\ -		pat = &((*pat)->next);					\ -	}								\ -    }									\ +/* NB: also uses h,pat,rc,no_data variables */ +#define gethosts(_family, _type)						\ +{										\ +	int i, herrno;								\ +	size_t tmpbuflen;							\ +	struct hostent th;							\ +	char *tmpbuf;								\ +										\ +	tmpbuflen = 512;							\ +	no_data = 0;								\ +	do {									\ +		tmpbuflen *= 2;							\ +		tmpbuf = alloca(tmpbuflen);					\ +		rc = gethostbyname2_r(name, _family, &th, tmpbuf,		\ +				tmpbuflen, &h, &herrno);			\ +	} while (rc == ERANGE && herrno == NETDB_INTERNAL);			\ +	if (rc != 0) {								\ +		if (herrno == NETDB_INTERNAL) {					\ +			__set_h_errno(herrno);					\ +			return -EAI_SYSTEM;					\ +		}								\ +		if (herrno == TRY_AGAIN)					\ +			no_data = EAI_AGAIN;					\ +		else								\ +			no_data = (herrno == NO_DATA);				\ +	} else if (h != NULL) {							\ +		for (i = 0; h->h_addr_list[i]; i++) {				\ +			if (*pat == NULL) {					\ +				*pat = alloca(sizeof(struct gaih_addrtuple));	\ +				(*pat)->scopeid = 0;				\ +			}							\ +			(*pat)->next = NULL;					\ +			(*pat)->family = _family;				\ +			memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type));	\ +			pat = &((*pat)->next);					\ +		}								\ +	}									\  }  static int -gaih_inet (const char *name, const struct gaih_service *service, -	   const struct addrinfo *req, struct addrinfo **pai) +gaih_inet(const char *name, const struct gaih_service *service, +		const struct addrinfo *req, struct addrinfo **pai)  { -    struct gaih_servtuple nullserv; - -    const struct gaih_typeproto *tp = gaih_inet_typeproto; -    struct gaih_servtuple *st = &nullserv; -    struct gaih_addrtuple *at = NULL; -    int rc; -    int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) && -	(req->ai_flags & AI_V4MAPPED); -    unsigned seen = __check_pf(); - -    memset(&nullserv, 0, sizeof(nullserv)); - -    if (req->ai_protocol || req->ai_socktype) -    { -	++tp; - -	while (tp->name[0] -	       && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype) -		   || (req->ai_protocol != 0 -		       && !(tp->protoflag & GAI_PROTO_PROTOANY) -		       && req->ai_protocol != tp->protocol))) -	    ++tp; - -	if (! tp->name[0]) -	{ -	    if (req->ai_socktype) -		return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); -	    return (GAIH_OKIFUNSPEC | -EAI_SERVICE); -	} -    } - -    if (service != NULL) -    { -	if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) -	    return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - -	if (service->num < 0) -	{ -	    if (tp->name[0]) -	    { -		st = (struct gaih_servtuple *) -		    alloca (sizeof (struct gaih_servtuple)); - -		if ((rc = gaih_inet_serv (service->name, tp, req, st))) -		    return rc; -	    } -	    else -	    { -		struct gaih_servtuple **pst = &st; -		for (tp++; tp->name[0]; tp++) -		{ -		    struct gaih_servtuple *newp; - -		    if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) -			continue; - -		    if (req->ai_socktype != 0 -			&& req->ai_socktype != tp->socktype) -			continue; -		    if (req->ai_protocol != 0 -			&& !(tp->protoflag & GAI_PROTO_PROTOANY) -			&& req->ai_protocol != tp->protocol) -			continue; - -		    newp = (struct gaih_servtuple *) -			alloca (sizeof (struct gaih_servtuple)); - -		    if ((rc = gaih_inet_serv (service->name, tp, req, newp))) -		    { -			if (rc & GAIH_OKIFUNSPEC) -			    continue; -			return rc; -		    } - -		    *pst = newp; -		    pst = &(newp->next); +	struct gaih_servtuple nullserv; + +	const struct gaih_typeproto *tp = gaih_inet_typeproto; +	struct gaih_servtuple *st = &nullserv; +	struct gaih_addrtuple *at = NULL; +	int rc; +	int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) +			&& (req->ai_flags & AI_V4MAPPED); +	unsigned seen = __check_pf(); + +	memset(&nullserv, 0, sizeof(nullserv)); + +	if (req->ai_protocol || req->ai_socktype) { +		++tp; +		while (tp->name[0] +			&& ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype) +			    || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol) +			) +		) { +			++tp; +		} +		if (! tp->name[0]) { +			if (req->ai_socktype) +				return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); +			return (GAIH_OKIFUNSPEC | -EAI_SERVICE);  		} -		if (st == &nullserv) -		    return (GAIH_OKIFUNSPEC | -EAI_SERVICE); -	    } -	} -	else -	{ -	    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 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) -	{ -	    struct gaih_servtuple *newp; - -	    newp = alloca (sizeof (struct gaih_servtuple)); -	    newp->next = NULL; -	    newp->socktype = tp->socktype; -	    newp->protocol = tp->protocol; -	    newp->port = 0; -	    *lastp = newp; -	    lastp = &newp->next; +	if (service != NULL) { +		if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) +			return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + +		if (service->num < 0) { +			if (tp->name[0]) { +				st = alloca(sizeof(struct gaih_servtuple)); +				rc = gaih_inet_serv(service->name, tp, req, st); +				if (rc) +					return rc; +			} else { +				struct gaih_servtuple **pst = &st; +				for (tp++; tp->name[0]; tp++) { +					struct gaih_servtuple *newp; + +					if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) +						continue; + +					if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) +						continue; +					if (req->ai_protocol != 0 +					 && !(tp->protoflag & GAI_PROTO_PROTOANY) +					 && req->ai_protocol != tp->protocol) +						continue; + +					newp = alloca(sizeof(struct gaih_servtuple)); +					rc = gaih_inet_serv(service->name, tp, req, newp); +					if (rc) { +						if (rc & GAIH_OKIFUNSPEC) +							continue; +						return rc; +					} + +					*pst = newp; +					pst = &(newp->next); +				} +				if (st == &nullserv) +					return (GAIH_OKIFUNSPEC | -EAI_SERVICE); +			} +		} else { +			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 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) { +			struct gaih_servtuple *newp; + +			newp = alloca(sizeof(struct gaih_servtuple)); +			newp->next = NULL; +			newp->socktype = tp->socktype; +			newp->protocol = tp->protocol; +			newp->port = 0; + +			*lastp = newp; +			lastp = &newp->next; +		}  	} -    } -    if (name != NULL) -    { -	at = alloca (sizeof (struct gaih_addrtuple)); - -	at->family = AF_UNSPEC; -	at->scopeid = 0; -	at->next = NULL; - -	if (inet_pton (AF_INET, name, at->addr) > 0) -	{ -	    if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) -		at->family = AF_INET; -	    else -		return -EAI_FAMILY; -	} +	if (name != NULL) { +		at = alloca(sizeof(struct gaih_addrtuple)); +		at->family = AF_UNSPEC; +		at->scopeid = 0; +		at->next = NULL; + +		if (inet_pton(AF_INET, name, at->addr) > 0) { +			if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) +				at->family = AF_INET; +			else +				return -EAI_FAMILY; +		}  #if defined __UCLIBC_HAS_IPV6__ -	if (at->family == AF_UNSPEC) -	{ -	    char *namebuf = strdupa (name); -	    char *scope_delim; - -	    scope_delim = strchr (namebuf, SCOPE_DELIMITER); -	    if (scope_delim != NULL) -		*scope_delim = '\0'; - -	    if (inet_pton (AF_INET6, namebuf, at->addr) > 0) -	    { -		if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) -		    at->family = AF_INET6; -		else -		    return -EAI_FAMILY; - -		if (scope_delim != NULL) -		{ -		    int try_numericscope = 0; -		    if (IN6_IS_ADDR_LINKLOCAL (at->addr) -			|| IN6_IS_ADDR_MC_LINKLOCAL (at->addr)) -		    { -			at->scopeid = if_nametoindex (scope_delim + 1); -			if (at->scopeid == 0) -			    try_numericscope = 1; -		    } -		    else -			try_numericscope = 1; - -		    if (try_numericscope != 0) -		    { -			char *end; -			assert (sizeof (uint32_t) <= sizeof (unsigned long)); -			at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end, -							  10); -			if (*end != '\0') -			    return GAIH_OKIFUNSPEC | -EAI_NONAME; -		    } +		if (at->family == AF_UNSPEC) { +			char *namebuf = strdupa(name); +			char *scope_delim; + +			scope_delim = strchr(namebuf, SCOPE_DELIMITER); +			if (scope_delim != NULL) +				*scope_delim = '\0'; + +			if (inet_pton(AF_INET6, namebuf, at->addr) > 0) { +				if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) +					at->family = AF_INET6; +				else +					return -EAI_FAMILY; + +				if (scope_delim != NULL) { +					int try_numericscope = 0; +					if (IN6_IS_ADDR_LINKLOCAL(at->addr) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) { +						at->scopeid = if_nametoindex(scope_delim + 1); +						if (at->scopeid == 0) +							try_numericscope = 1; +					} else +						try_numericscope = 1; + +					if (try_numericscope != 0) { +						char *end; +						assert(sizeof(uint32_t) <= sizeof(unsigned long)); +						at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10); +						if (*end != '\0') +							return (GAIH_OKIFUNSPEC | -EAI_NONAME); +					} +				} +			}  		} -	    } -	}  #endif -	if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) -	{ -	    struct hostent *h; -	    struct gaih_addrtuple **pat = &at; -	    int no_data = 0; -	    int no_inet6_data; - -	    /* -	     * If we are looking for both IPv4 and IPv6 address we don't want -	     * the lookup functions to automatically promote IPv4 addresses to -	     * IPv6 addresses. -	     */ - +		if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) { +			struct hostent *h; +			struct gaih_addrtuple **pat = &at; +			int no_data = 0; +			int no_inet6_data; + +			/* +			 * If we are looking for both IPv4 and IPv6 address we don't want +			 * the lookup functions to automatically promote IPv4 addresses to +			 * IPv6 addresses. +			 */  #if defined __UCLIBC_HAS_IPV6__ -	    if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) -		if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) -		    gethosts (AF_INET6, struct in6_addr); +			if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) +				if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) +					gethosts(AF_INET6, struct in6_addr);  #endif -	    no_inet6_data = no_data; - -	    if (req->ai_family == AF_INET || -		(!v4mapped && req->ai_family == AF_UNSPEC) || -		(v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))) -		if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) -		    gethosts (AF_INET, struct in_addr); - -	    if (no_data != 0 && no_inet6_data != 0) -	    { -		/* If both requests timed out report this. */ -		if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) -		    return -EAI_AGAIN; - -		/* -		 * We made requests but they turned out no data. -		 * The name is known, though. -		 */ -		return (GAIH_OKIFUNSPEC | -EAI_AGAIN); -	    } -	} - -	if (at->family == AF_UNSPEC) -	    return (GAIH_OKIFUNSPEC | -EAI_NONAME); -    } -    else -    { -	struct gaih_addrtuple *atr; -	atr = at = alloca (sizeof (struct gaih_addrtuple)); -	memset (at, '\0', sizeof (struct gaih_addrtuple)); +			no_inet6_data = no_data; + +			if (req->ai_family == AF_INET +			 || (!v4mapped && req->ai_family == AF_UNSPEC) +			 || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))) +			) { +				if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) +					gethosts(AF_INET, struct in_addr); +			} + +			if (no_data != 0 && no_inet6_data != 0) { +				/* If both requests timed out report this. */ +				if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) +					return -EAI_AGAIN; +				/* +				 * We made requests but they turned out no data. +				 * The name is known, though. +				 */ +				return (GAIH_OKIFUNSPEC | -EAI_AGAIN); +			} +		} -	if (req->ai_family == 0) -	{ -	    at->next = alloca (sizeof (struct gaih_addrtuple)); -	    memset (at->next, '\0', sizeof (struct gaih_addrtuple)); -	} +		if (at->family == AF_UNSPEC) +			return (GAIH_OKIFUNSPEC | -EAI_NONAME); +	} else { +		struct gaih_addrtuple *atr; +		atr = at = alloca(sizeof(struct gaih_addrtuple)); +		memset(at, '\0', sizeof(struct gaih_addrtuple)); +		if (req->ai_family == 0) { +			at->next = alloca(sizeof(struct gaih_addrtuple)); +			memset(at->next, '\0', sizeof(struct gaih_addrtuple)); +		}  #if defined __UCLIBC_HAS_IPV6__ -	if (req->ai_family == 0 || req->ai_family == AF_INET6) -	{ -	    at->family = AF_INET6; -	    if ((req->ai_flags & AI_PASSIVE) == 0) -		memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr)); -	    atr = at->next; -	} +		if (req->ai_family == 0 || req->ai_family == AF_INET6) { +			at->family = AF_INET6; +			if ((req->ai_flags & AI_PASSIVE) == 0) +				memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr)); +			atr = at->next; +		}  #endif - -	if (req->ai_family == 0 || req->ai_family == AF_INET) -	{ -	    atr->family = AF_INET; -	    if ((req->ai_flags & AI_PASSIVE) == 0) -		*(uint32_t *) atr->addr = htonl (INADDR_LOOPBACK); +		if (req->ai_family == 0 || req->ai_family == AF_INET) { +			atr->family = AF_INET; +			if ((req->ai_flags & AI_PASSIVE) == 0) +				*(uint32_t*)atr->addr = htonl(INADDR_LOOPBACK); +		}  	} -    } - -    if (pai == NULL) -	return 0; - -    { -	const char *c = NULL; -	struct gaih_servtuple *st2; -	struct gaih_addrtuple *at2 = at; -	size_t socklen, namelen; -	sa_family_t family; -	/* -	 * buffer is the size of an unformatted IPv6 address in -	 * printable format. -	 */ -	char buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; +	if (pai == NULL) +		return 0; -	while (at2 != NULL)  	{ -	    if (req->ai_flags & AI_CANONNAME) -	    { -		struct hostent *h = NULL; - -		int herrno; -		struct hostent th; -		size_t tmpbuflen = 512; -		char *tmpbuf; - -		do -		{ -		    tmpbuflen *= 2; -		    tmpbuf = alloca (tmpbuflen); - -		    if (tmpbuf == NULL) -			return -EAI_MEMORY; - -		    rc = gethostbyaddr_r (at2->addr, -					  ((at2->family == AF_INET6) -					   ? sizeof(struct in6_addr) -					   : sizeof(struct in_addr)), -					  at2->family, &th, tmpbuf, tmpbuflen, -					  &h, &herrno); - -		} -		while (rc == errno && herrno == NETDB_INTERNAL); - -		if (rc != 0 && herrno == NETDB_INTERNAL) -		{ -		    __set_h_errno (herrno); -		    return -EAI_SYSTEM; -		} - -		if (h == NULL) -		    c = inet_ntop (at2->family, at2->addr, buffer, sizeof(buffer)); -		else -		    c = h->h_name; +		const char *c = NULL; +		struct gaih_servtuple *st2; +		struct gaih_addrtuple *at2 = at; +		size_t socklen, namelen; +		sa_family_t family; -		if (c == NULL) -		    return GAIH_OKIFUNSPEC | -EAI_NONAME; - -		namelen = strlen (c) + 1; -	    } -	    else -		namelen = 0; +		/* +		 * buffer is the size of an unformatted IPv6 address in +		 * printable format. +		 */ +		char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + +		while (at2 != NULL) { +			if (req->ai_flags & AI_CANONNAME) { +				struct hostent *h = NULL; +				int herrno; +				struct hostent th; +				size_t tmpbuflen = 512; +				char *tmpbuf; + +				do { +					tmpbuflen *= 2; +					tmpbuf = alloca(tmpbuflen); +					//if (tmpbuf == NULL) +					//	return -EAI_MEMORY; +					rc = gethostbyaddr_r(at2->addr, +						((at2->family == AF_INET6) +						 ? sizeof(struct in6_addr) +						 : sizeof(struct in_addr)), +						at2->family, +						&th, tmpbuf, tmpbuflen, +						&h, &herrno); +				} while (rc == errno && herrno == NETDB_INTERNAL); + +				if (rc != 0 && herrno == NETDB_INTERNAL) { +					__set_h_errno(herrno); +					return -EAI_SYSTEM; +				} + +				if (h == NULL) +					c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); +				else +					c = h->h_name; + +				if (c == NULL) +					return (GAIH_OKIFUNSPEC | -EAI_NONAME); + +				namelen = strlen(c) + 1; +			} else +				namelen = 0;  #if defined __UCLIBC_HAS_IPV6__ -	    if (at2->family == AF_INET6 || v4mapped) -	    { -		family = AF_INET6; -		socklen = sizeof (struct sockaddr_in6); -	    } +			if (at2->family == AF_INET6 || v4mapped) { +				family = AF_INET6; +				socklen = sizeof(struct sockaddr_in6); +			}  #endif  #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ -	    else +			else  #endif  #if defined __UCLIBC_HAS_IPV4__ -	    { -		family = AF_INET; -		socklen = sizeof (struct sockaddr_in); -	    } +			{ +				family = AF_INET; +				socklen = sizeof(struct sockaddr_in); +			}  #endif -	    for (st2 = st; st2 != NULL; st2 = st2->next) -	    { -		if (req->ai_flags & AI_ADDRCONFIG) { -		    if (family == AF_INET && !(seen & SEEN_IPV4)) -			break; +			for (st2 = st; st2 != NULL; st2 = st2->next) { +				if (req->ai_flags & AI_ADDRCONFIG) { +					if (family == AF_INET && !(seen & SEEN_IPV4)) +						break;  #if defined __UCLIBC_HAS_IPV6__ -		    else if (family == AF_INET6 && !(seen & SEEN_IPV6)) -			break; +					else if (family == AF_INET6 && !(seen & SEEN_IPV6)) +						break;  #endif -		} -		*pai = malloc (sizeof (struct addrinfo) + socklen + namelen); -		if (*pai == NULL) -		    return -EAI_MEMORY; - -		(*pai)->ai_flags = req->ai_flags; -		(*pai)->ai_family = family; -		(*pai)->ai_socktype = st2->socktype; -		(*pai)->ai_protocol = st2->protocol; -		(*pai)->ai_addrlen = socklen; -		(*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); +				} +				*pai = malloc(sizeof(struct addrinfo) + socklen + namelen); +				if (*pai == NULL) +					return -EAI_MEMORY; + +				(*pai)->ai_flags = req->ai_flags; +				(*pai)->ai_family = family; +				(*pai)->ai_socktype = st2->socktype; +				(*pai)->ai_protocol = st2->protocol; +				(*pai)->ai_addrlen = socklen; +				(*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo);  #if SALEN -		(*pai)->ai_addr->sa_len = socklen; +				(*pai)->ai_addr->sa_len = socklen;  #endif /* SALEN */ -		(*pai)->ai_addr->sa_family = family; +				(*pai)->ai_addr->sa_family = family;  #if defined __UCLIBC_HAS_IPV6__ -		if (family == AF_INET6) -		{ -		    struct sockaddr_in6 *sin6p = -			(struct sockaddr_in6 *) (*pai)->ai_addr; - -		    sin6p->sin6_flowinfo = 0; -		    if (at2->family == AF_INET6) -		    { -			memcpy (&sin6p->sin6_addr, -				at2->addr, sizeof (struct in6_addr)); -		    } -		    else -		    { -			sin6p->sin6_addr.s6_addr32[0] = 0; -			sin6p->sin6_addr.s6_addr32[1] = 0; -			sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); -			memcpy(&sin6p->sin6_addr.s6_addr32[3], -			       at2->addr, sizeof (sin6p->sin6_addr.s6_addr32[3])); -		    } -		    sin6p->sin6_port = st2->port; -		    sin6p->sin6_scope_id = at2->scopeid; -		} +				if (family == AF_INET6)	{ +					struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; + +					sin6p->sin6_flowinfo = 0; +					if (at2->family == AF_INET6) { +						memcpy(&sin6p->sin6_addr, +							at2->addr, sizeof(struct in6_addr)); +					} else { +						sin6p->sin6_addr.s6_addr32[0] = 0; +						sin6p->sin6_addr.s6_addr32[1] = 0; +						sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); +						memcpy(&sin6p->sin6_addr.s6_addr32[3], +							at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3])); +					} +					sin6p->sin6_port = st2->port; +					sin6p->sin6_scope_id = at2->scopeid; +				}  #endif  #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ -		else +				else  #endif  #if defined __UCLIBC_HAS_IPV4__ -		{ -		    struct sockaddr_in *sinp = -			(struct sockaddr_in *) (*pai)->ai_addr; - -		    memcpy (&sinp->sin_addr, -			    at2->addr, sizeof (struct in_addr)); -		    sinp->sin_port = st2->port; -		    memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); -		} +				{ +					struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; + +					memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr)); +					sinp->sin_port = st2->port; +					memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero)); +				}  #endif -		if (c) -		{ -		    (*pai)->ai_canonname = ((void *) (*pai) + -					    sizeof (struct addrinfo) + socklen); -		    strcpy ((*pai)->ai_canonname, c); +				if (c) { +					(*pai)->ai_canonname = ((void *) (*pai) + +							sizeof(struct addrinfo) + socklen); +					strcpy((*pai)->ai_canonname, c); +				} else { +					(*pai)->ai_canonname = NULL; +				} +				(*pai)->ai_next = NULL; +				pai = &((*pai)->ai_next); +			} + +			at2 = at2->next;  		} -		else -		    (*pai)->ai_canonname = NULL; - -		(*pai)->ai_next = NULL; -		pai = &((*pai)->ai_next); -	    } - -	    at2 = at2->next;  	} -    } -    return 0; +	return 0;  } -static const struct gaih gaih[] = -{ +static const struct gaih gaih[] = {  #if defined __UCLIBC_HAS_IPV6__ -    { PF_INET6, gaih_inet }, +	{ PF_INET6, gaih_inet },  #endif -    { PF_INET, gaih_inet }, +	{ PF_INET, gaih_inet },  #if 0 -    { PF_LOCAL, gaih_local }, +	{ PF_LOCAL, gaih_local },  #endif -    { PF_UNSPEC, NULL } +	{ PF_UNSPEC, NULL }  };  libc_hidden_proto(freeaddrinfo)  void -freeaddrinfo (struct addrinfo *ai) +freeaddrinfo(struct addrinfo *ai)  { -    struct addrinfo *p; - -    while (ai != NULL) -    { -	p = ai; -	ai = ai->ai_next; -	free (p); -    } +	struct addrinfo *p; + +	while (ai != NULL) { +		p = ai; +		ai = ai->ai_next; +		free(p); +	}  }  libc_hidden_def(freeaddrinfo)  libc_hidden_proto(getaddrinfo)  int -getaddrinfo (const char *name, const char *service, +getaddrinfo(const char *name, const char *service,  	     const struct addrinfo *hints, struct addrinfo **pai)  { -    int i = 0, j = 0, last_i = 0; -    struct addrinfo *p = NULL, **end; -    const struct gaih *g = gaih, *pg = NULL; -    struct gaih_service gaih_service, *pservice; -    struct addrinfo default_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) -    { -	memset(&default_hints, 0, sizeof(default_hints)); -	if (AF_UNSPEC) -	    default_hints.ai_family = AF_UNSPEC; -	hints = &default_hints; -    } - -    if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| -			    AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) -	return EAI_BADFLAGS; - -    if ((hints->ai_flags & AI_CANONNAME) && name == NULL) -	return EAI_BADFLAGS; - -    if (service && service[0]) -    { -	char *c; -	gaih_service.name = service; -	gaih_service.num = strtoul (gaih_service.name, &c, 10); -	if (*c != '\0') { -		if (hints->ai_flags & AI_NUMERICSERV) -			return EAI_NONAME; - -	    gaih_service.num = -1; +	int i = 0, j = 0, last_i = 0; +	struct addrinfo *p = NULL, **end; +	const struct gaih *g = gaih, *pg = NULL; +	struct gaih_service gaih_service, *pservice; +	struct addrinfo default_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) { +		memset(&default_hints, 0, sizeof(default_hints)); +		if (AF_UNSPEC) +			default_hints.ai_family = AF_UNSPEC; +		hints = &default_hints;  	} + +	if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| +			AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) +		return EAI_BADFLAGS; + +	if ((hints->ai_flags & AI_CANONNAME) && name == NULL) +		return EAI_BADFLAGS; + +	if (service && service[0]) { +		char *c; +		gaih_service.name = service; +		gaih_service.num = strtoul(gaih_service.name, &c, 10); +		if (*c != '\0') { +			if (hints->ai_flags & AI_NUMERICSERV) +				return EAI_NONAME; +			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 -	    /* -	     * 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) -	{ -	    if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) -	    { -		++g; -		continue; -	    } -	    j++; -	    if (pg == NULL || pg->gaih != g->gaih) -	    { -		pg = g; -		i = g->gaih (name, pservice, hints, end); -		if (i != 0) -		{ -		    last_i = i; - -		    if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) -			continue; - -		    if (p) -			freeaddrinfo (p); - -		    return -(i & GAIH_EAI); +		end = NULL; + +	while (g->gaih) { +		if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) { +			if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) { +				++g; +				continue; +			} +			j++; +			if (pg == NULL || pg->gaih != g->gaih) { +				pg = g; +				i = g->gaih(name, pservice, hints, end); +				if (i != 0) { +					last_i = i; +					if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) +						continue; +					if (p) +						freeaddrinfo(p); +					return -(i & GAIH_EAI); +				} +				if (end) +					while (*end) +						end = &((*end)->ai_next); +			}  		} -		if (end) -		    while(*end) end = &((*end)->ai_next); -	    } +		++g;  	} -	++g; -    } -    if (j == 0) -	return EAI_FAMILY; +	if (j == 0) +		return EAI_FAMILY; -    if (p) -    { -	*pai = p; -	return 0; -    } +	if (p) { +		*pai = p; +		return 0; +	} -    if (pai == NULL && last_i == 0) -	return 0; +	if (pai == NULL && last_i == 0) +		return 0; -    if (p) -	freeaddrinfo (p); +	if (p) +		freeaddrinfo(p); -    return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME; +	return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;  }  libc_hidden_def(getaddrinfo) | 
