ns_req.c

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

C
1,919
字号
		case FW_NOSERVER:			if(np)				np = np->n_parent;			if(findns_count > 50) {				needreload = 1;#ifdef DEBUG				if (debug)				    fprintf(ddt,"ns_req:TOO many findns calls.\n");#endif				syslog(LOG_ERR, "ns_req:TOO many findns calls.  Auto HUP begins.");				return;			}			goto fetchns;	/* Try again. */		case FW_SERVFAIL:			hp->rcode = SERVFAIL;			goto finish;		}		/* Now is a safe time for housekeeping */		if (needs_prime_cache)			prime_cache();		return;	case IQUERY: {		register struct invbuf *ip;		register int i;		int dlen, alen;/* PACKETSZ below was changed to BUFSIZ.  This could affect transfers through   gateways.  Fix the problem with TCP and malloc.  */		char anbuf[BUFSIZ], *data;#ifdef STATS		stats[S_IQUERIES].cnt++;#endif		hp->ancount = htons(hp->ancount);		if (hp->ancount != 1 ||		    hp->qdcount || hp->nscount || hp->arcount) {#ifdef DEBUG			if (debug)			    fprintf(ddt,"FORMERR IQuery header counts wrong\n");#endif			hp->qdcount = 0;			hp->ancount = 0;			hp->nscount = 0;			hp->arcount = 0;			hp->rcode = FORMERR;			goto finish;		}		/*		 * Skip domain name, get class, and type.		 */		if ((n = dn_skipname(cp, eom)) < 0) {#ifdef DEBUG			if (debug)			    fprintf(ddt,"FORMERR IQuery packet name problem\n");#endif			hp->rcode = FORMERR;			goto finish;		}		cp += n;		GETSHORT(type, cp);		GETSHORT(class, cp);		cp += sizeof(u_long);		GETSHORT(dlen, cp);		cp += dlen;		if (cp != eom) {#ifdef DEBUG			if (debug)			    fprintf(ddt,"FORMERR IQuery message length off\n");#endif			hp->rcode = FORMERR;			goto finish;		}		/* not all inverse queries are handled. */		switch (type) {		case T_A:		case T_UID:		case T_GID:			break;		default:			hp->rcode = REFUSED;			goto finish;		}#ifdef DEBUG		if (debug)			fprintf(ddt,"req: IQuery class %d type %d\n",				class, type);#endif		fname = (char *)msg + sizeof(HEADER);		bcopy(fname, anbuf, alen = (char *)cp - fname);		data = anbuf + alen - dlen;		cp = (u_char *)fname;		buflen -= sizeof(HEADER);		count = 0;		for (ip = invtab[dhash(data, dlen)]; ip != NULL;		    ip = ip->i_next) {		    for (i = 0; i < INVBLKSZ; i++) {			if ((np = ip->i_dname[i]) == NULL)				break;#ifdef DEBUG			if (debug >= 5)				fprintf(ddt,"dname = %d\n", np->n_dname);#endif			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));#ifdef DEBUG				if (debug > 2)					fprintf(ddt,"req: IQuery found %s\n",						dnbuf);#endif				buflen -= QFIXEDSZ;				if ((n =				   dn_comp(dnbuf, cp, buflen, (char **)NULL,				      (char **)NULL)) < 0)				{					hp->tc = 1;					goto finish;				}				cp += n;				PUTSHORT((u_short)dp->d_type, cp);				PUTSHORT((u_short)dp->d_class, cp);				buflen -= n;				count++;			}		    }		}#ifdef DEBUG		if (debug)			fprintf(ddt,"req: IQuery %d records\n", count);#endif		hp->qdcount = htons((u_short)count);		if (alen > buflen) {			hp->tc = 1;			break;		}		bcopy(anbuf, cp, alen);		cp += alen;		break;	    }#ifdef ALLOW_UPDATES/* * In a sense the following constant should be defined in <arpa/nameser.h>, * since it is returned here in place of a response code if the update was * forwarded, and the response codes are defined in nameser.h.  On the other * hand, though, this constant is only seen in this file.  The assumption * here is that none of the other return codes equals this one (a good * assumption, since they only occupy 4 bits over-the-wire) */#define FORWARDED 1000        /* Call InitDynUpdate for all dynamic update requests */        case UPDATEM:        case UPDATEMA:        case UPDATED:        case UPDATEDA:        case UPDATEA:                n = InitDynUpdate(hp, nsp, msg, msglen, cp, from, qsp, dfd);                if (n == FORWARDED)                        return; /* Return directly because InitDynUpdate                                 * forwarded the query to the primary, so we                                 * will send response later                                 */                else                        break;  /* Either sucessful primary update or failure;                                 * return response code to client                                 */#endif ALLOW_UPDATES	case ZONEREF:#ifdef DEBUG		if (debug)			fprintf(ddt,"Refresh Zone\n");#endif	default:#ifdef DEBUG		if (debug >= 2)			fprintf(ddt,"Opcode %d not implemented\n", hp->opcode);#endif		hp->qdcount = 0;		hp->ancount = 0;		hp->nscount = 0;		hp->arcount = 0;		hp->rcode = NOTIMP;	}finish:#ifdef STATS	switch(hp->rcode) {	case NOERROR:		stats[S_RESPOK].cnt++;		break;	case FORMERR:		stats[S_RESPFORMERR].cnt++;		break;	default:		stats[S_RESPFAIL].cnt++;		break;	}#endif	hp->qr = 1;		/* set Response flag */	hp->ra = 1;		/* Recursion is Available */	hp->ancount = htons(hp->ancount);#ifdef AUTHEN	if(netsafe && query_to_aquery) {		if(fixup_rrs(ocp, (int)(cp - ocp), (int)(ocp - (u_char *)hp),				-(2 * sizeof(u_short)))	< 0)			return(-1);		ocp2 = ocp;		ocp -= 2 * sizeof(u_short);		bcopy(ocp2, ocp, cp - ocp2);		hp->opcode = QUERY;		query_to_aquery = 0;		cp -= 2 * sizeof(u_short);	}#endif AUTHEN	if (addcount) {#ifdef AUTHEN		if(hp->opcode == AQUERY)			n = doaddinfo(hp, cp, DEFSIZE_KRBCRED);		else			n = doaddinfo(hp, cp, buflen);#else		n = doaddinfo(hp, cp, buflen);#endif AUTHEN		cp += n;		buflen -= n;	}	#ifdef AUTHEN	if(hp->opcode == AQUERY && read_cred) {		/* switch on auth type */		dnptr = dname_authenrr;		if(type_authenrr != T_SOA && type_authenrr != T_AXFR)			res_dotname_rmhead(&dnptr);		hp->arcount = htons(1 + ntohs(hp->arcount));		if((cred_len = res_mks_krbcred(auth_version,					       "", "", &ns_ad,					       hp, cp, buflen,					       dnptr,					       type_authenrr,					       class_authenrr))		   < RET_OK) {			hp->rcode = AUTHENBAD;			cp = ocp;			hp->ancount = 0;			hp->nscount = 0;			hp->arcount = 0;		} else {			cp += cred_len;		}	}#endif AUTHEN			#ifdef DEBUG	if (debug) {	    fprintf(ddt,"req: answer -> %s %d (%d) id=%d %s\n",	        inet_ntoa(from->sin_addr), dfd, ntohs(from->sin_port),		ntohs(hp->id), local(from) == NULL ? "Remote" : "Local");	}	if (debug >= 10)		fp_query(msg, ddt);#endif DEBUG	if (qsp == QSTREAM_NULL) {		if (sendto(dfd, msg, cp-msg, 0, (struct sockaddr *)from,		    sizeof(*from))< 0){#ifdef DEBUG			if (debug)			    fprintf(ddt,"error returning msg errno=%d\n",errno);#endif DEBUG		}#ifdef STATS		stats[S_OUTPKTS].cnt++;#endif	} else {		(void) writemsg(qsp->s_rfd, msg, cp - msg);		qsp->s_time = tt.tv_sec;		qsp->s_refcnt--;	}	if (needs_prime_cache)		prime_cache();	/* Now is a safe time */}fwritemsg(rfp, msg, msglen)	FILE *rfp;	char *msg;	int msglen;{	u_short len = htons((u_short)msglen);	if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 ||	    fwrite(msg, msglen, 1, rfp) != 1) {#ifdef DEBUG		if (debug)			fprintf(ddt,"fwrite failed %d\n", errno);#endif	}	return;}writemsg(rfd, msg, msglen)	int rfd;	char *msg;	int msglen;{	struct iovec iov[2];	u_short len = htons((u_short)msglen);	iov[0].iov_base = (caddr_t)&len;	iov[0].iov_len = sizeof(len);	iov[1].iov_base = msg;	iov[1].iov_len = msglen;	if (writev(rfd, iov, 2) != sizeof(len) + msglen) {#ifdef DEBUG		if (debug)			fprintf(ddt,"write failed %d\n", errno);#endif		return (-1);	}	return (0);}/* *  Test a datum for validity and return non-zero if it is out of date. */stale(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:		return ((u_long)(tt.tv_sec - zp->z_lastupdate) > zp->z_expire);	case Z_CACHE:#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"stale: ttl %d %d (x%x)\n",				dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags);#endif		if (dp->d_flags & DB_F_HINT)			return(0);		return(dp->d_ttl < tt.tv_sec);	}	/* NOTREACHED */}/* * Copy databuf into a resource record for replies. * Return size of RR if OK, -1 if buffer is full. */make_rr(name, dp, buf, buflen, doadd)	char *name;	register struct databuf *dp;	char *buf;	int buflen, doadd;{	register char *cp;	char *cp1, *sp;	struct zoneinfo *zp;	register long n;	register long ttl;	u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);#ifdef DEBUG	if (debug >= 5)		fprintf(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);#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_long) tt.tv_sec;		if ((dp->d_flags & DB_F_HINT) || (ttl <= 0)) {#ifdef DEBUG/*XXX*/if (debug >= 3) fprintf(ddt,"make_rr: %d=>1, x%x\n", ttl, dp->d_flags);#endif			ttl = 1;		}	} else {		ttl = zp->z_minimum;		/* really default */		if (dp->d_ttl > 0)			ttl = dp->d_ttl;		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;		}	}	buflen -= RRFIXEDSZ;	if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0)		return (-1);	cp = buf + n;	buflen -= n;	PUTSHORT((u_short)dp->d_type, cp);	PUTSHORT((u_short)dp->d_class, cp);	PUTLONG(ttl, cp);	sp = cp;	cp += sizeof(u_short);	switch (dp->d_type) {	case T_CNAME:	case T_MG:	case T_MR:	case T_PTR:		if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,		   (char **)edp)) < 0)			return (-1);		PUTSHORT((u_short)n, sp);		cp += n;		break;	case T_MB:	case T_NS:		/* Store domain name in answer */		if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,		   (char **)edp)) < 0)			return (-1);		PUTSHORT((u_short)n, sp);		cp += n;		if (doadd)			addname(dp->d_data, dp->d_class);		break;	case T_SOA:	case T_MINFO:		cp1 = dp->d_data;		if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,		    (char **)edp)) < 0)			return (-1);		cp += n;		buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long);		cp1 += strlen(cp1) + 1;		if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,		    (char **)edp)) < 0)			return (-1);		cp += n;		if (dp->d_type == T_SOA) {			cp1 += strlen(cp1) + 1;			bcopy(cp1, cp,			   (int)(n = dp->d_size - (cp1 - dp->d_data)));			cp += n;		}		n = (u_short)(cp - sp) - sizeof(u_short);		PUTSHORT((u_short)n, sp);		break;	case T_MX:		/* cp1 == our data/ cp == data of RR */		cp1 = dp->d_data; 		/* copy preference */ 		bcopy(cp1,cp,sizeof(u_short)); 		cp += sizeof(u_short); 		cp1 += sizeof(u_short); 		buflen -= sizeof(u_short);  		if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,		    (char **)edp)) < 0)  			return(-1);  		cp += n;  		/* save data length */  		n = (u_short)(cp - sp) - sizeof(u_short);  		PUTSHORT((u_short)n, sp);		if (doadd)			addname(cp1, dp->d_class);		break;	default:		if (dp->d_size > buflen)			return (-1);		bcopy(dp->d_data, cp, dp->d_size);		PUTSHORT((u_short)dp->d_size, sp);		cp += dp->d_size;	}	return (cp - buf);}addname(name, class)register char	*name;short	class;{	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 = name;		ap->a_class = class;	}}/* * Lookup addresses for names in addinfo and put into the message's * additional section. */doaddinfo(hp, msg, msglen)	HEADER *hp;	char *msg;	int msglen;{	register struct namebuf *np;	register struct databuf *dp;	register struct addinfo *ap;	register char *cp;	struct hashbuf *htp;	char *fname;	int n, count, foundstale;#ifdef DEBUG	if (debug >= 3)		fprintf(ddt,"doaddinfo() addcount = %d\n", addcount);#endif	count = 0;	cp = msg;	for (ap = addinfo; --addcount >= 0; ap++) {#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"do additional '%s'\n", ap->a_dname);#endif		htp = hashtab;	/* because "nlookup" stomps on arg. */		np = nlookup(ap->a_dname, &htp, &fname, 0);		if (np == NULL || fname != ap->a_dname)			continue;#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"found it\n");#endif		foundstale = 0;		/* look for the data */		for (dp = np->n_data; dp != NULL; dp = dp->d_next) {			if (!match(dp, (int)ap->a_class, T_A))				continue;			if (stale(dp)) {				foundstale++;#ifdef DEBUG				if (debug)				    fprintf(ddt,"doaddinfo: stale entry '%s'%s\n",					    np->n_dname,					    (dp->d_flags&DB_F_HINT) ? " hint":"" );#endif				continue;			}			/*			 *  Should be smart and eliminate duplicate			 *  data here.	XXX			 */			if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0)				break;#ifdef DEBUG			if (debug >= 5)			    fprintf(ddt,"addinfo: adding address data n = %d\n",			       n);#endif			cp += n;			msglen -= n;			count++;		}		if (foundstale) {			/* Cache invalidate the address RR's */			delete_all(np, (int)ap->a_class, T_A);			(void) sysquery(ap->a_dname, (int)ap->a_class, T_A);		}	}	hp->arcount = htons((u_short)count);	return (cp - msg);}doaddauth(hp, cp, buflen, np, dp)	register HEADER *hp;	char *cp;	int buflen;	struct namebuf *np;	struct databuf *dp;{	char dnbuf[MAXDNAME];	int n;	getname(np, dnbuf, sizeof(dnbuf));	if (stale(dp) || (n = make_rr(dnbuf, dp, cp, buflen, 1)) <= 0) {#ifdef DEBUG		if (debug)			fprintf(ddt,"doaddauth: can't add '%s' (%d)\n",				dnbuf, buflen);#endif		return(0);	} else {		hp->nscount = htons(1);		return(n);	}}/* * Get the domain name of 'np' and put in 'buf'.  Bounds checking is done. */getname(np, buf, buflen)	struct namebuf *np;	char *buf;	int buflen;{	register char *cp;	register int i;	cp = buf;	while (np != NULL) {		if ((i = strlen(np->n_dname))+1 >= buflen) {			*cp = '\0';			syslog(LOG_ERR, "domain name too long: %s...\n", buf);

⌨️ 快捷键说明

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