⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getaddrinfo.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			pai->ai_family = ex->e_af;		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)			pai->ai_socktype = ex->e_socktype;		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)			pai->ai_protocol = ex->e_protocol;		if (hostname == NULL)			error = explore_null(pai, servname, &cur->ai_next);		else			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);		if (error)			goto free;		while (cur && cur->ai_next)			cur = cur->ai_next;	}	/*	 * XXX	 * If numreic representation of AF1 can be interpreted as FQDN	 * representation of AF2, we need to think again about the code below.	 */	if (sentinel.ai_next)		goto good;	if (pai->ai_flags & AI_NUMERICHOST)		ERR(EAI_NONAME);	if (hostname == NULL)		ERR(EAI_NODATA);	if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))		ERR(EAI_FAIL);	/*	 * hostname as alphabetical name.	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a	 * outer loop by AFs.	 */	for (ex = explore; ex->e_af >= 0; ex++) {		*pai = ai0;		/* require exact match for family field */		if (pai->ai_family != ex->e_af)			continue;		if (!MATCH(pai->ai_socktype, ex->e_socktype,				WILD_SOCKTYPE(ex))) {			continue;		}		if (!MATCH(pai->ai_protocol, ex->e_protocol,				WILD_PROTOCOL(ex))) {			continue;		}		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)			pai->ai_socktype = ex->e_socktype;		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)			pai->ai_protocol = ex->e_protocol;		error = explore_fqdn(pai, hostname, servname,			&cur->ai_next);		while (cur && cur->ai_next)			cur = cur->ai_next;	}	/* XXX */	if (sentinel.ai_next)		error = 0;	if (error)		goto free;	if (error == 0) {		if (sentinel.ai_next) { good:			*res = sentinel.ai_next;			return SUCCESS;		} else			error = EAI_FAIL;	} free: bad:	if (sentinel.ai_next)		freeaddrinfo(sentinel.ai_next);	*res = NULL;	return error;}/* * FQDN hostname, DNS lookup */static intexplore_fqdn(pai, hostname, servname, res)	const struct addrinfo *pai;	const char *hostname;	const char *servname;	struct addrinfo **res;{	struct addrinfo *result;	struct addrinfo *cur;	int error = 0;	static const ns_dtab dtab[] = {		NS_FILES_CB(_files_getaddrinfo, NULL)		{ NSSRC_DNS, _dns_getaddrinfo, NULL },	/* force -DHESIOD */		NS_NIS_CB(_yp_getaddrinfo, NULL)		{ 0 }	};	result = NULL;	/*	 * if the servname does not match socktype/protocol, ignore it.	 */	if (get_portmatch(pai, servname) != 0)		return 0;	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",			default_dns_files, hostname, pai)) {	case NS_TRYAGAIN:		error = EAI_AGAIN;		goto free;	case NS_UNAVAIL:		error = EAI_FAIL;		goto free;	case NS_NOTFOUND:		error = EAI_NODATA;		goto free;	case NS_SUCCESS:		error = 0;		for (cur = result; cur; cur = cur->ai_next) {			GET_PORT(cur, servname);			/* canonname should be filled already */		}		break;	}	*res = result;	return 0;free:	if (result)		freeaddrinfo(result);	return error;}/* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */static intexplore_null(pai, servname, res)	const struct addrinfo *pai;	const char *servname;	struct addrinfo **res;{	int s;	const struct afd *afd;	struct addrinfo *cur;	struct addrinfo sentinel;	int error;	*res = NULL;	sentinel.ai_next = NULL;	cur = &sentinel;	/*	 * filter out AFs that are not supported by the kernel	 * XXX errno?	 */	s = socket(pai->ai_family, SOCK_DGRAM, 0);	if (s < 0) {		if (errno != EMFILE)			return 0;	} else		close(s);	/*	 * if the servname does not match socktype/protocol, ignore it.	 */	if (get_portmatch(pai, servname) != 0)		return 0;	afd = find_afd(pai->ai_family);	if (afd == NULL)		return 0;	if (pai->ai_flags & AI_PASSIVE) {		GET_AI(cur->ai_next, afd, afd->a_addrany);		/* xxx meaningless?		 * GET_CANONNAME(cur->ai_next, "anyaddr");		 */		GET_PORT(cur->ai_next, servname);	} else {		GET_AI(cur->ai_next, afd, afd->a_loopback);		/* xxx meaningless?		 * GET_CANONNAME(cur->ai_next, "localhost");		 */		GET_PORT(cur->ai_next, servname);	}	cur = cur->ai_next;	*res = sentinel.ai_next;	return 0;free:	if (sentinel.ai_next)		freeaddrinfo(sentinel.ai_next);	return error;}/* * numeric hostname */static intexplore_numeric(pai, hostname, servname, res)	const struct addrinfo *pai;	const char *hostname;	const char *servname;	struct addrinfo **res;{	const struct afd *afd;	struct addrinfo *cur;	struct addrinfo sentinel;	int error;	char pton[PTON_MAX];	*res = NULL;	sentinel.ai_next = NULL;	cur = &sentinel;	/*	 * if the servname does not match socktype/protocol, ignore it.	 */	if (get_portmatch(pai, servname) != 0)		return 0;	afd = find_afd(pai->ai_family);	if (afd == NULL)		return 0;	switch (afd->a_af) {#if 1 /*X/Open spec*/	case AF_INET:		if (inet_aton(hostname, (struct in_addr *)pton) == 1) {			if (pai->ai_family == afd->a_af ||			    pai->ai_family == PF_UNSPEC /*?*/) {				GET_AI(cur->ai_next, afd, pton);				GET_PORT(cur->ai_next, servname);				while (cur && cur->ai_next)					cur = cur->ai_next;			} else				ERR(EAI_FAMILY);	/*xxx*/		}		break;#endif	default:		if (inet_pton(afd->a_af, hostname, pton) == 1) {			if (pai->ai_family == afd->a_af ||			    pai->ai_family == PF_UNSPEC /*?*/) {				GET_AI(cur->ai_next, afd, pton);				GET_PORT(cur->ai_next, servname);				while (cur && cur->ai_next)					cur = cur->ai_next;			} else				ERR(EAI_FAMILY);	/*xxx*/		}		break;	}	*res = sentinel.ai_next;	return 0;free:bad:	if (sentinel.ai_next)		freeaddrinfo(sentinel.ai_next);	return error;}/* * numeric hostname with scope */static intexplore_numeric_scope(pai, hostname, servname, res)	const struct addrinfo *pai;	const char *hostname;	const char *servname;	struct addrinfo **res;{#if !defined(SCOPE_DELIMITER) || !defined(INET6)	return explore_numeric(pai, hostname, servname, res);#else	const struct afd *afd;	struct addrinfo *cur;	int error;	char *cp, *hostname2 = NULL, *scope, *addr;	struct sockaddr_in6 *sin6;	/*	 * if the servname does not match socktype/protocol, ignore it.	 */	if (get_portmatch(pai, servname) != 0)		return 0;	afd = find_afd(pai->ai_family);	if (afd == NULL)		return 0;	if (!afd->a_scoped)		return explore_numeric(pai, hostname, servname, res);	cp = strchr(hostname, SCOPE_DELIMITER);	if (cp == NULL)		return explore_numeric(pai, hostname, servname, res);	/*	 * Handle special case of <scoped_address><delimiter><scope id>	 */	hostname2 = strdup(hostname);	if (hostname2 == NULL)		return EAI_MEMORY;	/* terminate at the delimiter */	hostname2[cp - hostname] = '\0';	addr = hostname2;	scope = cp + 1;	error = explore_numeric(pai, addr, servname, res);	if (error == 0) {		int scopeid;		for (cur = *res; cur; cur = cur->ai_next) {			if (cur->ai_family != AF_INET6)				continue;			sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;			if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) {				free(hostname2);				return(EAI_NODATA); /* XXX: is return OK? */			}			sin6->sin6_scope_id = scopeid;		}	}	free(hostname2);	return error;#endif}static intget_canonname(pai, ai, str)	const struct addrinfo *pai;	struct addrinfo *ai;	const char *str;{	if ((pai->ai_flags & AI_CANONNAME) != 0) {		ai->ai_canonname = (char *)malloc(strlen(str) + 1);		if (ai->ai_canonname == NULL)			return EAI_MEMORY;		strcpy(ai->ai_canonname, str);	}	return 0;}static struct addrinfo *get_ai(pai, afd, addr)	const struct addrinfo *pai;	const struct afd *afd;	const char *addr;{	char *p;	struct addrinfo *ai;#ifdef FAITH	struct in6_addr faith_prefix;	char *fp_str;	int translate = 0;#endif#ifdef FAITH	/*	 * Transfrom an IPv4 addr into a special IPv6 addr format for	 * IPv6->IPv4 translation gateway. (only TCP is supported now)	 *	 * +-----------------------------------+------------+	 * | faith prefix part (12 bytes)      | embedded   |	 * |                                   | IPv4 addr part (4 bytes)	 * +-----------------------------------+------------+	 *	 * faith prefix part is specified as ascii IPv6 addr format	 * in environmental variable GAI.	 * For FAITH to work correctly, routing to faith prefix must be	 * setup toward a machine where a FAITH daemon operates.	 * Also, the machine must enable some mechanizm	 * (e.g. faith interface hack) to divert those packet with	 * faith prefixed destination addr to user-land FAITH daemon.	 */	fp_str = getenv("GAI");	if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&	    afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {		u_int32_t v4a;		u_int8_t v4a_top;		memcpy(&v4a, addr, sizeof v4a);		v4a_top = v4a >> IN_CLASSA_NSHIFT;		if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&		    v4a_top != 0 && v4a != IN_LOOPBACKNET) {			afd = &afdl[N_INET6];			memcpy(&faith_prefix.s6_addr[12], addr,			       sizeof(struct in_addr));			translate = 1;		}	}#endif	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)		+ (afd->a_socklen));	if (ai == NULL)		return NULL;	memcpy(ai, pai, sizeof(struct addrinfo));	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);	ai->ai_addrlen = afd->a_socklen;	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;	p = (char *)(void *)(ai->ai_addr);#ifdef FAITH	if (translate == 1)		memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);	else#endif	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);	return ai;}static intget_portmatch(ai, servname)	const struct addrinfo *ai;	const char *servname;{	/* get_port does not touch first argument. when matchonly == 1. */	/* LINTED const cast */	return get_port((struct addrinfo *)ai, servname, 1);}static intget_port(ai, servname, matchonly)	struct addrinfo *ai;	const char *servname;	int matchonly;{	const char *proto;	struct servent *sp;	int port;	int allownumeric;	if (servname == NULL)		return 0;	switch (ai->ai_family) {	case AF_INET:#ifdef AF_INET6	case AF_INET6:#endif		break;	default:		return 0;	}	switch (ai->ai_socktype) {	case SOCK_RAW:		return EAI_SERVICE;	case SOCK_DGRAM:	case SOCK_STREAM:		allownumeric = 1;		break;	case ANY:		allownumeric = 0;		break;	default:		return EAI_SOCKTYPE;	}	if (str_isnumber(servname)) {		if (!allownumeric)			return EAI_SERVICE;		port = htons(atoi(servname));		if (port < 0 || port > 65535)			return EAI_SERVICE;	} else {		switch (ai->ai_socktype) {		case SOCK_DGRAM:			proto = "udp";			break;

⌨️ 快捷键说明

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