ns_resp.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,318 行 · 第 1/4 页

C
2,318
字号
		} while (--c > 0);		tp = cp;        }#endif AUTHEN#ifdef AUTHEN	if (authen_count) {		if(ans_authentype == qp->q_authentype_out &&				ans_authentype == AUTH_KRB &&				ans_authenver == qp->q_authenver_out &&				ans_authenver == ONE) {		        krbnameptr = res_dotname_head(Q_NEXTNAME(qp,				qp->q_curaddr));			dnameptr = dname_authenrr;			if(type_authenrr != T_SOA && type_authenrr != T_AXFR)				res_dotname_rmhead(&dnameptr);			if(res_rds_krbcred(ONE, "named", krbnameptr,					Q_NEXTCRED(qp, qp->q_curaddr),					msg, authen_rr,					authen_rrlen, dnameptr,					type_authenrr, class_authenrr)			   < RET_OK)				authen = 0;			else {				read_cred = 1;				authen = 1;			}			free(krbnameptr);		}	}#endif AUTHEN				/*	 * Add the info received in the response to the Data Base	 */	c = ancount + aucount + arcount;#ifdef notdef	/*	 * If the request was for a CNAME that doesn't exist,	 * but the name is valid, fetch any other data for the name.	 * DON'T do this now, as it will requery if data are already	 * in the cache (maybe later with negative caching).	 */#ifdef AUTHEN	if (hp->qdcount && type == T_CNAME &&		((c == 1 && authen_count) !! (c == 0 && !authen_count)) &&		&& hp->rcode == NOERROR && !qp->q_system && authen) {#else AUTHEN	if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR &&	   !qp->q_system) {#endif AUTHEN#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"resp: leaving, no CNAME\n");#endif		/* Cause us to put it in the cache later */		prime(class, T_ANY, qp);		/* Nothing to store, just give user the answer */		goto return_msg;	}#endif /* notdef */	nspp = nsp;	if (qp->q_system)		dbflags = DB_NOTAUTH | DB_NODATA;	else		dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;	for (i = 0;#ifdef AUTHEN	     i < c && authen; i++) {#else AUTHEN	     i < c; i++) {#endif AUTHEN		struct databuf *ns3;#ifdef AUTHEN		if(arcount && authen_count && c == i+1)			break;#endif AUTHEN		if (cp >= msg + msglen)			goto formerr;		ns3 = 0;#ifdef AUTHEN		if ((n = doupdate(msg, msglen, cp, 0, &ns3, ans_authentype,				  ans_authenver, dbflags)) < 0) {#else AUTHEN		if ((n = doupdate(msg, msglen, cp, 0, &ns3, dbflags)) < 0) {#endif AUTHEN#ifdef DEBUG			if (debug)			    fprintf(ddt,"resp: leaving, doupdate failed\n");#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;		cp += n;	}#ifdef AUTHEN	if (qp->q_system && ancount) {#else AUTHEN	if (qp->q_system) {#endif AUTHEN		if (qp->q_system == PRIMING_CACHE)			check_root();#ifdef DEBUG		if (debug > 2)			fprintf(ddt,"resp: leaving, SYSQUERY ancount %d\n", ancount);#endif		qremove(qp);		return;	}	if (cp > msg + msglen)		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#ifdef AUTHEN	    && authen) {#else AUTHEN		)#endif AUTHEN		sort_response(tp, ancount, lp, msg + msglen);#ifdef AUTHEN		dname_authenrr = ans_name;		n = dn_expand(msg, msg + msglen, tp, dname_authenrr, MAXDNAME);		if (n < 0)			goto servfail;	}#endif AUTHEN	/*	 * An answer to a C_ANY query or a successful answer to a	 * regular query with no indirection, then just return answer.	 */#ifdef AUTHEN	if (authen && ((type == C_ANY && ancount) ||		       (!cname && !qp->q_cmsglen && ancount))) {#else AUTHEN	if((type == C_ANY && ancount) ||		    (!cname && !qp->q_cmsglen && ancount)) {#endif AUTHEN#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"resp: got as much answer as there is\n");#endif		goto return_msg;	}	/*	 * Eventually we will want to cache this negative answer.	 */#ifdef AUTHEN	if (authen && ancount == 0 && (hp->aa || qp->q_fwd) && nscount == 0) {#else AUTHEN	if (ancount == 0 && (hp->aa || qp->q_fwd) && nscount == 0) {#endif AUTHEN		/* We have an authoritative NO */#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"resp: leaving auth NO\n");#endif		if (qp->q_cmsglen) {			msg = (u_char *)qp->q_cmsg;			msglen = qp->q_cmsglen;			hp = (HEADER *)msg;		}		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) {#ifdef DEBUG		if (debug)			fprintf(ddt,"Cname second pass\n");#endif		newmsglen = qp->q_cmsglen;		bcopy(qp->q_cmsg, newmsg, newmsglen);#ifdef AUTHEN		type_authenrr = qp->q_type;		class_authenrr = qp->q_class;		dname_authenrr = qp->q_dname;#endif AUTHEN	} else {		newmsglen = msglen;		bcopy(msg, newmsg, newmsglen);#ifdef AUTHEN		type_authenrr = type;		class_authenrr = class;		dname_authenrr= resp_name;#endif AUTHEN	}	hp = (HEADER *) newmsg;	hp->ancount = 0;	hp->nscount = 0;	hp->arcount = 0;	dnptrs[0] = newmsg;	dnptrs[1] = NULL;	cp = newmsg + sizeof(HEADER);	if (cname)#ifdef AUTHEN		cp += dn_skipname(cp, newmsg + newmsglen) + (hp->opcode == AQUERY ? AQFIXEDSZ : QFIXEDSZ);#else AUTHEN		cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ;#endif AUTHEN	if ((n = dn_expand(newmsg, newmsg + newmsglen,		cp, dname, sizeof(name))) < 0) {#ifdef DEBUG		if (debug)			fprintf(ddt,"dn_expand failed\n" );#endif		goto servfail;	}#ifdef AUTHEN	cp = newmsg + sizeof(HEADER) + 		(cname ? dn_skipname(cp, newmsg + newmsglen) : n) + 		(hp->opcode == AQUERY ? AQFIXEDSZ : QFIXEDSZ);#else AUTHEN	cp = newmsg + sizeof(HEADER) +	    (cname ? dn_skipname(cp, newmsg + newmsglen) : n) + QFIXEDSZ;#endif AUTHEN	buflen = sizeof(newmsg) - (cp - newmsg);try_again:#ifdef DEBUG	if (debug)		fprintf(ddt,"resp: nlookup(%s) type=%d\n",dname, type);#endif	fname = "";	htp = hashtab;		/* lookup relative to root */	np = nlookup(dname, &htp, &fname, 0);#ifdef DEBUG	if (debug)		fprintf(ddt,"resp: %s '%s' as '%s' (cname=%d)\n",			np == NULL ? "missed" : "found", dname, fname, cname);#endif	if (np == NULL || fname != dname)		goto fetch_ns;	foundname++;	count = cp - newmsg;#ifdef AUTHEN	if (cname) {		n = finddata(np, class, type, hp, &dname, &buflen, &count,		     qp->q_authentype_out, qp->q_authenver_out,		     &junk, &junk);	}else {		dname_authenrr = ans_name;		strcpy(dname_authenrr, dname);		n = finddata(np, class, type, hp, &dname_authenrr,		     &buflen, &count,		     qp->q_authentype_out, qp->q_authenver_out,		     &type_authenrr, &class_authenrr);		dname = dname_authenrr;	}#else AUTHEN	n = finddata(np, class, type, hp, &dname, &buflen, &count);#endif AUTHEN	if (n == 0)		goto fetch_ns;		/* NO data available */	cp += n;	buflen -= n;	hp->ancount += count;	if (strcmp(fname, dname) && type != T_CNAME && type != T_ANY) {		cname++;		goto try_again;	}	founddata = 1;#ifdef DEBUG	if (debug >= 3) {	    fprintf(ddt,"resp: foundname = %d count = %d ", foundname, count);	    fprintf(ddt,"founddata = %d cname = %d\n", founddata, cname);	}#endiffetch_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). 	 */	switch (findns(&np, class, nsp, &count)) {	case NXDOMAIN:		/* shouldn't happen */#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"req: leaving (%s, rcode %d)\n",				dname, hp->rcode);#endif		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_short)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) {#ifdef DEBUG		if (debug)		    fprintf(ddt,"resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",			dname, class, type);#endif		syslog(LOG_NOTICE,		    	    "MAXQUERIES exceeded, possible data loop in resolving (%s)",			    dname);		goto servfail;	}	/* Reset the query control structure */	qp->q_naddr = 0;	qp->q_curaddr = 0;#ifdef ULTRIXFUNC	qp->q_fwd = qp->q_fwdorig;#else ULTRIXFUNC	qp->q_fwd = fwdtab;#endif ULTRIXFUNC	qp->q_addr[0].stime = tt;	if (nslookup(nsp, qp) == 0) {#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"resp: no addrs found for NS's\n");#endif		goto servfail;	}	if (cname) {	 	if (qp->q_cname++ == MAXCNAMES) {#ifdef DEBUG			if (debug >= 3)				fprintf(ddt,"resp: leaving, MAXCNAMES exceeded\n");#endif			goto servfail;	 	}#ifdef DEBUG	 	if (debug)	 		fprintf(ddt,"q_cname = %d\n",qp->q_cname);		if (debug >= 3)		       fprintf(ddt,"resp: building recursive query; nslookup\n");#endif		if (qp->q_msg)			(void) free(qp->q_msg);		if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {#ifdef DEBUG			if (debug)				fprintf(ddt,"resp: malloc error\n");#endif			goto servfail;		}#ifdef AUTHEN		qp->q_msglen = res_mkquery(qp->q_type_out, dname, class,		    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);		dname_authenrr = dname;		type_authenrr = type;		class_authenrr = class;		strcpy(qp->q_dname_curr, dname);		qp->q_type_curr = type;		qp->q_class_curr = class;#else AUTHEN		qp->q_msglen = res_mkquery(QUERY, dname, class,		    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);#endif AUTHEN#ifndef AUTHEN		hp = (HEADER *) qp->q_msg;#endif AUTHEN	    	hp->rd = 0;	}#ifndef AUTHEN	else		hp = (HEADER *) qp->q_msg;#endif AUTHEN#ifdef AUTHEN	hp = (HEADER *) msgbuf;	bcopy(qp->q_msg, msgbuf, qp->q_msglen);	msgbuflen = qp->q_msglen;	hp->id = qp->q_nsid = htons((u_short)++nsid);	if(qp->q_type_out == AQUERY && qp->q_authentype_out == AUTH_KRB &&	   qp->q_authenver_out == ONE) {		krbnameptr = res_dotname_head(Q_NEXTNAME(qp,0));		dnameptr = dname_authenrr;		if(type_authenrr != T_SOA && type_authenrr != T_AXFR)			res_dotname_rmhead(&dnameptr);		if(res_mkl_krbcred(ONE, "named", dnameptr, Q_NEXTCRED(qp, 0),				   msgbuf, msgbuf + msgbuflen,				   sizeof(msgbuf) - msgbuflen,				   dnameptr, type_authenrr,				   class_authenrr) < RET_OK)			goto servfail;		hp->arcount = 1;	} else if( qp->q_type_in == AQUERY)		goto servfail;#else AUTHEN			hp->id = qp->q_nsid = htons((u_short)++nsid);#endif AUTHEN					unsched(qp);#ifdef ULTRIXFUNC	schedretry(qp, qp->q_fwd ? (2*RETRYBASE): retrytime(qp) );#else ULTRIXFUNC	schedretry(qp, retrytime(qp));#endif ULTRIXFUNC#ifdef DEBUG	if (debug)		fprintf(ddt,"resp: forw -> %s %d (%d) nsid=%d id=%d %dms\n",			inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),			ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),			ntohs(qp->q_nsid), ntohs(qp->q_id),			qp->q_addr[0].nsdata->d_nstime);	if ( debug >= 10)		fp_query(msg, ddt);#endif#ifdef AUTHEN	if (sendto(ds, msgbuf, msgbuflen, 0,		(struct sockaddr *)Q_NEXTADDR(qp,0),		sizeof(struct sockaddr_in)) < 0)#else AUTHEN			if (sendto(ds, qp->q_msg, qp->q_msglen, 0,		(struct sockaddr *)Q_NEXTADDR(qp,0),		sizeof(struct sockaddr_in)) < 0)#endif AUTHEN				{#ifdef DEBUG		if (debug >= 5)			fprintf(ddt, "sendto error = %d\n", errno);#endif	}#ifdef STATS	stats[S_OUTPKTS].cnt++;#endif#ifdef DEBUG	if (debug >= 3)		fprintf(ddt,"resp: Query sent.\n");#endif	return;formerr:#ifdef DEBUG	if (debug)	    fprintf(ddt,"FORMERR resp() from %s size err %d, msglen %d\n",		inet_ntoa(from_addr.sin_addr),		cp-msg, msglen);#endif	syslog(LOG_INFO, "Malformed response from %s\n",		inet_ntoa(from_addr.sin_addr));#ifdef STATS	stats[S_RESPFORMERR].cnt++;#endif	return;#ifdef AUTHENservfail:#ifdef STATS	stats[S_RESPFAIL].cnt++;#endif	hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);	hp->rcode = SERVFAIL;	hp->id = qp->q_id;	tmplen = (cname ? qp->q_cmsglen : qp->q_msglen);	tmpmsg = (u_char *)(cname ? qp->q_cmsg : qp->q_msg);	dname_authenrr = qp->q_dname;	type_authenrr = qp->q_type;	class_authenrr = qp->q_class;	new = 1;	goto return_msg;return_newmsg:	if (addcount) {		n = doaddinfo(hp, cp, buflen);		cp += n;		buflen -= n;	}	tmplen = cp - newmsg;	tmpmsg = newmsg;#ifdef STATS	stats[S_RESPOK].cnt++;#endif	new = 1;return_msg:	if (!new) {		tmpmsg = msg;		tmplen = msglen;#ifdef STATS		stats[S_RESPOK].cnt++;#endif	}	hp->id = qp->q_id;	hp->rd = 1;	hp->ra = 1;	hp->qr = 1;	if(qp->q_type_in == QUERY &&			qp->q_type_out == AQUERY) {		cp = tmpmsg;		cp += sizeof(HEADER);			n = dn_skipname(cp, tmpmsg + tmplen);		cp += n + 4 * sizeof(u_short);		if (fixup_rrs(cp, tmplen - (cp - tmpmsg), cp - (u_char *)hp,			      -(2 * sizeof(u_short))) < 0)		  return(-1);		bcopy(cp, cp - (2 * sizeof(u_short)), tmplen - 			(cp - tmpmsg));		tmplen -= authen_rrlen + (2 * sizeof(u_short));		hp->arcount = 0;		hp->opcode = QUERY;	}	if(qp->q_type_in == AQUERY && qp->q_authentype_in == AUTH_KRB &&	   qp->q_authenver_in == ONE && read_cred) {		dnameptr = dname_authenrr;		if (type_authenrr != T_SOA && type_authenrr != T_AXFR)			res_dotname_rmhead(&dnameptr);

⌨️ 快捷键说明

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