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

📄 ns_req.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
 	 * 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	nsp[0] = NULL;	count = 0;	switch (findns(&np, class, nsp, &count, 0)) {	case NXDOMAIN:		if (!foundname) {			hp->rcode = NXDOMAIN;		}		dprintf(3, (ddt, "req: leaving (%s, rcode %d)\n",			    dname, hp->rcode));		if (class != C_ANY) {			hp->aa = 1;			/* XXX			 * 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, *cpp, *buflenp, np, nsp[0]);				*cpp += n;				*buflenp -= n;#ifdef ADDAUTH			} else if (hp->ancount) {				/* don't add NS records for NOERROR NODATA				   as some severs can get confused */#ifdef DATUMREFCNT				free_nsp(nsp);#endif				switch (findns(&np, class, nsp, &count, 1)) {				case NXDOMAIN:				case SERVFAIL:					break;				default:					if (np) {						n = add_data(np, nsp, *cpp,							     *buflenp);						if (n < 0) {							hp->tc = 1;							n = (-n);						}						*cpp += n;						*buflenp -= n;						hp->nscount = 							htons((u_int16_t)							      count);					}				}#endif /*ADDAUTH*/			}		}#ifdef DATUMREFCNT		free_nsp(nsp);#endif		return Finish;	case SERVFAIL:		if (!founddata && !(forward_only && fwdtab)) {			hp->rcode = SERVFAIL;#ifdef DATUMREFCNT			free_nsp(nsp);#endif			return Finish;		}	}	/*	 *  If we successfully found the answer in the cache,	 *  or this is not a recursive query, or we are purposely	 *  never recursing, then add the nameserver references	 *  ("authority section") here and we're done.	 */	if (founddata || (!hp->rd) || NoRecurse) {		n = add_data(np, nsp, *cpp, *buflenp);		if (n < 0) {			hp->tc = 1;			n = (-n);		}		*cpp += n;		*buflenp -= n;		hp->nscount = htons((u_int16_t)count);#ifdef DATUMREFCNT		free_nsp(nsp);#endif		return Finish;	}	/*	 *  At this point, we don't have the answer, but we do	 *  have some NS's to try.  If the user would like us	 *  to recurse, create the initial query.  If a cname	 *  is involved, we need to build a new query and save	 *  the old one in cmsg/cmsglen.	 */	if (cname) {		omsg = (u_char *)malloc((unsigned) *msglenp);		if (omsg == (u_char *)NULL) {			dprintf(1, (ddt, "ns_req: malloc fail\n"));			syslog(LOG_ERR, "ns_req: Out Of Memory");			hp->rcode = SERVFAIL;			return Finish;		}		id = hp->id;		hp->ancount = htons(hp->ancount);		omsglen = *msglenp;		bcopy(msg, omsg, omsglen);		*msglenp = res_mkquery(QUERY, dname, class, type,				       (char *)NULL, 0, NULL, (char *)msg,				       *msglenp + *buflenp);	}	n = ns_forw(nsp, msg, *msglenp, from, qsp, dfd, &qp, dname);	if (n != FW_OK && cname)		free(omsg);	switch (n) {	case FW_OK:		if (cname) {			qp->q_cname = cname;			qp->q_cmsg = (char *)omsg;			qp->q_cmsglen = omsglen;			qp->q_id = id;		}		break;	case FW_DUP:		break;		/* Duplicate request dropped */	case FW_NOSERVER:		/* 		** Don't go into an infinite loop if 		** the admin gave root NS records in the cache		** file without giving address records		** for the root servers.		*/		if (np) {			if (np->n_dname[0] == '\0') {				dprintf(1, (ddt,					    "ns_req: no address for root NS\n"					    ));				syslog(LOG_ERR, 				       "ns_req: no address for root server");				hp->rcode = SERVFAIL;				return Finish;			}#ifdef	VALIDATE			/*			 * we need to kill all the NS records here as			 * validate will fail as we are talking to the parent			 * server			 */			delete_all(np, class, T_NS);#endif			np = np->n_parent;		}		goto fetchns;	/* Try again. */	case FW_SERVFAIL:		hp->rcode = SERVFAIL;#ifdef DATUMREFCNT		free_nsp(nsp);#endif		return Finish;	}#ifdef DATUMREFCNT	free_nsp(nsp);#endif	return Return;}#if INVQstatic enum req_actionreq_iquery(hp, cpp, eom, buflenp, msg)	HEADER *hp;	u_char **cpp, *eom;	int *buflenp;	u_char *msg;{	register struct invbuf *ip;	int dlen, alen, i, n, type, class, count;	char dnbuf[MAXDNAME], anbuf[PACKETSZ], *data, *fname;	struct namebuf *np;	struct qinfo *qp;	struct databuf *dp;	stats[S_IQUERIES].cnt++;	hp->ancount = htons(hp->ancount);	if ((hp->ancount != 1)	    || hp->qdcount	    || hp->nscount	    || hp->arcount) {		dprintf(1, (ddt, "FORMERR IQuery header counts wrong\n"));		hp->qdcount = 0;		hp->ancount = 0;		hp->nscount = 0;		hp->arcount = 0;		hp->rcode = FORMERR;		return Finish;	}	/*	 * Skip domain name, get class, and type.	 */	if ((n = dn_skipname(*cpp, eom)) < 0) {		dprintf(1, (ddt, "FORMERR IQuery packet name problem\n"));		hp->rcode = FORMERR;		return Finish;	}	*cpp += n;	GETSHORT(type, *cpp);	GETSHORT(class, *cpp);	*cpp += sizeof(u_int32_t);	/* ttl */	GETSHORT(dlen, *cpp);	*cpp += dlen;	if (*cpp != eom) {		dprintf(1, (ddt, "FORMERR IQuery message length off\n"));		hp->rcode = FORMERR;		return Finish;	}	/*	 * not all inverse queries are handled.	 */	switch (type) {	case T_A:	case T_UID:	case T_GID:		break;	default:		return Refuse;	}	dprintf(1, (ddt, "req: IQuery class %d type %d\n", class, type));	fname = (char *)msg + sizeof(HEADER);	bcopy(fname, anbuf, alen = (char *)*cpp - fname);	data = anbuf + alen - dlen;	*cpp = (u_char *)fname;	*buflenp -= sizeof(HEADER);	count = 0;	for (ip = invtab[dhash((u_char *)data, dlen)];	     ip != NULL;	     ip = ip->i_next) {		for (i = 0; i < INVBLKSZ; i++) {			if ((np = ip->i_dname[i]) == NULL)				break;			dprintf(5, (ddt, "dname = %d\n", np->n_dname));			for (dp = np->n_data; dp != NULL; dp = dp->d_next) {				if (!match(dp, class, type))					continue;				if (dp->d_size != dlen ||				    bcmp(dp->d_data, data, dlen))					continue;				getname(np, dnbuf, sizeof(dnbuf));				dprintf(2, (ddt, "req: IQuery found %s\n",					    dnbuf));				*buflenp -= QFIXEDSZ;				if ((n = dn_comp((u_char *)dnbuf, *cpp,						 *buflenp,						 (u_char **)NULL,						 (u_char **)NULL)) < 0) {					hp->tc = 1;					return Finish;				}				*cpp += n;				PUTSHORT((u_int16_t)dp->d_type, *cpp);				PUTSHORT((u_int16_t)dp->d_class, *cpp);				*buflenp -= n;				count++;			}		}	}	dprintf(1, (ddt, "req: IQuery %d records\n", count));	hp->qdcount = htons((u_int16_t)count);	if (alen > *buflenp) {		hp->tc = 1;		return Finish;	}	bcopy(anbuf, *cpp, alen);	*cpp += alen;	return Finish;}#endifstatic voidfwritemsg(rfp, msg, msglen)	FILE *rfp;	char *msg;	int msglen;{	u_int16_t len = htons((u_int16_t)msglen);	if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 ||	    fwrite(msg, msglen, 1, rfp) != 1) {		dprintf(1, (ddt, "fwrite failed %d\n", errno));	}}/* *  Test a datum for validity and return non-zero if it is out of date. */intstale(dp)	register struct databuf *dp;{	register struct zoneinfo *zp = &zones[dp->d_zone];	switch (zp->z_type) {	case Z_PRIMARY:		return (0);	case Z_SECONDARY:#ifdef STUBS	case Z_STUB:#endif		/*		 * Check to see whether a secondary zone		 * has expired; if so clear authority flag		 * for zone and return true.  If lastupdate		 * is in the future, assume zone is up-to-date.		 */		if ((int32_t)(tt.tv_sec - zp->z_lastupdate)		    > (int32_t)zp->z_expire) {			dprintf(1, (ddt,				    "stale: secondary zone %s expired\n",				    zp->z_origin));			if (!haveComplained(zp->z_origin, (char*)stale)) {				syslog(LOG_ERR,				       "secondary zone \"%s\" expired",				       zp->z_origin);			}			zp->z_state &= ~Z_AUTH;			return (1);		}		return (0);	case Z_CACHE:		dprintf(3, (ddt, "stale: ttl %d %d (x%x)\n",			    dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags));		if (dp->d_flags & DB_F_HINT)			return(0);		return(dp->d_ttl < tt.tv_sec);	}	abort();	/* NOTREACHED */}/* * Copy databuf into a resource record for replies. * Return size of RR if OK, -1 if buffer is full. */intmake_rr(name, dp, buf, buflen, doadd)	char *name;	register struct databuf *dp;	u_char *buf;	int buflen, doadd;{	register u_char *cp;	u_char *cp1, *sp;	struct zoneinfo *zp;	register int32_t n;	register int32_t ttl;	u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);	dprintf(5, (ddt, "make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %d\n",		    name, dp, buf,		    buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl));#ifdef	NCACHE	if (dp->d_rcode) {		syslog(LOG_CRIT, "make_rr d_rcode %d", dp->d_rcode);		if (debug) abort();		return -1;	/* XXX We should exit here */	}#endif	zp = &zones[dp->d_zone];	/* check for outdated RR before updating dnptrs by dn_comp() (???) */	if (zp->z_type == Z_CACHE) {		ttl = dp->d_ttl - (u_int32_t) tt.tv_sec;		if ((dp->d_flags & DB_F_HINT) || (ttl < 0)) {			dprintf(3, (ddt,				    "make_rr: %d=>0, x%x\n",				    ttl, dp->d_flags));		/* XXX */			ttl = 0;		}	} else {		if (dp->d_ttl)			ttl = dp->d_ttl;		else			ttl = zp->z_minimum;		/* really default */#ifdef notdef /* don't decrease ttl based on time since verification */		if (zp->z_type == Z_SECONDARY) {			/*			 * Set ttl to value received from primary,			 * less time since we verified it (but never			 * less than a small positive value).			 */			ttl -= tt.tv_sec - zp->z_lastupdate;			if (ttl <= 0)				ttl = 120;		}#endif	}	buflen -= RRFIXEDSZ;	if ((n = dn_comp((u_char *)name, (u_char *)buf, buflen,	    (u_char **)dnptrs, (u_char **)edp)) < 0)		return (-1);	cp = buf + n;	buflen -= n;	PUTSHORT((u_int16_t)dp->d_type, cp);	PUTSHORT((u_int16_t)dp->d_class, cp);	PUTLONG(ttl, cp);	sp = cp;	cp += sizeof(u_int16_t);	switch (dp->d_type) {	case T_CNAME:	case T_MG:	case T_MR:	case T_PTR:		if ((n = dn_comp((u_char *)dp->d_data, (u_char *)cp, buflen,		    (u_char **)dnptrs, (u_char **)edp)) < 0)			return (-1);		PUTSHORT((u_int16_t)n, sp);		cp += n;		break;	case T_MB:	case T_NS:		/* Store domain name in answer */		if ((n = dn_comp((u_char *)dp->d_data, (u_char *)cp, buflen,		    (u_char **)dnptrs, (u_char **)edp)) < 0)			return (-1);		PUTSHORT((u_int16_t)n, sp);		cp += n;		if (doadd)			addname((char*)dp->d_data, dp->d_class);		break;	case T_SOA:	case T_MINFO:	case T_RP:		cp1 = dp->d_data;		if ((n = dn_comp((u_char *)cp1, (u_char *)cp, buflen,		    (u_char **)dnptrs, (u_char **)edp)) < 0)			return (-1);		cp += n;		buflen -= dp->d_type == T_SOA ? n + 5 * sizeof(u_int32_t) : n;		cp1 += strlen((char *)cp1) + 1;		if ((n = dn_comp((u_char *)cp1, (u_char *)cp, buflen,		    (u_char **)dnptrs, (u_char **)edp)) < 0)			return (-1);		cp += n;		if (dp->d_type == T_SOA) {			cp1 += strlen((char *)cp1) + 1;			bcopy(cp1, cp,			   (int)(n = dp->d_size - (cp1 - dp->d_data)));			cp += n;		}		n = (u_int16_t)((cp - sp) - sizeof(u_int16_t));		PUTSHORT((u_int16_t)n, sp);		break;	case T_MX:	case T_AFSDB:		/* cp1 == our data/ cp == data of RR */		cp1 = dp->d_data; 		/* copy preference */ 		bcopy(cp1, cp, sizeof(u_int16_t)); 		cp += sizeof(u_int16_t); 		cp1 += sizeof(u_int16_t); 		buflen -= sizeof(u_int16_t);  		if ((n = dn_comp((u_char *)cp1, (u_char *)cp, buflen,		    (u_char **)dnptrs, (u_char **)edp)) < 0)  			return(-1);  		cp += n;  		/* save data length */		n = (u_int16_t)((cp - sp) - sizeof(u_int16_t));  		PUTSHORT((u_int16_t)n, sp);		if (doadd)			addname((char*)cp1, dp->d_class);		break;	default:		if (dp->d_size > buflen)			return (-1);		bcopy(dp->d_data, cp, dp->d_size);		PUTSHORT((u_int16_t)dp->d_size, sp);		cp += dp->d_size;	}	return (cp - buf);}#if defined(__STDC__) || defined(__GNUC__)static voidaddname(register char *name,	u_int16_t class)#elsestatic voidaddname(name, class)	register char	*name;	u_int16_t	class;#endif{	register struct addinfo *ap;	register int n;	for (ap = addinfo, n = addcount; --n >= 0; ap++)		if (strcasecmp(ap->a_dname, name) == 0)			return;		/* add domain name to additional section */	if (addcount < NADDRECS) {		addcount++;		ap->a_dname = malloc(strlen(name)+1);		strcpy(ap->a_dname,name);		ap->a_class = class;	}}/* * Lookup addresses for names in addinfo and put into the message's * additional section. */intdoaddinfo(hp, msg, msglen)	HEADER *hp;	u_char *msg;	int msglen;{	register struct namebuf *np;	register struct databuf *dp;	register struct addinfo *ap;	register u_char *cp;	struct hashbuf *htp;	char *fname;	int n, count;	dprintf(3, (ddt, "doaddinfo() addcount = %d\n", addcount));	if (hp->tc) {		dprintf(4, (ddt, "doaddinfo(): tc already set, bailing\n"));		return 0;	}	count = 0;	cp = msg;	for (ap = addinfo; --addcount >= 0; ap++) {		int	foundstale = 0,			foundany = 0,			save_count = count,			save_msglen = msglen;		u_char	*save_cp = cp;		dprintf(3, (ddt, "do additional '%s'\n", ap->a_dname));		htp = hashtab;	/* because "nlookup" stomps on arg. */		np = nlookup(ap->a_dname, &htp, &fname, 0);		if (np == NULL || fname != ap->a_dname)			goto next_rr;		dprintf(3, (ddt, "found it\n"));		/* look for the data */		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {			if ( (!match(dp, (int)ap->a_class, T_A))			  && (!match(dp, C_IN, T_A))			   ) {				continue;			}			foundany++;			if (stale(dp)) {				foundstale++;

⌨️ 快捷键说明

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