getaddrinfo.c

来自「Axis 221 camera embedded programing inte」· C语言 代码 · 共 874 行 · 第 1/2 页

C
874
字号
    }    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 __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;		    }		}	    }	}#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 __UCLIBC_HAS_IPV6__	    if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)		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))))		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));	if (req->ai_family == 0)	{	    at->next = alloca (sizeof (struct gaih_addrtuple));	    memset (at->next, '\0', sizeof (struct gaih_addrtuple));	}#if __UCLIBC_HAS_IPV6__	if (req->ai_family == 0 || req->ai_family == AF_INET6)	{	    extern const struct in6_addr __in6addr_loopback;	    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 (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"];	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 __UCLIBC_HAS_IPV6__	    if (at2->family == AF_INET6 || v4mapped)	    {		family = AF_INET6;		socklen = sizeof (struct sockaddr_in6);	    }	    else#endif	    {		family = AF_INET;		socklen = sizeof (struct sockaddr_in);	    }	    for (st2 = st; st2 != NULL; st2 = st2->next)	    {		*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;#endif /* SALEN */		(*pai)->ai_addr->sa_family = family;#if __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;		}		else#endif		{		    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));		}		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;	}    }    return 0;}static struct gaih gaih[] ={#if __UCLIBC_HAS_IPV6__    { PF_INET6, gaih_inet },#endif    { PF_INET, gaih_inet },#if 0    { PF_LOCAL, gaih_local },#endif    { PF_UNSPEC, NULL }};intgetaddrinfo (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;    struct gaih *g = gaih, *pg = NULL;    struct gaih_service gaih_service, *pservice;    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|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)	    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)	{	    if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family))		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);	    }	}	++g;    }    if (j == 0)	return EAI_FAMILY;    if (p)    {	*pai = p;	return 0;    }    if (pai == NULL && last_i == 0)	return 0;    if (p)	freeaddrinfo (p);    return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;}voidfreeaddrinfo (struct addrinfo *ai){    struct addrinfo *p;    while (ai != NULL)    {	p = ai;	ai = ai->ai_next;	free (p);    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?