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

📄 ns_resp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			goto formerr;		}		if ((n = dovalidate((caddr_t)msg, msglen, tempcp, 0,				    dbflags, server, &VCode)) < 0) {			dprintf(1, (ddt,				    "resp: leaving, dovalidate failed\n"));			/* return code filled in by dovalidate */			goto return_msg;		}		validatelist[i] = VCode;		if (VCode == INVALID) lesscount++;		tempcp += n;	}	/* need to delete INVALID records from the message	 * and change fields appropriately	 */	n = update_msg(msg, &msglen, validatelist, count);	free((char *)validatelist);	if (n < 0)		goto formerr;	count -= lesscount;	if (old_ancount && !hp->ancount) {		/* We lost all the answers */		dprintf(1, (ddt, "validate count -> 0"));		return;	}	ancount <- ntohs(hp->ancount);#endif	for (i = 0;  i < count;  i++) {		struct databuf *ns3;#ifdef CRED		u_char cred;#endif		if (cp >= msg + msglen) {			formerrmsg = outofDataFinal;			goto formerr;		}#ifdef CRED		if (i < ancount) {			cred = hp->aa ?DB_C_AUTH :DB_C_ANSWER;		} else {			cred = DB_C_ADDITIONAL;		}#endif		ns3 = 0;		if ((n = doupdate((caddr_t)msg, msglen, cp, 0, &ns3, dbflags#ifdef CRED			      , cred#endif			      )) < 0) {			dprintf(1, (ddt, "resp: leaving, doupdate failed\n"));#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			/* return code filled in by doupdate */			goto return_msg;		}		/*		 * Remember nameservers from the authority section		 * for referrals.		 * (This is usually overwritten by findns below(?). XXX		 */		if (ns3 && i >= ancount && i < ancount + aucount &&		    nspp < &nsp[NSMAX-1]) {			*nspp++ = ns3;#ifdef DATUMREFCNT			ns3->d_rcnt++;			*nspp = NULL;#endif		}		cp += n;	}	if ((qp->q_flags & Q_SYSTEM) && ancount) {		if (qp->q_flags & Q_PRIMING)			check_root();		dprintf(3, (ddt, "resp: leaving, SYSQUERY ancount %d\n",			    ancount));		qremove(qp);#ifdef	DATUMREFCNT		free_nsp(nsp);#endif		return;	}	if (cp > msg + msglen) {		formerrmsg = outofDataAFinal;		goto formerr;	}	/*	 *  If there are addresses and this is a local query,	 *  sort them appropriately for the local context.	 */	if (ancount > 1 && (lp = local(&qp->q_from)) != NULL) 		sort_response((caddr_t)tp, ancount, lp, msg + msglen);	/*	 * An answer to a T_ANY query or a successful answer to a	 * regular query with no indirection, then just return answer.	 */	if ((hp->qdcount && type == T_ANY && ancount) ||	    (!cname && !qp->q_cmsglen && ancount)) {		dprintf(3, (ddt, "resp: got as much answer as there is\n"));		goto return_msg;	}	/*	 * Eventually we will want to cache this negative answer.	 */	if (ancount == 0 && nscount == 0 &&	    (hp->aa || fwd || class == C_ANY)) {		/* We have an authoritative NO */		dprintf(3, (ddt, "resp: leaving auth NO\n"));		if (qp->q_cmsglen) {			msg = (u_char *)qp->q_cmsg;			msglen = qp->q_cmsglen;			hp = (HEADER *)msg;		}#ifdef NCACHE	/*answer was an authoritative NO,*/	if ((ancount == 0) && (hp->aa) &&	   ((hp->rcode == NXDOMAIN) || (hp->rcode == NOERROR))) {		cache_n_resp(msg, msglen);	}#endif /*NCACHE*/		goto return_msg;	}	/*	 * All messages in here need further processing.  i.e. they	 * are either CNAMEs or we got referred again.	 */	count = 0;	founddata = 0;	foundname = 0;	dname = name;	if (!cname && qp->q_cmsglen && ancount) {		dprintf(1, (ddt, "Cname second pass\n"));		newmsglen = qp->q_cmsglen;		bcopy(qp->q_cmsg, newmsg, newmsglen);	} else {		newmsglen = msglen;		bcopy(msg, newmsg, newmsglen);	}	hp = (HEADER *) newmsg;	hp->ancount = 0;	hp->nscount = 0;	hp->arcount = 0;	dnptrs[0] = newmsg;	dnptrs[1] = NULL;	cp = newmsg + sizeof(HEADER);	if (cname)		cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ;	if ((n = dn_expand(newmsg, newmsg + newmsglen,		cp, (u_char *)dname, sizeof(name))) < 0) {		dprintf(1, (ddt, "dn_expand failed\n"));		goto servfail;	}	if (!cname)		cp += n + QFIXEDSZ;	buflen = sizeof(newmsg) - (cp - newmsg);try_again:	dprintf(1, (ddt, "resp: nlookup(%s) type=%d\n", dname, type));	fname = "";	htp = hashtab;		/* lookup relative to root */	np = nlookup(dname, &htp, &fname, 0);	dprintf(1, (ddt, "resp: %s '%s' as '%s' (cname=%d)\n",		    np == NULL ? "missed" : "found", dname, fname, cname));	if (np == NULL || fname != dname)		goto fetch_ns;	foundname++;	count = cp - newmsg;	n = finddata(np, class, type, hp, &dname, &buflen, &count);	if (n == 0)		goto fetch_ns;		/* NO data available */	cp += n;	buflen -= n;	hp->ancount += count;	if (fname != dname && type != T_CNAME && type != T_ANY) {		cname++;		goto try_again;	}	founddata = 1;	dprintf(3, (ddt,		    "resp: foundname=%d, count=%d, founddata=%d, cname=%d\n",		    foundname, count, founddata, cname));fetch_ns:	hp->ancount = htons(hp->ancount);	/* 	 * Look for name servers to refer to and fill in the authority 	 * section or record the address for forwarding the query 	 * (recursion desired). 	 */#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	switch (findns(&np, class, nsp, &count, 0)) {	case NXDOMAIN:		/* shouldn't happen */		dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",			    dname, hp->rcode));		if (!foundname)			hp->rcode = NXDOMAIN;		if (class != C_ANY) {			hp->aa = 1;			/*			 * should return SOA if founddata == 0,			 * but old named's are confused by an SOA			 * in the auth. section if there's no error.			 */			if (foundname == 0 && np) {			    n = doaddauth(hp, cp, buflen, np, nsp[0]);			    cp += n;			    buflen -= n;			}		}		goto return_newmsg;	case SERVFAIL:		goto servfail;	}	if (founddata) {		hp = (HEADER *)newmsg;		n = add_data(np, nsp, cp, buflen);		if (n < 0) {			hp->tc = 1;			n = (-n);		}		cp += n;		buflen -= n;		hp->nscount = htons((u_int16_t)count);		goto return_newmsg;	}	/*	 *  If we get here, we don't have the answer yet and are about	 *  to iterate to try and get it.  First, infinite loop avoidance.	 */	if (qp->q_nqueries++ > MAXQUERIES) {		dprintf(1,			(ddt,			 "resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",			 dname, class, type			 )			);		syslog(LOG_NOTICE,		    	    "MAXQUERIES exceeded, possible data loop in resolving (%s)",			    dname);		goto servfail;	}	/* Reset the query control structure */#ifdef	DATUMREFCNT	for (i = 0 ; i < qp->q_naddr ; i++) {		if ((--(qp->q_addr[i].ns->d_rcnt))) {			dprintf(1 ,(ddt, "ns_resp: ns %s rcnt %d\n",					qp->q_addr[i].ns->d_data,					qp->q_addr[i].ns->d_rcnt));		} else {			dprintf(1 ,(ddt, "ns_resp: ns %s rcnt %d delayed\n",					qp->q_addr[i].ns->d_data,					qp->q_addr[i].ns->d_rcnt));			free((char*)qp->q_addr[i].ns);		}		if ((--(qp->q_addr[i].nsdata->d_rcnt))) {			dprintf(1 ,(ddt, "ns_resp: nsdata %08.8X rcnt %d\n",					*(int32_t *)(qp->q_addr[i].nsdata->d_data),					qp->q_addr[i].nsdata->d_rcnt));		} else {			dprintf(1 ,(ddt, "ns_resp: nsdata %08.8X rcnt %d delayed\n",					*(int32_t *)(qp->q_addr[i].nsdata->d_data),					qp->q_addr[i].nsdata->d_rcnt));			free((char*)qp->q_addr[i].nsdata);		}	}#endif	qp->q_naddr = 0;	qp->q_curaddr = 0;	qp->q_fwd = fwdtab;	if ((n = nslookup(nsp, qp, dname, "ns_resp")) <= 0) {		if (n < 0) {			dprintf(3, (ddt, "resp: nslookup reports danger\n"));		} else {			dprintf(3, (ddt, "resp: no addrs found for NS's\n"));		}		if (cname)	/* a remote CNAME that does not have data */			goto return_newmsg;		goto servfail;	}	for (n = 0; n < qp->q_naddr; n++)		qp->q_addr[n].stime.tv_sec = 0;	if (!qp->q_fwd)		qp->q_addr[0].stime = tt;	if (cname) {	 	if (qp->q_cname++ == MAXCNAMES) {			dprintf(3, (ddt,				    "resp: leaving, MAXCNAMES exceeded\n"));			goto servfail;	 	}		dprintf(1, (ddt, "q_cname = %d\n",qp->q_cname));		dprintf(3, (ddt,			    "resp: building recursive query; nslookup\n"));		if (qp->q_msg)			(void) free(qp->q_msg);		if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {			dprintf(1, (ddt, "resp: malloc error\n"));			goto servfail;		}		qp->q_msglen = res_mkquery(QUERY, dname, class,		    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);		hp = (HEADER *) qp->q_msg;	    	hp->rd = 0;	} else		hp = (HEADER *)qp->q_msg;	hp->id = qp->q_nsid = htons((u_int16_t)++nsid);	if (qp->q_fwd)		hp->rd = 1;	unsched(qp);	schedretry(qp, retrytime(qp));	dprintf(1, (ddt, "resp: forw -> [%s].%d ds=%d nsid=%d id=%d %dms\n",		    inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),		    ntohs(Q_NEXTADDR(qp,0)->sin_port), ds,		    ntohs(qp->q_nsid), ntohs(qp->q_id),		    (qp->q_addr[0].nsdata != NULL)			? qp->q_addr[0].nsdata->d_nstime			: (-1)));#ifdef DEBUG	if (debug >= 10)		fp_query((char *)msg, ddt);#endif	if (sendto(ds, qp->q_msg, qp->q_msglen, 0,		(struct sockaddr *)Q_NEXTADDR(qp,0),		sizeof(struct sockaddr_in)) < 0) {		dprintf(5, (ddt, "sendto error = %d\n", errno));	}	hp->rd = 0;	/* leave set to 0 for dup detection */	stats[S_OUTPKTS].cnt++;	dprintf(3, (ddt, "resp: Query sent.\n"));#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return;formerr:	dprintf(3, (ddt,		    "FORMERR resp() from [%s].%d size err %d, msglen %d\n",		    inet_ntoa(from_addr.sin_addr),		    ntohs(from_addr.sin_port),		    cp-msg, msglen));	if (!haveComplained((char*)from_addr.sin_addr.s_addr,			    (char*)dhash((u_char *)formerrmsg,					 strlen(formerrmsg)					 )			    )	    ) {		syslog(LOG_INFO, "Malformed response from [%s].%d (%s)\n",		       inet_ntoa(from_addr.sin_addr),		       ntohs(from_addr.sin_port),		       formerrmsg);	}	stats[S_RESPFORMERR].cnt++;#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return;return_msg:	stats[S_RESPOK].cnt++;	/* The "standard" return code */	hp->qr = 1;	hp->id = qp->q_id;	hp->rd = 1;	hp->ra = 1;	(void) send_msg((caddr_t)msg, msglen, qp);	qremove(qp);#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return;return_newmsg:	stats[S_RESPOK].cnt++;	if (addcount) {		n = doaddinfo(hp, cp, buflen);		cp += n;		buflen -= n;	}	hp->id = qp->q_id;	hp->rd = 1;	hp->ra = 1;	hp->qr = 1;	(void) send_msg((caddr_t)newmsg, cp - newmsg, qp);	qremove(qp);#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return;servfail:	stats[S_RESPFAIL].cnt++;	hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);	hp->rcode = SERVFAIL;	hp->id = qp->q_id;	hp->rd = 1;	hp->ra = 1;	hp->qr = 1;	(void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp);	qremove(qp);#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return;}/* * Decode the resource record 'rrp' and update the database. * If savens is non-nil, record pointer for forwarding queries a second time. */intdoupdate(msg, msglen, rrp, zone, savens, flags#ifdef CRED	 , cred#endif	 )	char *msg;	u_char *rrp;	struct databuf **savens;	int  msglen, zone, flags;#ifdef CRED	u_int cred;#endif{	register u_char *cp;	register int n;	int class, type, dlen, n1;	u_int32_t ttl;	struct databuf *dp;	char dname[MAXDNAME];	u_char *cp1;	u_char data[BUFSIZ];	register HEADER *hp = (HEADER *) msg;#ifdef ALLOW_UPDATES	int zonenum;#endif	dprintf(3, (ddt, "doupdate(zone %d, savens %x, flags %x)\n",		    zone, savens, flags));	cp = rrp;	if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp,	    (u_char *)dname, sizeof(dname))) < 0) {		hp->rcode = FORMERR;		return (-1);	}	cp += n;	GETSHORT(type, cp);	GETSHORT(class, cp);	GETLONG(ttl, cp);	GETSHORT(dlen, cp);	dprintf(3, (ddt, "doupdate: dname %s type %d class %d ttl %d\n",		    dname, type, class, ttl));	/*	 * Convert the resource record data into the internal	 * database format.	 */	switch (type) {	case T_A:	case T_WKS:	case T_HINFO:	case T_UINFO:	case T_UID:	case T_GID:	case T_TXT:#ifdef ALLOW_T_UNSPEC	case T_UNSPEC:#endif		cp1 = cp;		n = dlen;		cp += n;		break;	case T_CNAME:	case T_MB:	case T_MG:	case T_MR:	case T_NS:	case T_PTR:		if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,		    cp, data, sizeof(data))) < 0) {			hp->rcode = FORMERR;			return (-1);		}		cp += n;		cp1 = data;		n = strlen((char *)data) + 1;		break;	case T_MINFO:	case T_SOA:	case T_RP:		if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,		    cp, data, sizeof(data))) < 0) {			hp->rcode = FORMERR;

⌨️ 快捷键说明

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