ns_resp.c

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

C
2,318
字号
		return(0);	}#ifdef AUTHEN	qp->q_msglen = res_mkquery(qp->q_type_out, dname, class,	    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);#else AUTHEN	qp->q_msglen = res_mkquery(QUERY, dname, class,	    type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);#endif AUTHEN	hp = (HEADER *) qp->q_msg;	hp->id = qp->q_nsid = htons((u_short)++nsid);	hp->rd = (qp->q_fwd ? 1 : 0);	/* First check for an already pending query for this data */	for (oqp = qhead; oqp!=QINFO_NULL; oqp = oqp->q_link) {		if (oqp != qp && oqp->q_msglen == qp->q_msglen &&	     bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0) {#ifdef DEBUG			if (debug >= 3)				fprintf(ddt, "sysquery: duplicate\n");#endif			qfree(qp);			return(0);		}	}	if (nslookup(nsp, qp) == 0) {#ifdef DEBUG		if (debug)			fprintf(ddt,"resp: no addrs found for NS's\n");#endif		qfree(qp);		return(0);	}#ifdef ULTRIXFUNC	schedretry(qp, qp->q_fwd ? (2*RETRYBASE): retrytime(qp) );#else ULTRIXFUNC	schedretry(qp, retrytime(qp));#endif ULTRIXFUNC	if (qp->q_fwd == 0)		qp->q_addr[0].stime = tt;#ifdef AUTHEN	if(netsafe && class == C_HS) {		krbnameptr = res_dotname_head(Q_NEXTNAME(qp,0));		dnameptr = dname;		if(type != T_SOA && type != T_AXFR)			res_dotname_rmhead(&dnameptr);		if((authenlen = res_mkl_krbcred(ONE, "named", krbnameptr,						Q_NEXTCRED(qp,0),						qp->q_msg,						qp->q_msg + qp->q_msglen,						BUFSIZ - qp->q_msglen,						dnameptr, type, class))		   < RET_OK)			return(0);		msglen = qp->q_msglen + authenlen;	      }#endif AUTHEN#ifdef DEBUG	if (debug)	    fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %dms\n",		inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),		qp->q_dfd, 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(qp->q_msg, ddt);#endif#ifdef AUTHEN	if (sendto(qp->q_dfd, qp->q_msg, msglen, 0,	    (struct sockaddr *)Q_NEXTADDR(qp,0),	    sizeof(struct sockaddr_in)) < 0){#else AUTHEN	if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,	    (struct sockaddr *)Q_NEXTADDR(qp,0),	    sizeof(struct sockaddr_in)) < 0){#endif AUTHEN#ifdef DEBUG	    if (debug)		fprintf(ddt, "sendto error errno= %d\n",errno);#endif	}#ifdef STATS	stats[S_OUTPKTS].cnt++;#endif	return(qp);}/* * Check the list of root servers after receiving a response * to a query for the root servers. */check_root(){	register struct databuf *dp, *pdp;	register struct namebuf *np;	int count = 0;	priming = 0;	for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)		if (np->n_dname[0] == '\0')			break;	if (np == NULL) {		syslog(LOG_ERR, "check_root: Can't find root!\n");		return;	}	for (dp = np->n_data; dp != NULL; dp = dp->d_next)		if (dp->d_type == T_NS)			count++;#ifdef DEBUG	if (debug)	    fprintf(ddt,"%d root servers\n", count);#endif	if (count < MINROOTS) {		syslog(LOG_WARNING,		"check_root: %d root servers after query to root server < min",		    count);		return;	}	pdp = NULL;	dp = np->n_data;	while (dp != NULL) {		if (dp->d_type == T_NS && dp->d_zone == 0 &&		    dp->d_ttl < tt.tv_sec) {#ifdef DEBUG			if (debug)			    fprintf(ddt,"deleting old root server '%s'\n",				dp->d_data);#endif#ifdef ULTRIXFUNC			dp = rm_datum(0, dp, np, pdp);#endif ULTRIXFUNC			/* SHOULD DELETE FROM HINTS ALSO */			continue;		}		pdp = dp;		dp = dp->d_next;	}	check_ns();}/*  * Check the root to make sure that for each NS record we have a A RR */check_ns(){	register struct databuf *dp, *tdp;	register struct namebuf *np, *tnp;	struct hashbuf *htp;	char *dname;	int found_arr;	char *fname;	time_t curtime;#ifdef DEBUG	if (debug >= 2)	       fprintf(ddt,"check_ns()\n");#endif#ifdef STATS	stats[S_CHECKNS].cnt++;#endif	curtime = (u_long) tt.tv_sec;	for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {		if (np->n_dname[0] != 0)			continue;	        for (dp = np->n_data; dp != NULL; dp = dp->d_next) {	        	if (dp->d_type != T_NS)	        	    continue;	        	/* look for A records */			dname = dp->d_data;			htp = hashtab;			tnp = nlookup(dname, &htp, &fname, 0);			if (tnp == NULL || fname != dname) {#ifdef DEBUG			    if (debug >= 3)			        fprintf(ddt,"check_ns: %s: not found %s %x\n",					dname, fname, tnp);#endif			    (void) sysquery(dname, dp->d_class, T_A);			    continue;			}			/* look for name server addresses */			found_arr = 0;			for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) {			    if (tdp->d_type != T_A ||			       tdp->d_class != dp->d_class)				continue;			    if ((tdp->d_zone == 0) &&				(tdp->d_ttl < curtime)) {#ifdef DEBUG			        if (debug >= 3)			            fprintf(ddt,"check_ns: stale entry '%s'\n",			                tnp->n_dname);#endif				/* Cache invalidate the address RR's */				delete_all(tnp, dp->d_class, T_A);				found_arr = 0;			        break;			    }			    found_arr++;			}			if (!found_arr)			    (void) sysquery(dname, dp->d_class, T_A);	        }	}}#define	MAXCLASS 255		/* belongs elsewhere */int	norootlogged[MAXCLASS];/* *  Find NS's or an SOA for the given dname (np) and fill in the *  nsp array.  Returns OK on success, and SERVFAIL on error. *  We return NXDOMAIN to indicate we are authoritative. */findns(npp, class, nsp, countp)	register struct namebuf **npp;	struct databuf **nsp;	int *countp;{	register struct namebuf *np = *npp;	register struct databuf *dp;	register struct	databuf **nspp;	struct hashbuf *htp = hashtab;		if (priming && (np == NULL || np->n_dname[0] == '\0'))		htp = fcachetab;try_again:/*#ifdef AUTHEN	if (htp == fcachetab && !(forward_only && fwdtab))#else AUTHEN*/	if (htp == fcachetab)/*#endif AUTHEN*/		needs_prime_cache = 1;	while (np == NULL && htp != NULL) {#ifdef DEBUG		if (debug > 2)			fprintf(ddt, "findns: using %s\n", htp == hashtab ?				"cache" : "hints");#endif		for (np = htp->h_tab[0]; np != NULL; np = np->n_next)			if (np->n_dname[0] == '\0')				break;		htp = (htp == hashtab ? fcachetab : NULL);	/* Fallback */	}	while(np != NULL) {#ifdef DEBUG		if (debug >= 5)			fprintf(ddt, "findns: np 0x%x\n", np);#endif		/* Look first for SOA records. */		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {			if (dp->d_zone != 0 && match(dp, class, T_SOA)) {#ifdef DEBUG				if (debug >= 3)					fprintf(ddt,"findns: SOA found\n");#endif				if (zones[dp->d_zone].z_auth) {					*npp = np;					nsp[0] = dp;					return(NXDOMAIN);				} else					return (SERVFAIL);			}		}		/* If no SOA records, look for NS records. */		nspp = &nsp[0];		*nspp = NULL;		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {			if (dp->d_type != T_NS ||			    (dp->d_class != class && class != C_ANY))				continue;			/*			 * Don't use records that may become invalid to			 * reference later when we do the rtt computation.			 * Never delete our safety-belt information!			 */			if ((dp->d_zone == 0) &&			    (dp->d_ttl < (tt.tv_sec+900)) &&			    !(dp->d_flags & DB_F_HINT)) {#ifdef DEBUG				if (debug)					fprintf(ddt,"findns: stale entry '%s'\n",						    np->n_dname);#endif				/* Cache invalidate the NS RR's */				if (dp->d_ttl < tt.tv_sec)					delete_all(np, class, T_NS);				goto try_parent;			}			if (nspp < &nsp[NSMAX-1])				*nspp++ = dp;		}		*countp = nspp - nsp;		if (*countp > 0) {#ifdef DEBUG			if (debug >= 3)				fprintf(ddt,"findns: %d NS's added for '%s'\n",					*countp, np->n_dname);#endif			*nspp = NULL;			*npp = np;			return(OK);	/* Success, got some NS's */		}try_parent:		np = np->n_parent;	}	if (htp)		goto try_again;#ifdef DEBUG	if (debug)		fprintf(ddt, "findns: No root nameservers for class %d?\n",		    class);#endif	if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {		norootlogged[class] = 1;		syslog(LOG_ERR, "No root nameservers for class %d\n", class);	}	return(SERVFAIL);}/* *  Extract RR's from the given node that match class and type. *  Return number of bytes added to response. *  If no matching data is found, then 0 is returned. *  Authoritative answer bit is set in response if appropriate. */#ifdef AUTHENfinddata(np, class, type, hp, dnamep, lenp, countp,	 authtype, authver, ans_type, ans_class)	struct namebuf *np;	int class, type;	register HEADER *hp;	char **dnamep;	int *lenp, *countp;	int authtype, authver;	int *ans_type, *ans_class;{#else AUTHENfinddata(np, class, type, hp, dnamep, lenp, countp)	struct namebuf *np;	int class, type;	register HEADER *hp;	char **dnamep;	int *lenp, *countp;{#endif AUTHEN	register struct databuf *dp;	register char *cp;	int buflen, n, count = 0, foundstale = 0;#ifdef AUTHEN	int foundnotauth = 0;#endif AUTHEN	buflen = *lenp;	cp = ((char *)hp) + *countp;	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {		if (!wanted(dp, class, type)) {#ifdef notdef			if (type == T_CNAME && class == dp->d_class) {				/* any data means no CNAME exists */				*countp = 0;				return(0);			}#endif			continue;		}		if (stale(dp)) {			/*			 * Don't use stale data.			 * Would like to call delete_all here			 * and continue, but the data chain would get			 * munged; can't restart, as make_rr has side			 * effects (leaving pointers in dnptr).			 * Just skip this entry for now			 * and call delete_all at the end.			 */#ifdef DEBUG			if (debug >=3)			   fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname);#endif			if (dp->d_zone == 0)				foundstale++;			continue;		}#ifdef AUTHEN		if(not_authen(authtype, authver, dp)) {			foundnotauth = 1;			continue;		}#endif AUTHEN		if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) {			hp->tc = 1;			*countp = count;			return(*lenp - buflen);		}		cp += n;		buflen -= n;		count++;#ifdef AUTHEN		if(count == 1) {			*ans_type = dp->d_type;			*ans_class = dp->d_class;		}#endif AUTHEN#ifdef notdef		/* this isn't right for glue records, aa is set in ns_req */		if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY)			hp->aa = 1;			/* XXX */#endif		if (dp->d_type == T_CNAME) {			if (type != T_ANY) {	/* or T_NS? */				*dnamep = dp->d_data;				if (dp->d_zone && zones[dp->d_zone].z_auth &&				    class != C_ANY)		/* XXX */					hp->aa = 1;		/* XXX */			}			break;		}	}	/*	 * Cache invalidate the other RR's of same type	 * if some have timed out	 */#ifdef AUTHEN	if (foundstale || foundnotauth)#else AUTHEN	if (foundstale)#endif AUTHEN		delete_all(np, class, type);#ifdef DEBUG	if (debug >=3)		fprintf(ddt,"finddata: added %d class %d type %d RRs\n",			count, class, type);#endif	*countp = count;	return(*lenp - buflen);}/* * Do we want this data record based on the class and type? */wanted(dp, class, type)	struct databuf *dp;	int class, type;{#ifdef DEBUG	if (debug > 3)		fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type,			dp->d_class, dp->d_type);#endif	if (dp->d_class != class && class != C_ANY)		return (0);	if (type == dp->d_type)		return (1);	switch (dp->d_type) {	case T_ANY:	case T_CNAME:		return (1);	}	switch (type) {	case T_TXT:		return(dp->d_type == T_TXT);	case T_ANY:		return (1);	case T_MAILB:		switch (dp->d_type) {		case T_MR:		case T_MB:		case T_MG:		case T_MINFO:			return (1);		}		break;	case T_AXFR:		if (dp->d_type == T_SOA)			return (1);	}	return (0);}/* *  Add RR entries from dpp array to a query/response. *  Return the number of bytes added or negative the amount *  added if truncation was required.  Typically you are *  adding NS records to a response. */add_data(np, dpp, cp, buflen)	struct namebuf *np;	struct databuf **dpp;	register char *cp;	int buflen;{	register struct databuf *dp;	char dname[MAXDNAME];	register int n, count = 0;	getname(np, dname, sizeof(dname));	for(dp = *dpp++; dp != NULL; dp = *dpp++) {		if (stale(dp))			continue;	/* ignore old cache entry */		if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0)			return(-count);		/* Truncation */		cp += n;		buflen -= n;		count += n;	}	return(count);}/* *  This is best thought of as a "cache invalidate" function. *  It is called whenever a piece of data is determined to have *  timed out.  It is better to have no information, than to *  have partial information you pass off as complete. */delete_all(np, class, type)register struct namebuf *np;int class, type;{	register struct databuf *dp, *pdp;#ifdef DEBUG	if (debug > 2)		fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n",			    np->n_dname, np, class, type);#endif	pdp = NULL;	dp = np->n_data;	while (dp != NULL) {		if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)		    && match(dp, class, type)) {#ifdef ULTRIXFUNC			dp = rm_datum(0, dp, np, pdp);#endif ULTRIXFUNC			continue;		}		pdp = dp;		dp = dp->d_next;	}}#ifdef AUTHENnot_authen(authentype, authenver, dp)	int authentype, authenver;	struct databuf *dp;{	if(dp->d_authen_type == AUTH_CACHE)		return(0);	if (authentype == dp->d_authen_type && authenver == dp->d_authen_ver)		return(0);	if (authentype == AUTH_NONE)		return(0);	return(-1);}#endif AUTHEN

⌨️ 快捷键说明

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