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

📄 name6.c

📁 用于嵌入式Linux系统的标准C的库函数
💻 C
📖 第 1 页 / 共 3 页
字号:
				bp += n;				buflen -= n;			}			break;#else			template->h_name = bp;			*errp = NETDB_SUCCESS;			return (template);#endif		case T_A:		case T_AAAA:			DNS_ASSERT(strcasecmp(template->h_name, bp) == 0);			DNS_ASSERT(n == template->h_length);			if (!haveanswer) {				int nn;				template->h_name = bp;				nn = strlen(bp) + 1;	/* for the \0 */				bp += nn;				buflen -= nn;			}#ifdef ALIGN			bp = (char *)ALIGN(bp);#else			bp = (char *)(bp);#endif			DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]);			DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]);#ifdef FILTER_V4MAPPED			if (type == T_AAAA) {				struct in6_addr in6;				memcpy(&in6, cp, sizeof(in6));				DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0);			}#endif			bcopy(cp, *hap++ = bp, n);			bp += n;			buflen -= n;			cp += n;			if (cp != erdata) {				*errp = NO_RECOVERY;				return (NULL);			}			break;		default:			abort();		}		if (!had_error)			haveanswer++;	}	if (haveanswer) {		*ap = NULL;		*hap = NULL;		if (!template->h_name) {			n = strlen(qname) + 1;	/* for the \0 */			if (n > buflen || n >= MAXHOSTNAMELEN)				goto no_recovery;			strcpy(bp, qname);			template->h_name = bp;			bp += n;			buflen -= n;		}		*errp = NETDB_SUCCESS;		return (template);	} no_recovery:	*errp = NO_RECOVERY;	return (NULL);#undef BOUNDED_INCR#undef BOUNDS_CHECK#undef DNS_ASSERT#undef DNS_FATAL}/* res_search() variant with multiple query support. */static struct hostent *_res_search_multi(name, rtl, errp)	const char *name;	/* domain name */	struct	__res_type_list *rtl; /* list of query types */	int *errp;{	const char *cp, * const *domain;	struct hostent *hp0 = NULL, *hp;	struct hostent hpbuf;	u_int dots;	int trailing_dot, ret, saved_herrno;	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;	struct __res_type_list *rtl0 = rtl;	querybuf buf;	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {		*errp = NETDB_INTERNAL;		return (NULL);	}	dots = 0;	for (cp = name; *cp; cp++)		dots += (*cp == '.');	trailing_dot = 0;	if (cp > name && *--cp == '.')		trailing_dot++;	/* If there aren't any dots, it could be a user-level alias */	if (!dots && (cp = hostalias(name)) != NULL) {		for(rtl = rtl0; rtl != NULL;		    rtl = rtl->rtl_entry) {			ret = res_query(cp, C_IN, rtl->rtl_type, buf.buf,					     sizeof(buf.buf));			if (ret > 0) {				hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)				    ? AF_INET6 : AF_INET;				hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);				hp = getanswer(&buf, ret, name, rtl->rtl_type,						    &hpbuf, errp);				if (!hp)					continue;				hp = _hpcopy(&hpbuf, errp);				hp0 = _hpmerge(hp0, hp, errp);			}		}		return (hp0);	}	/*	 * If there are dots in the name already, let's just give it a try	 * 'as is'.  The threshold can be set with the "ndots" option.	 */	saved_herrno = -1;	if (dots >= _res.ndots) {		for(rtl = rtl0; rtl != NULL;		    rtl = rtl->rtl_entry) {			ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,					      buf.buf, sizeof(buf.buf));			if (ret > 0) {				hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)				    ? AF_INET6 : AF_INET;				hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);				hp = getanswer(&buf, ret, name, rtl->rtl_type,						    &hpbuf, errp);				if (!hp)					continue;				hp = _hpcopy(&hpbuf, errp);				hp0 = _hpmerge(hp0, hp, errp);			}		}		if (hp0 != NULL)			return (hp0);		saved_herrno = *errp;		tried_as_is++;	}	/*	 * We do at least one level of search if	 *	- there is no dot and RES_DEFNAME is set, or	 *	- there is at least one dot, there is no trailing dot,	 *	  and RES_DNSRCH is set.	 */	if ((!dots && (_res.options & RES_DEFNAMES)) ||	    (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {		int done = 0;		for (domain = (const char * const *)_res.dnsrch;		     *domain && !done;		     domain++) {			for(rtl = rtl0; rtl != NULL;			    rtl = rtl->rtl_entry) {				ret = res_querydomain(name, *domain, C_IN,						      rtl->rtl_type,						      buf.buf, sizeof(buf.buf));				if (ret > 0) {					hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)					    ? AF_INET6 : AF_INET;					hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);					hp = getanswer(&buf, ret, name,					    rtl->rtl_type, &hpbuf, errp);					if (!hp)						continue;					hp = _hpcopy(&hpbuf, errp);					hp0 = _hpmerge(hp0, hp, errp);				}			}			if (hp0 != NULL)				return (hp0);			/*			 * If no server present, give up.			 * If name isn't found in this domain,			 * keep trying higher domains in the search list			 * (if that's enabled).			 * On a NO_DATA error, keep trying, otherwise			 * a wildcard entry of another type could keep us			 * from finding this entry higher in the domain.			 * If we get some other error (negative answer or			 * server failure), then stop searching up,			 * but try the input name below in case it's			 * fully-qualified.			 */			if (errno == ECONNREFUSED) {				*errp = TRY_AGAIN;				return (NULL);			}			switch (*errp) {			case NO_DATA:				got_nodata++;				/* FALLTHROUGH */			case HOST_NOT_FOUND:				/* keep trying */				break;			case TRY_AGAIN:				if (buf.hdr.rcode == SERVFAIL) {					/* try next search element, if any */					got_servfail++;					break;				}				/* FALLTHROUGH */			default:				/* anything else implies that we're done */				done++;			}			/* if we got here for some reason other than DNSRCH,			 * we only wanted one iteration of the loop, so stop.			 */			if (!(_res.options & RES_DNSRCH))				done++;		}	}	/*	 * If we have not already tried the name "as is", do that now.	 * note that we do this regardless of how many dots were in the	 * name or whether it ends with a dot unless NOTLDQUERY is set.	 */	if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {		for(rtl = rtl0; rtl != NULL;		    rtl = rtl->rtl_entry) {			ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,					      buf.buf, sizeof(buf.buf));			if (ret > 0) {				hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)				    ? AF_INET6 : AF_INET;				hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);				hp = getanswer(&buf, ret, name, rtl->rtl_type,				    &hpbuf, errp);				if (!hp)					continue;				hp = _hpcopy(&hpbuf, errp);				hp0 = _hpmerge(hp0, hp, errp);			}		}		if (hp0 != NULL)			return (hp0);	}	/* if we got here, we didn't satisfy the search.	 * if we did an initial full query, return that query's h_errno	 * (note that we wouldn't be here if that query had succeeded).	 * else if we ever got a nodata, send that back as the reason.	 * else send back meaningless h_errno, that being the one from	 * the last DNSRCH we did.	 */	if (saved_herrno != -1)		*errp = saved_herrno;	else if (got_nodata)		*errp = NO_DATA;	else if (got_servfail)		*errp = TRY_AGAIN;	return (NULL);}static int_dns_ghbyname(void *rval, void *cb_data, va_list ap){	const char *name;	int af;	int *errp;	res_type_list *rtl, rtl4;#ifdef INET6	res_type_list rtl6;#endif	name = va_arg(ap, const char *);	af = va_arg(ap, int);	errp = va_arg(ap, int *);#ifdef INET6	switch (af) {	case AF_UNSPEC:		&rtl4->rtl_entry = NULL; rtl4.rtl_type = T_A;		&rtl6->rtl_entry = &rtl4; rtl6.rtl_type = T_AAAA;		rtl = &rtl6;		break;	case AF_INET6:		&rtl6->rtl_entry = NULL; rtl6.rtl_type = T_AAAA;		rtl = &rtl6;		break;	case AF_INET:		&rtl4->rtl_entry = NULL; rtl4.rtl_type = T_A;		rtl = &rtl4;		break;	}#else	(&rtl4)->rtl_entry = NULL;        rtl4.rtl_type = T_A;	rtl = &rtl4;#endif	*(struct hostent **)rval = _res_search_multi(name, rtl, errp);	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;}static int_dns_ghbyaddr(void *rval, void *cb_data, va_list ap){	const void *addr;	int addrlen;	int af;	int *errp;	int n;	struct hostent *hp;	u_char c, *cp;	char *bp;	struct hostent hbuf;	int na;#ifdef INET6	static const char hex[] = "0123456789abcdef";#endif	querybuf buf;	char qbuf[MAXDNAME+1];	char *hlist[2];	addr = va_arg(ap, const void *);	addrlen = va_arg(ap, int);	af = va_arg(ap, int);	errp = va_arg(ap, int *);	*(struct hostent **)rval = NULL;#ifdef INET6	/* XXX */	if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))		return NS_NOTFOUND;#endif	if ((_res.options & RES_INIT) == 0) {		if (res_init() < 0) {			*errp = h_errno;			return NS_UNAVAIL;		}	}	memset(&hbuf, 0, sizeof(hbuf));	hbuf.h_name = NULL;	hbuf.h_addrtype = af;	hbuf.h_length = addrlen;	na = 0;	/* XXX assumes that MAXDNAME is big enough */	n = 0;	bp = qbuf;	cp = (u_char *)addr+addrlen-1;	switch (af) {#ifdef INET6	case AF_INET6:		for (; n < addrlen; n++, cp--) {			c = *cp;			*bp++ = hex[c & 0xf];			*bp++ = '.';			*bp++ = hex[c >> 4];			*bp++ = '.';		}		strcpy(bp, "ip6.int");		break;#endif	default:		for (; n < addrlen; n++, cp--) {			c = *cp;			if (c >= 100)				*bp++ = '0' + c / 100;			if (c >= 10)				*bp++ = '0' + (c % 100) / 10;			*bp++ = '0' + c % 10;			*bp++ = '.';		}		strcpy(bp, "in-addr.arpa");		break;	}	n = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf);	if (n < 0) {		*errp = h_errno;		return NS_UNAVAIL;	}	hp = getanswer(&buf, n, qbuf, T_PTR, &hbuf, errp);	if (!hp)		return NS_NOTFOUND;	hbuf.h_addrtype = af;	hbuf.h_length = addrlen;	hbuf.h_addr_list = hlist;	hlist[0] = (char *)addr;	hlist[1] = NULL;	*(struct hostent **)rval = _hpcopy(&hbuf, errp);	return NS_SUCCESS;}#if 0 // keep gcc happystatic void_dns_shent(int stayopen){	if ((_res.options & RES_INIT) == 0) {		if (res_init() < 0)			return;	}	if (stayopen)		_res.options |= RES_STAYOPEN | RES_USEVC;}static void_dns_ehent(void){	_res.options &= ~(RES_STAYOPEN | RES_USEVC);	res_close();}#endif#ifdef ICMPNL/* * experimental: *	draft-ietf-ipngwg-icmp-namelookups-02.txt *	ifindex is assumed to be encoded in addr. */#include <sys/uio.h>#include <netinet/ip6.h>#include <netinet/icmp6.h>struct _icmp_host_cache {	struct _icmp_host_cache *hc_next;	int hc_ifindex;	struct in6_addr hc_addr;	char *hc_name;};static char *_icmp_fqdn_query(const struct in6_addr *addr, int ifindex){	int s;	struct icmp6_filter filter;	struct msghdr msg;	struct cmsghdr *cmsg;	struct in6_pktinfo *pkt;	char cbuf[256];	char buf[1024];	int cc;	struct icmp6_fqdn_query *fq;	struct icmp6_fqdn_reply *fr;	struct _icmp_host_cache *hc;	struct sockaddr_in6 sin6;	struct iovec iov;	fd_set s_fds, fds;	struct timeval tout;	int len;	char *name;	static int pid;	static struct _icmp_host_cache *hc_head;	for (hc = hc_head; hc; hc = hc->hc_next) {		if (hc->hc_ifindex == ifindex		&&  IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr))			return hc->hc_name;	}	if (pid == 0)		pid = getpid();	ICMP6_FILTER_SETBLOCKALL(&filter);	ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);	FD_ZERO(&s_fds);	tout.tv_sec = 0;	tout.tv_usec = 200000;	/*XXX: 200ms*/	fq = (struct icmp6_fqdn_query *)buf;	fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;	fq->icmp6_fqdn_code = 0;	fq->icmp6_fqdn_cksum = 0;	fq->icmp6_fqdn_id = (u_short)pid;	fq->icmp6_fqdn_unused = 0;	fq->icmp6_fqdn_cookie[0] = 0;	fq->icmp6_fqdn_cookie[1] = 0;	memset(&sin6, 0, sizeof(sin6));	sin6.sin6_family = AF_INET6;	sin6.sin6_addr = *addr;	memset(&msg, 0, sizeof(msg));	msg.msg_name = (caddr_t)&sin6;	msg.msg_namelen = sizeof(sin6);	msg.msg_iov = &iov;	msg.msg_iovlen = 1;	msg.msg_control = NULL;	msg.msg_controllen = 0;	iov.iov_base = (caddr_t)buf;	iov.iov_len = sizeof(struct icmp6_fqdn_query);	if (ifindex) {		msg.msg_control = cbuf;		msg.msg_controllen = sizeof(cbuf);		cmsg = CMSG_FIRSTHDR(&msg);		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));		cmsg->cmsg_level = IPPROTO_IPV6;		cmsg->cmsg_type = IPV6_PKTINFO;		pkt = (struct in6_pktinfo *)&cmsg[1];		memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));		pkt->ipi6_ifindex = ifindex;		cmsg = CMSG_NXTHDR(&msg, cmsg);		msg.msg_controllen = (char *)cmsg - cbuf;	}	if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)		return NULL;	(void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,			 (char *)&filter, sizeof(filter));	cc = _sendmsg(s, &msg, 0);	if (cc < 0) {		close(s);		return NULL;	}	FD_SET(s, &s_fds);	for (;;) {		fds = s_fds;		if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) {			close(s);			return NULL;		}		len = sizeof(sin6);		cc = _recvfrom(s, buf, sizeof(buf), 0,			      (struct sockaddr *)&sin6, &len);		if (cc <= 0) {			close(s);			return NULL;		}		if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))			continue;		if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))			continue;		fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));		if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)			break;	}	close(s);	if (fr->icmp6_fqdn_cookie[1] != 0) {		/* rfc1788 type */		name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;		len = (buf + cc) - name;	} else {		len = fr->icmp6_fqdn_namelen;		name = fr->icmp6_fqdn_name;	}	if (len <= 0)		return NULL;	name[len] = 0;	if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)		return NULL;	/* XXX: limit number of cached entries */	hc->hc_ifindex = ifindex;	hc->hc_addr = *addr;	hc->hc_name = strdup(name);	hc->hc_next = hc_head;	hc_head = hc;	return hc->hc_name;}static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp){	char *hname;	int ifindex;	struct in6_addr addr6;	if (af != AF_INET6) {		/*		 * Note: rfc1788 defines Who Are You for IPv4,		 * but no one implements it.		 */		return NULL;	}	memcpy(&addr6, addr, addrlen);	ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];	addr6.s6_addr[2] = addr6.s6_addr[3] = 0;	if (!IN6_IS_ADDR_LINKLOCAL(&addr6))		return NULL;	/*XXX*/	if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)		return NULL;	return _hpaddr(af, hname, &addr6, errp);}#endif /* ICMPNL */

⌨️ 快捷键说明

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