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

📄 dns_ho.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
		RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL);		errno = ENOMEM;		goto cleanup;	}	memset(q, 0, sizeof(q2));	memset(q2, 0, sizeof(q2));	switch (pai->ai_family) {	case AF_UNSPEC:		/* prefer IPv6 */		q->qclass = C_IN;		q->qtype = T_AAAA;		q->answer = q->qbuf.buf;		q->anslen = sizeof(q->qbuf);		q->next = q2;		q->action = RESTGT_DOALWAYS;		q2->qclass = C_IN;		q2->qtype = T_A;		q2->answer = q2->qbuf.buf;		q2->anslen = sizeof(q2->qbuf);		q2->action = RESTGT_DOALWAYS;		break;	case AF_INET:		q->qclass = C_IN;		q->qtype = T_A;		q->answer = q->qbuf.buf;		q->anslen = sizeof(q->qbuf);		q->action = RESTGT_DOALWAYS;		break;	case AF_INET6:		q->qclass = C_IN;		q->qtype = T_AAAA;		q->answer = q->qbuf.buf;		q->anslen = sizeof(q->qbuf);		q->action = RESTGT_DOALWAYS;		break;	default:		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /* better error? */		goto cleanup;	}	/*	 * if there aren't any dots, it could be a user-level alias.	 * this is also done in res_nquery() since we are not the only	 * function that looks up host names.	 */	if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name,						      tmp, sizeof tmp)))		name = cp;	for (p = q; p; p = p->next) {		struct addrinfo *ai;		switch(p->action) {		case RESTGT_DOALWAYS:			break;		case RESTGT_AFTERFAILURE:			if (querystate == RESQRY_SUCCESS)				continue;			break;		case RESTGT_IGNORE:			continue;		}		if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype,				     p->answer, p->anslen)) < 0) {			querystate = RESQRY_FAIL;			continue;		}		(void)gethostans(this, p->answer, n, name, p->qtype,				 pai->ai_family, /* XXX: meaningless */				 0, &ai, pai);		if (ai) {			querystate = RESQRY_SUCCESS;			cur->ai_next = ai;			while (cur && cur->ai_next)				cur = cur->ai_next;		}		else			querystate = RESQRY_FAIL;	} cleanup:	if (q != NULL)		memput(q, sizeof(*q));	if (q2 != NULL)		memput(q2, sizeof(*q2));	return(sentinel.ai_next);}static voidho_res_set(struct irs_ho *this, struct __res_state *res,		void (*free_res)(void *)) {	struct pvt *pvt = (struct pvt *)this->private;	if (pvt->res && pvt->free_res) {		res_nclose(pvt->res);		(*pvt->free_res)(pvt->res);	}	pvt->res = res;	pvt->free_res = free_res;}/* Private. */static struct hostent *gethostans(struct irs_ho *this,	   const u_char *ansbuf, int anslen, const char *qname, int qtype,	   int af, int size,	/* meaningless for addrinfo cases */	   struct addrinfo **ret_aip, const struct addrinfo *pai){	struct pvt *pvt = (struct pvt *)this->private;	int type, class, ancount, qdcount, n, haveanswer, had_error;	int error = NETDB_SUCCESS, arcount;	int (*name_ok)(const char *);	const HEADER *hp;	const u_char *eom;	const u_char *eor;	const u_char *cp;	const char *tname;	const char *hname;	char *bp, *ep, **ap, **hap;	char tbuf[MAXDNAME+1];	struct addrinfo sentinel, *cur, ai;	if (pai == NULL) abort();	if (ret_aip != NULL)		*ret_aip = NULL;	memset(&sentinel, 0, sizeof(sentinel));	cur = &sentinel;	tname = qname;	eom = ansbuf + 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;	case T_PTR:		name_ok = res_dnok;		break;	default:		abort();	}	pvt->host.h_addrtype = af;	pvt->host.h_length = size;	hname = pvt->host.h_name = NULL;	/*	 * Find first satisfactory answer.	 */	if (ansbuf + HFIXEDSZ > eom) {		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);		return (NULL);	}	hp = (const HEADER *)ansbuf;	ancount = ntohs(hp->ancount);	qdcount = ntohs(hp->qdcount);	arcount = ntohs(hp->arcount);	bp = pvt->hostbuf;	ep = pvt->hostbuf + sizeof(pvt->hostbuf);	cp = ansbuf + HFIXEDSZ;	if (qdcount != 1) {		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);		return (NULL);	}	n = dn_expand(ansbuf, eom, cp, bp, ep - bp);	if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);		return (NULL);	}	cp += n + QFIXEDSZ;	if (cp > eom) {		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);		return (NULL);	}	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {		/* res_nsend() 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) {			RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);			return (NULL);		}		pvt->host.h_name = bp;		hname = bp;		bp += n;		/* The qname can be abbreviated, but hname is now absolute. */		qname = pvt->host.h_name;	}	ap = pvt->host_aliases;	*ap = NULL;	pvt->host.h_aliases = pvt->host_aliases;	hap = pvt->h_addr_ptrs;	*hap = NULL;	pvt->host.h_addr_list = pvt->h_addr_ptrs;	haveanswer = 0;	had_error = 0;	while (ancount-- > 0 && cp < eom && !had_error) {		n = dn_expand(ansbuf, eom, cp, bp, ep - bp);		if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {			had_error++;			continue;		}		cp += n;			/* name */		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);		type = ns_get16(cp); 		cp += INT16SZ;			/* type */		class = ns_get16(cp); 		cp += INT16SZ + INT32SZ;	/* class, TTL */		n = ns_get16(cp);		cp += INT16SZ;			/* len */		BOUNDS_CHECK(cp, n);		if (class != C_IN) {			cp += n;			continue;		}		eor = cp + n;		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&		    type == T_CNAME) {			if (haveanswer) {				int level = LOG_CRIT;#ifdef LOG_SECURITY				level |= LOG_SECURITY;#endif				syslog(level, "gethostans: possible attempt to exploit buffer overflow while looking up %s",					*qname ? qname : ".");			}			n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf);			if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) {				had_error++;				continue;			}			cp += n;			/* Store alias. */			if (ap >= &pvt->host_aliases[MAXALIASES-1])				continue;			*ap++ = bp;			n = strlen(bp) + 1;	/* for the \0 */			bp += n;			/* Get canonical name. */			n = strlen(tbuf) + 1;	/* for the \0 */			if (n > (ep - bp) || n > MAXHOSTNAMELEN) {				had_error++;				continue;			}			strcpy(bp, tbuf);	/* (checked) */			pvt->host.h_name = bp;			hname = bp;			bp += n;			continue;		}		if (qtype == T_PTR && type == T_CNAME) {			n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf);			if (n < 0 || !maybe_dnok(pvt->res, tbuf)) {				had_error++;				continue;			}			cp += n;#ifdef RES_USE_DNAME			if ((pvt->res->options & RES_USE_DNAME) != 0U)#endif			{				/*				 * We may be able to check this regardless				 * of the USE_DNAME bit, but we add the check				 * for now since the DNAME support is				 * experimental.				 */				if (ns_samename(tname, bp) != 1)					continue;			}			/* Get canonical name. */			n = strlen(tbuf) + 1;	/* for the \0 */			if (n > (ep - bp)) {				had_error++;				continue;			}			strcpy(bp, tbuf);	/* (checked) */			tname = bp;			bp += n;			continue;		}		if (qtype == T_ANY) {			if (!(type == T_A || type == T_AAAA)) {				cp += n;				continue;			}		} else if (type != qtype) {			cp += n;			continue;		}		switch (type) {		case T_PTR:			if (ret_aip != NULL) {				/* addrinfo never needs T_PTR */				cp += n;				continue;			}			if (ns_samename(tname, bp) != 1) {				cp += n;				continue;			}			n = dn_expand(ansbuf, eor, cp, bp, ep - bp);			if (n < 0 || !maybe_hnok(pvt->res, bp) ||			    n >= MAXHOSTNAMELEN) {				had_error++;				break;			}			cp += n;			if (!haveanswer) {				pvt->host.h_name = bp;				hname = bp;			}			else if (ap < &pvt->host_aliases[MAXALIASES-1])				*ap++ = bp;			else				n = -1;			if (n != -1) {				n = strlen(bp) + 1;	/* for the \0 */				bp += n;			}			break;		case T_A:		case T_AAAA:			if (ns_samename(hname, bp) != 1) {				cp += n;				continue;			}			if (type == T_A && n != INADDRSZ) {				cp += n;				continue;			}			if (type == T_AAAA && n != IN6ADDRSZ) {				cp += n;				continue;			}			/* make addrinfo. don't overwrite constant PAI */			ai = *pai;			ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET;			cur->ai_next = addr2addrinfo(					(const struct addrinfo *)&ai,					(const char *)cp);			if (cur->ai_next == NULL)				had_error++;			if (!haveanswer) {				int nn;				nn = strlen(bp) + 1;	/* for the \0 */				if (nn >= MAXHOSTNAMELEN) {					cp += n;					had_error++;					continue;				}				pvt->host.h_name = bp;				hname = bp;				bp += nn;			}			/* Ensure alignment. */			bp = (char *)(((u_long)bp + (sizeof(align) - 1)) &				      ~(sizeof(align) - 1));			/* Avoid overflows. */			if (bp + n >= &pvt->hostbuf[sizeof pvt->hostbuf]) {				had_error++;				continue;			}			if (ret_aip) { /* need addrinfo. keep it. */				while (cur && cur->ai_next)					cur = cur->ai_next;			} else if (cur->ai_next) { /* need hostent */				struct addrinfo *aip = cur->ai_next;				for (aip = cur->ai_next; aip;				     aip = aip->ai_next) {					int m;					m = add_hostent(pvt, bp, hap, aip);					if (m < 0) {						had_error++;						break;					}					if (m == 0)						continue;					if (hap < &pvt->h_addr_ptrs[MAXADDRS-1])						hap++;					*hap = NULL;					bp += m;				}				freeaddrinfo(cur->ai_next);				cur->ai_next = NULL;			}			cp += n;			break;		default:			abort();		}		if (!had_error)			haveanswer++;	}	if (haveanswer) {		if (ret_aip == NULL) {			*ap = NULL;			*hap = NULL;			if (pvt->res->nsort && haveanswer > 1 && qtype == T_A)				addrsort(pvt->res, pvt->h_addr_ptrs,					 haveanswer);			if (pvt->host.h_name == NULL) {				n = strlen(qname) + 1;	/* for the \0 */				if (n > (ep - bp) || n >= MAXHOSTNAMELEN)					goto no_recovery;				strcpy(bp, qname);	/* (checked) */				pvt->host.h_name = bp;				bp += n;			}			if (pvt->res->options & RES_USE_INET6)				map_v4v6_hostent(&pvt->host, &bp, ep);			RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);			return (&pvt->host);		} else {			if ((pai->ai_flags & AI_CANONNAME) != 0) {				if (pvt->host.h_name == NULL) {					sentinel.ai_next->ai_canonname =						strdup(qname);				}				else {					sentinel.ai_next->ai_canonname =						strdup(pvt->host.h_name);				}			}			*ret_aip = sentinel.ai_next;			return(NULL);		}	} no_recovery:	if (sentinel.ai_next) {		/* this should be impossible, but check it for safety */		freeaddrinfo(sentinel.ai_next);	}	if (error == NETDB_SUCCESS)		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);	else		RES_SET_H_ERRNO(pvt->res, error);	return(NULL);}static intadd_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai){	int addrlen;	char *addrp;	const char **tap;	char *obp = bp;	switch(ai->ai_addr->sa_family) {	case AF_INET6:		addrlen = IN6ADDRSZ;		addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;		break;	case AF_INET:		addrlen = INADDRSZ;		addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;		break;	default:		return(-1);	/* abort? */	}	/* Ensure alignment. */	bp = (char *)(((u_long)bp + (sizeof(align) - 1)) &		      ~(sizeof(align) - 1));	/* Avoid overflows. */	if (bp + addrlen >= &pvt->hostbuf[sizeof pvt->hostbuf])		return(-1);	if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1])		return(0); /* fail, but not treat it as an error. */	/* Suppress duplicates. */	for (tap = (const char **)pvt->h_addr_ptrs;	     *tap != NULL;	     tap++)		if (memcmp(*tap, addrp, addrlen) == 0)			break;	if (*tap != NULL)		return (0);	memcpy(*hap = bp, addrp, addrlen);	return((bp + addrlen) - obp);}static voidmap_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {	char **ap;	if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)		return;	hp->h_addrtype = AF_INET6;	hp->h_length = IN6ADDRSZ;	for (ap = hp->h_addr_list; *ap; ap++) {		int i = (u_long)*bpp % sizeof(align);		if (i != 0)			i = sizeof(align) - i;		if ((ep - *bpp) < (i + IN6ADDRSZ)) {			/* Out of memory.  Truncate address list here. */			*ap = NULL;			return;		}		*bpp += i;		map_v4v6_address(*ap, *bpp);		*ap = *bpp;		*bpp += IN6ADDRSZ;	}}static voidaddrsort(res_state statp, char **ap, int num) {	int i, j, needsort = 0, aval[MAXADDRS];	char **p;	p = ap;	for (i = 0; i < num; i++, p++) {		for (j = 0 ; (unsigned)j < statp->nsort; j++)			if (statp->sort_list[j].addr.s_addr == 			    (((struct in_addr *)(*p))->s_addr &			     statp->sort_list[j].mask))				break;		aval[i] = j;		if (needsort == 0 && i > 0 && j < aval[i-1])			needsort = i;	}	if (!needsort)		return;	while (needsort < num) {		for (j = needsort - 1; j >= 0; j--) {			if (aval[j] > aval[j+1]) {				char *hp;				i = aval[j];				aval[j] = aval[j+1];				aval[j+1] = i;				hp = ap[j];				ap[j] = ap[j+1];				ap[j+1] = hp;			} else				break;		}		needsort++;	}}static intinit(struct irs_ho *this) {	struct pvt *pvt = (struct pvt *)this->private;		if (!pvt->res && !ho_res_get(this))		return (-1);	if (((pvt->res->options & RES_INIT) == 0U) &&	    res_ninit(pvt->res) == -1)		return (-1);	return (0);}

⌨️ 快捷键说明

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