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

📄 ns_resp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Check the list of root servers after receiving a response * to a query for the root servers. */static voidcheck_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++;	dprintf(1, (ddt, "%d root servers\n", count));	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) {			dprintf(1, (ddt, "deleting old root server '%s'\n",				    dp->d_data));			dp = rm_datum(dp, np, pdp);			/* 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 */static voidcheck_ns(){	register struct databuf *dp, *tdp;	register struct namebuf *np, *tnp;	struct hashbuf *htp;	char *dname;	int found_arr;	char *fname;	time_t curtime;	dprintf(2, (ddt, "check_ns()\n"));	stats[S_CHECKNS].cnt++;	curtime = (u_int32_t) 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 = (caddr_t) dp->d_data;			htp = hashtab;			tnp = nlookup(dname, &htp, &fname, 0);			if (tnp == NULL || fname != dname) {				dprintf(3, (ddt,					    "check_ns: %s: not found %s %x\n",					    dname, fname, tnp));			    sysquery(dname, dp->d_class, T_A, NULL, 0);			    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)) {				dprintf(3, (ddt,					    "check_ns: stale entry '%s'\n",					    tnp->n_dname));				/* 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, NULL, 0);	        }	}}/* *  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. */intfindns(npp, class, nsp, countp, flag)	register struct namebuf **npp;	int class;	struct databuf **nsp;	int *countp;	int flag;{	register struct namebuf *np = *npp;	register struct databuf *dp;	register struct	databuf **nspp;	struct hashbuf *htp;		if (priming && (np == NULL || np->n_dname[0] == '\0'))		htp = fcachetab;	else		htp = hashtab;try_again:	if (htp == fcachetab)		needs_prime_cache = 1;	while (np == NULL && htp != NULL) {		dprintf(3, (ddt, "findns: using %s\n", htp == hashtab ?			    "cache" : "hints"));		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) {		dprintf(5, (ddt, "findns: np 0x%x '%s'\n", np, np->n_dname));		/* Look first for SOA records. */#ifdef ADDAUTH		if(!flag)#endif		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {			if (dp->d_zone != 0 && match(dp, class, T_SOA)) {				dprintf(3, (ddt, "findns: SOA found\n"));				if (zones[dp->d_zone].z_state & Z_AUTH) {					*npp = np;					nsp[0] = dp;#ifdef DATUMREFCNT					nsp[1] = NULL;					dp->d_rcnt++;#endif					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)) {				dprintf(1, (ddt, "findns: stale entry '%s'\n",					    np->n_dname));				/* 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;#ifdef DATUMREFCNT				dp->d_rcnt++;#endif			}		}		*countp = nspp - nsp;		if (*countp > 0) {			dprintf(3, (ddt, "findns: %d NS's added for '%s'\n",				    *countp, np->n_dname));			*nspp = NULL;			*npp = np;			return OK;	/* Success, got some NS's */		}try_parent:		np = np->n_parent;	}	if (htp)		goto try_again;	dprintf(1, (ddt, "findns: No root nameservers for class %d?\n",		    class));	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. */intfinddata(np, class, type, hp, dnamep, lenp, countp)	struct namebuf *np;	int class, type;	register HEADER *hp;	char **dnamep;	int *lenp, *countp;{	register struct databuf *dp;	register char *cp;	int buflen, n, count = 0, foundstale = 0;#ifdef ROUND_ROBIN	if (type != T_ANY) {		/* cycle order of RRs, for a load balancing effect... */		register struct databuf **dpp; 		for (dpp = &np->n_data;  *dpp;  dpp = &dp->d_next) {			dp = *dpp;			if (dp->d_next && wanted(dp, class, type)) {				register struct databuf *lp;				*dpp = lp = dp->d_next;				dp->d_next = NULL;				for (dpp = &lp->d_next;				     *dpp;				     dpp = &lp->d_next) {					lp = *dpp;				}				*dpp = dp;				break;			}		}	}#endif /*ROUND_ROBIN*/  	buflen = *lenp;	cp = ((char *)hp) + *countp;	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {		if (!wanted(dp, class, type)) {#ifndef NCACHE /*if no negative caching then cname => nothing else*/			if (type == T_CNAME && class == dp->d_class) {				/* any data means no CNAME exists */				*countp = 0;				return 0;			}#endif /*NCACHE*/			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.			 */			dprintf(3, (ddt,				    "finddata: stale entry '%s'\n",				    np->n_dname));			if (dp->d_zone == 0)				foundstale++;			continue;		}#ifdef CRED		if (dp->d_cred == DB_C_ADDITIONAL) {			/* we want to expire additional data very			 * quickly.  current strategy is to cut 5%			 * off each time it is accessed.  this makes			 * stale(dp) true faster when this datum is			 * used often.			 */			dp->d_ttl = tt.tv_sec					+				0.95 * (dp->d_ttl - tt.tv_sec);		}#endif /*CRED*/#ifdef NCACHE		/* -ve $ing stuff, anant@isi.edu		 * if we have a -ve $ed record, change the rcode on the		 * header to reflect that		 */		if (dp->d_rcode == NOERROR_NODATA) {			if (count != 0) {				/*				 * This should not happen, yet it does...				 */				syslog(LOG_WARNING,				  "NODATA & data for \"%s\" type %d class %d",				    *dnamep, type, class);				continue;			}			if (type != T_ANY) {				hp->rcode = NOERROR_NODATA;				*countp = 0;				return 1; /* XXX - we have to report success */			}			/* don't satisfy T_ANY queries from -$ info */			continue;		}		if (dp->d_rcode == NXDOMAIN) {			if (count != 0) {				/*				 * This should not happen, yet it might...				 */				syslog(LOG_WARNING,				  "NXDOMAIN & data for \"%s\" type %d class %d",				    *dnamep, type, class);				continue;			}			if (type != T_ANY) {				hp->rcode = NXDOMAIN;				*countp = 0;				return 1; /* XXX - we have to report success */			}			/* don't satisfy T_ANY queries from -$ info */			continue;		}#endif /*NCACHE*/		if ((n = make_rr(*dnamep, dp, (u_char *)cp, buflen, 1)) < 0) {			hp->tc = 1;			*countp = count;			return (*lenp - buflen);		}		cp += n;		buflen -= n;		count++;#ifdef notdef		/* this isn't right for glue records, aa is set in ns_req */		if (dp->d_zone &&		    (zones[dp->d_zone].z_state & Z_AUTH) &&		    class != C_ANY)			hp->aa = 1;			/* XXX */#endif		if (dp->d_type == T_CNAME) {			if (type != T_ANY) {	/* or T_NS? */				*dnamep = (caddr_t) dp->d_data;				if (dp->d_zone &&				    (zones[dp->d_zone].z_state & 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	 */	if (foundstale) {		delete_all(np, class, type);		/* XXX this isn't right if 'type' is something special		 * such as T_AXFR or T_MAILB, since the matching done		 * by match() in delete_all() is different from that		 * done by wanted() above.		 */	}	dprintf(3, (ddt, "finddata: added %d class %d type %d RRs\n",		    count, class, type));	*countp = count;	return (*lenp - buflen);}/* * Do we want this data record based on the class and type? */intwanted(dp, class, type)	struct databuf *dp;	int class, type;{	dprintf(3, (ddt, "wanted(%x, %d, %d) %d, %d\n", dp, class, type,		    dp->d_class, dp->d_type));	if (dp->d_class != class && class != C_ANY)		return (0);	if (type == dp->d_type)		return (1);#ifdef NCACHE	/*-ve $ing stuff, for a T_ANY query, we do not want to return	 * -ve $ed RRs.	 */	if (type == T_ANY && dp->d_rcode == NOERROR_NODATA)		return (0);#endif	switch (dp->d_type) {	case T_ANY:		return (1);	case T_CNAME:#ifdef NCACHE              if (dp->d_rcode != NOERROR_NODATA)#endif                      return (1);#ifdef NCACHE              else                      break;#endif	}	switch (type) {	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:		/* T_AXFR needs an authoritative SOA */		if (dp->d_type == T_SOA && dp->d_zone != 0		    && (zones[dp->d_zone].z_state & Z_AUTH))			return (1);		break;	}	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. */intadd_data(np, dpp, cp, buflen)	struct namebuf *np;	struct databuf **dpp;	register u_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 */#ifdef NCACHE		if (dp->d_rcode)			continue;#endif		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. */voiddelete_all(np, class, type)	register struct namebuf *np;	int class, type;{	register struct databuf *dp, *pdp;	dprintf(3, (ddt, "delete_all: '%s' 0x%x class %d type %d\n",		    np->n_dname, np, class, type));	pdp = NULL;	dp = np->n_data;	while (dp != NULL) {		if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)		    && match(dp, class, type)) {			dp = rm_datum(dp, np, pdp);			continue;		}		pdp = dp;		dp = dp->d_next;	}}

⌨️ 快捷键说明

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