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

📄 getaddrinfo.c

📁 用于嵌入式Linux系统的标准C的库函数
💻 C
📖 第 1 页 / 共 4 页
字号:
		case SOCK_STREAM:			proto = "tcp";			break;		default:			proto = NULL;			break;		}		if ((sp = getservbyname(servname, proto)) == NULL)			return EAI_SERVICE;		port = sp->s_port;	}	if (!matchonly) {		switch (ai->ai_family) {		case AF_INET:			((struct sockaddr_in *)(void *)			    ai->ai_addr)->sin_port = port;			break;#ifdef INET6		case AF_INET6:			((struct sockaddr_in6 *)(void *)			    ai->ai_addr)->sin6_port = port;			break;#endif		}	}	return 0;}static const struct afd *find_afd(af)	int af;{	const struct afd *afd;	if (af == PF_UNSPEC)		return NULL;	for (afd = afdl; afd->a_af; afd++) {		if (afd->a_af == af)			return afd;	}	return NULL;}/* * post-2553: AI_ADDRCONFIG check.  if we use getipnodeby* as backend, backend * will take care of it. * the semantics of AI_ADDRCONFIG is not defined well.  we are not sure * if the code is right or not. * * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with * _dns_getaddrinfo. */static intaddrconfig(pai)	struct addrinfo *pai;{	int s, af;	/*	 * TODO:	 * Note that implementation dependent test for address	 * configuration should be done everytime called	 * (or apropriate interval),	 * because addresses will be dynamically assigned or deleted.	 */	af = pai->ai_family;	if (af == AF_UNSPEC) {		if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)			af = AF_INET;		else {			close(s);			if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)				af = AF_INET6;			else				close(s);		}	}	if (af != AF_UNSPEC) {		if ((s = socket(af, SOCK_DGRAM, 0)) < 0)			return 0;		close(s);	}	pai->ai_family = af;	return 1;}#ifdef INET6/* convert a string to a scope identifier. XXX: IPv6 specific */static intip6_str2scopeid(scope, sin6)	char *scope;	struct sockaddr_in6 *sin6;{	int scopeid;	struct in6_addr *a6 = &sin6->sin6_addr;	char *ep;	/* empty scopeid portion is invalid */	if (*scope == '\0')		return -1;	if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {		/*		 * We currently assume a one-to-one mapping between links		 * and interfaces, so we simply use interface indices for		 * like-local scopes.		 */		scopeid = if_nametoindex(scope);		if (scopeid == 0)			goto trynumeric;		return(scopeid);	}	/* still unclear about literal, allow numeric only - placeholder */	if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))		goto trynumeric;	if (IN6_IS_ADDR_MC_ORGLOCAL(a6))		goto trynumeric;	else		goto trynumeric;	/* global */	/* try to convert to a numeric id as a last resort */  trynumeric:	scopeid = (int)strtoul(scope, &ep, 10);	if (*ep == '\0')		return scopeid;	else		return -1;}#endif#ifdef DEBUGstatic const char AskedForGot[] =	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";#endifstatic FILE *hostf = NULL;static struct addrinfo *getanswer(answer, anslen, qname, qtype, pai)	const querybuf *answer;	int anslen;	const char *qname;	int qtype;	const struct addrinfo *pai;{	struct addrinfo sentinel, *cur;	struct addrinfo ai;	const struct afd *afd;	char *canonname;	const HEADER *hp;	const u_char *cp;	int n;	const u_char *eom;	char *bp;	int type, class, buflen, ancount, qdcount;	int haveanswer, had_error;	char tbuf[MAXDNAME];	int (*name_ok)(const char *);	char hostbuf[8*1024];	memset(&sentinel, 0, sizeof(sentinel));	cur = &sentinel;	canonname = NULL;	eom = answer->buf + anslen;	switch (qtype) {	case T_A:	case T_AAAA:	case T_ANY:	/*use T_ANY only for T_A/T_AAAA lookup*/		name_ok = res_hnok;		break;	default:		return (NULL);	/* XXX should be abort(); */	}	/*	 * find first satisfactory answer	 */	hp = &answer->hdr;	ancount = ntohs(hp->ancount);	qdcount = ntohs(hp->qdcount);	bp = hostbuf;	buflen = sizeof hostbuf;	cp = answer->buf + HFIXEDSZ;	if (qdcount != 1) {		h_errno = NO_RECOVERY;		return (NULL);	}	n = dn_expand(answer->buf, eom, cp, bp, buflen);	if ((n < 0) || !(*name_ok)(bp)) {		h_errno = NO_RECOVERY;		return (NULL);	}	cp += n + QFIXEDSZ;	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {		/* res_send() has already verified that the query name is the		 * same as the one we sent; this just gets the expanded name		 * (i.e., with the succeeding search-domain tacked on).		 */		n = strlen(bp) + 1;		/* for the \0 */		if (n >= MAXHOSTNAMELEN) {			h_errno = NO_RECOVERY;			return (NULL);		}		canonname = bp;		bp += n;		buflen -= n;		/* The qname can be abbreviated, but h_name is now absolute. */		qname = canonname;	}	haveanswer = 0;	had_error = 0;	while (ancount-- > 0 && cp < eom && !had_error) {		n = dn_expand(answer->buf, eom, cp, bp, buflen);		if ((n < 0) || !(*name_ok)(bp)) {			had_error++;			continue;		}		cp += n;			/* name */		type = _getshort(cp); 		cp += INT16SZ;			/* type */		class = _getshort(cp); 		cp += INT16SZ + INT32SZ;	/* class, TTL */		n = _getshort(cp);		cp += INT16SZ;			/* len */		if (class != C_IN) {			/* XXX - debug? syslog? */			cp += n;			continue;		/* XXX - had_error++ ? */		}		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&		    type == T_CNAME) {			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);			if ((n < 0) || !(*name_ok)(tbuf)) {				had_error++;				continue;			}			cp += n;			/* Get canonical name. */			n = strlen(tbuf) + 1;	/* for the \0 */			if (n > buflen || n >= MAXHOSTNAMELEN) {				had_error++;				continue;			}			strcpy(bp, tbuf);			canonname = bp;			bp += n;			buflen -= n;			continue;		}		if (qtype == T_ANY) {			if (!(type == T_A || type == T_AAAA)) {				cp += n;				continue;			}		} else if (type != qtype) {#ifdef DEBUG			if (type != T_KEY && type != T_SIG)				syslog(LOG_NOTICE|LOG_AUTH,	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",				       qname, p_class(C_IN), p_type(qtype),				       p_type(type));#endif			cp += n;			continue;		/* XXX - had_error++ ? */		}		switch (type) {		case T_A:		case T_AAAA:			if (strcasecmp(canonname, bp) != 0) {#ifdef DEBUG				syslog(LOG_NOTICE|LOG_AUTH,				       AskedForGot, canonname, bp);#endif				cp += n;				continue;	/* XXX - had_error++ ? */			}			if (type == T_A && n != INADDRSZ) {				cp += n;				continue;			}			if (type == T_AAAA && n != IN6ADDRSZ) {				cp += n;				continue;			}#ifdef FILTER_V4MAPPED			if (type == T_AAAA) {				struct in6_addr in6;				memcpy(&in6, cp, sizeof(in6));				if (IN6_IS_ADDR_V4MAPPED(&in6)) {					cp += n;					continue;				}			}#endif			if (!haveanswer) {				int nn;				canonname = bp;				nn = strlen(bp) + 1;	/* for the \0 */				bp += nn;				buflen -= nn;			}			/* don't overwrite pai */			ai = *pai;			ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;			afd = find_afd(ai.ai_family);			if (afd == NULL) {				cp += n;				continue;			}			cur->ai_next = get_ai(&ai, afd, (const char *)cp);			if (cur->ai_next == NULL)				had_error++;			while (cur && cur->ai_next)				cur = cur->ai_next;			cp += n;			break;		default:			abort();		}		if (!had_error)			haveanswer++;	}	if (haveanswer) {		if (!canonname)			(void)get_canonname(pai, sentinel.ai_next, qname);		else			(void)get_canonname(pai, sentinel.ai_next, canonname);		h_errno = NETDB_SUCCESS;		return sentinel.ai_next;	}	h_errno = NO_RECOVERY;	return NULL;}/*ARGSUSED*/static int_dns_getaddrinfo(rv, cb_data, ap)	void	*rv;	void	*cb_data;	va_list	 ap;{	struct addrinfo *ai;	querybuf buf, buf2;	const char *name;	const struct addrinfo *pai;	struct addrinfo sentinel, *cur;	struct res_target q, q2;	name = va_arg(ap, char *);	pai = va_arg(ap, const struct addrinfo *);	memset(&q, 0, sizeof(q2));	memset(&q2, 0, sizeof(q2));	memset(&sentinel, 0, sizeof(sentinel));	cur = &sentinel;	switch (pai->ai_family) {	case AF_UNSPEC:		/* prefer IPv6 */		q.qclass = C_IN;		q.qtype = T_AAAA;		q.answer = buf.buf;		q.anslen = sizeof(buf);		q.next = &q2;		q2.qclass = C_IN;		q2.qtype = T_A;		q2.answer = buf2.buf;		q2.anslen = sizeof(buf2);		break;	case AF_INET:		q.qclass = C_IN;		q.qtype = T_A;		q.answer = buf.buf;		q.anslen = sizeof(buf);		break;	case AF_INET6:		q.qclass = C_IN;		q.qtype = T_AAAA;		q.answer = buf.buf;		q.anslen = sizeof(buf);		break;	default:		return NS_UNAVAIL;	}	if (res_searchN(name, &q) < 0)		return NS_NOTFOUND;	ai = getanswer(&buf, q.n, q.name, q.qtype, pai);	if (ai) {		cur->ai_next = ai;		while (cur && cur->ai_next)			cur = cur->ai_next;	}	if (q.next) {		ai = getanswer(&buf2, q2.n, q2.name, q2.qtype, pai);		if (ai)			cur->ai_next = ai;	}	if (sentinel.ai_next == NULL)		switch (h_errno) {		case HOST_NOT_FOUND:			return NS_NOTFOUND;		case TRY_AGAIN:			return NS_TRYAGAIN;		default:			return NS_UNAVAIL;		}	*((struct addrinfo **)rv) = sentinel.ai_next;	return NS_SUCCESS;}static void_sethtent(){	if (!hostf)		hostf = fopen(_PATH_HOSTS, "r" );	else		rewind(hostf);}static void_endhtent(){	if (hostf) {		(void) fclose(hostf);		hostf = NULL;	}}static struct addrinfo *_gethtent(name, pai)	const char *name;	const struct addrinfo *pai;{	char *p;	char *cp, *tname, *cname;	struct addrinfo hints, *res0, *res;	int error;	const char *addr;	char hostbuf[8*1024];	if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))		return (NULL); again:	if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))		return (NULL);	if (*p == '#')		goto again;	if (!(cp = strpbrk(p, "#\n")))		goto again;	*cp = '\0';	if (!(cp = strpbrk(p, " \t")))		goto again;	*cp++ = '\0';	addr = p;	cname = NULL;	/* if this is not something we're looking for, skip it. */	while (cp && *cp) {		if (*cp == ' ' || *cp == '\t') {			cp++;			continue;		}		tname = cp;		if (cname == NULL)			cname = cp;		if ((cp = strpbrk(cp, " \t")) != NULL)			*cp++ = '\0';		if (strcasecmp(name, tname) == 0)			goto found;	}	goto again;found:	hints = *pai;	hints.ai_flags = AI_NUMERICHOST;	error = getaddrinfo(addr, NULL, &hints, &res0);	if (error)		goto again;#ifdef FILTER_V4MAPPED	/* XXX should check all items in the chain */	if (res0->ai_family == AF_INET6 &&	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {		freeaddrinfo(res0);		goto again;	}#endif	for (res = res0; res; res = res->ai_next) {		/* cover it up */		res->ai_flags = pai->ai_flags;

⌨️ 快捷键说明

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