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

📄 ns_resp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			return (-1);		}		cp += n;		cp1 = data + (n = strlen((char *)data) + 1);		n1 = sizeof(data) - n;		if (type == T_SOA)			n1 -= 5 * sizeof(u_int32_t);		if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,		    cp, cp1, n1)) < 0) {			hp->rcode = FORMERR;			return (-1);		}		cp += n;		cp1 += strlen((char *)cp1) + 1;		if (type == T_SOA) {			bcopy(cp, cp1, n = 5 * sizeof(u_int32_t));			cp += n;			cp1 += n;		}		n = cp1 - data;		cp1 = data;		break;	case T_MX:	case T_AFSDB:		/* grab preference */		bcopy(cp, data, sizeof(u_int16_t));		cp1 = data + sizeof(u_int16_t);		cp += sizeof(u_int16_t);		/* get name */		if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,		    cp, cp1, sizeof(data) - sizeof(u_int16_t))) < 0) {			hp->rcode = FORMERR;			return(-1);		}		cp += n;		/* compute end of data */		cp1 += strlen((char *)cp1) + 1;		/* compute size of data */		n = cp1 - data;		cp1 = data;		break;	default:		dprintf(3, (ddt, "unknown type %d\n", type));		return ((cp - rrp) + dlen);	}	if (n > MAXDATA) {		dprintf(1, (ddt,			    "update type %d: %d bytes is too much data\n",			    type, n));		hp->rcode = NOCHANGE;	/* XXX - FORMERR ??? */		return(-1);	}#ifdef ALLOW_UPDATES	/*	 * If this is a dynamic update request, process it specially; else,	 * execute normal update code.	 */	switch(hp->opcode) {	/* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */	case UPDATEM:	case UPDATEMA:	/*	 * The named code for UPDATED and UPDATEDA is the same except that for	 * UPDATEDA we we ignore any data that was passed: we just delete all	 * RRs whose name, type, and class matches	 */	case UPDATED:	case UPDATEDA:		if (type == T_SOA) {	/* Not allowed */			dprintf(1, (ddt, "UDPATE: REFUSED - SOA delete\n"));			hp->rcode = REFUSED;			return(-1);		}		/*		 * Don't check message length if doing UPDATEM/UPDATEMA,		 * since the whole message wont have been demarshalled until		 * we reach the code for UPDATEA		 */		if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {			if (cp != (u_char *)(msg + msglen)) {			    dprintf(1,				    (ddt, 				     "FORMERR UPDATE message length off\n"				     )				    );			    hp->rcode = FORMERR;			    return(-1);			}		}		if ((zonenum = findzone(dname, class)) == 0) { 			hp->rcode = NXDOMAIN;			return(-1);		}		if (zones[zonenum].z_state & Z_DYNADDONLY) {			hp->rcode = NXDOMAIN;			return(-1);		}		if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {			/* Make a dp for use in db_update, as old dp */			dp = savedata(class, type, 0, cp1, n);			dp->d_zone = zonenum;#ifdef CRED			dp->d_cred = cred;			dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif			n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,				      hashtab);			if (n != OK) {				dprintf(1, (ddt,					    "UPDATE: db_update failed\n"));				free((char*) dp);				hp->rcode = NOCHANGE;				return(-1);			}		} else {	/* UPDATEDA or UPDATEMA */			int DeletedOne = 0;			/* Make a dp for use in db_update, as old dp */			dp = savedata(class, type, 0, NULL, 0);			dp->d_zone = zonenum;#ifdef CRED			dp->d_cred = cred;			dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif			do {	/* Loop and delete all matching RR(s) */				n = db_update(dname, dp, NULL, DB_DELETE,					      hashtab);				if (n != OK)					break;				DeletedOne++;			} while (1);			free((char*) dp);			/* Ok for UPDATEMA not to have deleted any RRs */			if (!DeletedOne && hp->opcode == UPDATEDA) {				dprintf(1, (ddt,					    "UPDATE: db_update failed\n"));				hp->rcode = NOCHANGE;				return(-1);			}		}		if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )			return (cp - rrp);;		/*		 * Else unmarshal the RR to be added and continue on to		 * UPDATEA code for UPDATEM/UPDATEMA		 */		if ((n =		   dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {			dprintf(1, (ddt,				    "FORMERR UPDATE expand name failed\n"));			hp->rcode = FORMERR;			return(-1);		}		cp += n;		GETSHORT(type, cp);		GETSHORT(class, cp);		GETLONG(ttl, cp);		GETSHORT(n, cp);		cp1 = cp;/**** XXX - need bounds checking here ****/		cp += n;	case UPDATEA:		if (n > MAXDATA) {			dprintf(1, (ddt, "UPDATE: too much data\n"));			hp->rcode = NOCHANGE;			return(-1);		}		if (cp != (u_char *)(msg + msglen)) {			dprintf(1, (ddt,				    "FORMERR UPDATE message length off\n"));			hp->rcode = FORMERR;			return(-1);		}		if ((zonenum = findzone(dname, class)) == 0) { 			hp->rcode = NXDOMAIN;			return(-1);		}		if (zones[zonenum].z_state & Z_DYNADDONLY) {			struct hashbuf *htp = hashtab;			char *fname;			if (nlookup(dname, &htp, &fname, 0) &&			    !strcmp(dname, fname)) {				dprintf(1, (ddt,					    "refusing add of existing name\n"					    ));				hp->rcode = REFUSED;				return(-1);			}		}		dp = savedata(class, type, ttl, cp1, n);		dp->d_zone = zonenum;#ifdef CRED		dp->d_cred = cred;		dp->d_clev = db_getclev(zones[zonenum].z_origin);#endif		if ((n = db_update(dname, NULL, dp, DB_NODATA,				   hashtab)) != OK) {			dprintf(1, (ddt, "UPDATE: db_update failed\n"));			hp->rcode = NOCHANGE;			free((char*) dp);	/* vix@dec mar92 */			return (-1);		}		else			return (cp - rrp);	}#endif /* ALLOW_UPDATES */	if (zone == 0)		ttl += tt.tv_sec;#if defined(TRACEROOT) || defined(BOGUSNS)	/*	 *  This is a variation on a theme which was posted by	 *  pma@cnd.hp.com.  It not only records who is giving out	 *  bogus root NS records, it also prevents them from 	 *  polluting our cache.	 */	if ((type == T_NS) && (savens != NULL)) {		char qname[MAXDNAME], *temp;		int bogus = 0, qn;#ifdef BOGUSNS		if (net_on_netlist(from_addr.sin_addr, boglist))			bogus++;#endif		if (!bogus &&		    ((temp = strrchr((char *)data, '.')) != NULL) &&		     !strcasecmp(temp, ".arpa")		     )			bogus++;		qname[0] = qname[1] = '\0';		qn = dn_expand((u_char *)msg, (u_char *)msg + msglen,			       (u_char *)msg + sizeof(HEADER),			       (u_char *)qname, sizeof(qname));		if (qn < 0)			qname[0] = '?';		else if (qname[0] == '\0')			qname[0] = '.';		if (bogus && ((dname[0] == '\0') && (zone == 0))) {/* We want the filtering but not (normally) the syslogging, since we are   occasionally plagued with multi-megabyte floods of syslog messages.   syslog call therefore replaced with dprintf call.*/			       dprintf(1, (ddt,    "Bogus root NS %s received from %s on query on name [%s] -- rejected\n",			       data,			       inet_ntoa(from_addr.sin_addr),			       qname));			return(cp - rrp);		}	}#endif /*TRACEROOT || BOGUSNS*/	dp = savedata(class, type, ttl, cp1, n);	dp->d_zone = zone;#ifdef CRED	dp->d_cred = cred;	dp->d_clev = 0;	/* We trust what is on disk more, except root servers */#endif	if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) {#ifdef DEBUG		if (debug && (n != DATAEXISTS))			fprintf(ddt,"update failed (%d)\n", n);		else if (debug >= 3)			fprintf(ddt,"update failed (DATAEXISTS)\n");#endif		free((char *)dp);	} else if (type == T_NS && savens != NULL)		*savens = dp;	return (cp - rrp);}intsend_msg(msg, msglen, qp)	char *msg;	int msglen;	struct qinfo *qp;{#ifdef DEBUG	struct qinfo *tqp;#endif /* DEBUG */	if (qp->q_flags & Q_SYSTEM)		return(1);#ifdef DEBUG	if (debug) {		fprintf(ddt,"send_msg -> [%s] (%s %d %d) id=%d\n",			inet_ntoa(qp->q_from.sin_addr), 			qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",			qp->q_stream == QSTREAM_NULL ? qp->q_dfd						     : qp->q_stream->s_rfd,			ntohs(qp->q_from.sin_port),			ntohs(qp->q_id));	}	if (debug>4)		for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {		    fprintf(ddt, "qp %x q_id: %d  q_nsid: %d q_msglen: %d ",		    	tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen);	            fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr,			tqp->q_curaddr);	            fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next,		   	 qp->q_link);		}	if (debug >= 10)		fp_query(msg, ddt);#endif /* DEBUG */	if (qp->q_stream == QSTREAM_NULL) {		if (sendto(qp->q_dfd, msg, msglen, 0,		    (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) {			dprintf(1, (ddt, "sendto error errno= %d\n",errno));			return(1);		}		stats[S_OUTPKTS].cnt++;	} else {		(void) writemsg(qp->q_stream->s_rfd, (u_char*)msg, msglen);		sq_done(qp->q_stream);	}	return 0;}#ifdef notdef/* i don't quite understand this but the only ref to it is notdef'd --vix */prime(class, type, oqp)	int class, type;	register struct qinfo *oqp;{	char	dname[BUFSIZ];	if (oqp->q_msg == NULL)		return;	if (dn_expand((u_char *)oqp->q_msg,	    (u_char *)oqp->q_msg + oqp->q_msglen,	    (u_char *)oqp->q_msg + sizeof(HEADER), (u_char *)dname,	    sizeof(dname)) < 0)		return;	dprintf(2, (ddt, "prime: %s\n", dname));	(void) sysquery(dname, class, type, NULL, 0);}#endifvoidprime_cache(){	register struct qinfo *qp;	dprintf(1, (ddt, "prime_cache: priming = %d\n", priming));	stats[S_PRIMECACHE].cnt++;	if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {		priming++;		if ((qp = sysquery("", C_IN, T_NS, NULL, 0)) == NULL)			priming = 0;		else			qp->q_flags |= (Q_SYSTEM | Q_PRIMING);	}	needs_prime_cache = 0;	return;}struct qinfo *sysquery(dname, class, type, nss, nsc)	char *dname;	int class, type;	struct in_addr *nss;	int nsc;{	register struct qinfo *qp, *oqp;	register HEADER *hp;	struct namebuf *np;	struct databuf *nsp[NSMAX];	struct hashbuf *htp;	char *fname;	int count;#ifdef	DATUMREFCNT	nsp[0] = NULL;#endif	dprintf(3, (ddt, "sysquery(%s, %d, %d, 0x%x, %d)\n",		    dname, class, type, nss, nsc));	stats[S_SYSQUERIES].cnt++;	qp = qnew();	if (nss && nsc) {	} else {		htp = hashtab;		if (priming && dname[0] == '\0') {			np = NULL;		} else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {			dprintf(1, (ddt,				    "sysquery: nlookup error on %s?\n",				    dname));			qfree(qp);			return 0;		}		switch (findns(&np, class, nsp, &count, 0)) {		case NXDOMAIN:		case SERVFAIL:			dprintf(1, (ddt,				    "sysquery: findns error on %s?\n", dname));			qfree(qp);#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			return(0);		}	}	/* build new qinfo struct */	qp->q_cmsg = qp->q_msg = NULL;	qp->q_dfd = ds;	if (nss && nsc)		qp->q_fwd = NULL;	else		qp->q_fwd = fwdtab;	qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;	qp->q_flags |= Q_SYSTEM;	if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {		qfree(qp);#ifdef	DATUMREFCNT		free_nsp(nsp);#endif		return(0);	}	qp->q_msglen = res_mkquery(QUERY, dname, class,				   type, (char *)NULL, 0, NULL,				   qp->q_msg, BUFSIZ);	hp = (HEADER *) qp->q_msg;	hp->id = qp->q_nsid = htons((u_int16_t)++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		    ) {			dprintf(3, (ddt, "sysquery: duplicate\n"));			qfree(qp);#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			return(0);		}	}	if (nss && nsc) {		int i;		struct qserv *qs;		for (i = 0, qs = qp->q_addr;		     i < nsc;		     i++, qs++) {			qs->ns_addr.sin_family = AF_INET;			qs->ns_addr.sin_addr = nss[i];			qs->ns_addr.sin_port = ns_port;			qs->ns = NULL;			qs->nsdata = NULL;			qs->stime = tt;			qs->nretry = 0;		}		qp->q_naddr = nsc;	} else {	    if ((count = nslookup(nsp, qp, dname, "sysquery")) <= 0) {		if (count < 0) {			dprintf(1, (ddt,				    "sysquery: nslookup reports danger\n"));		} else {			dprintf(1, (ddt,				    "sysquery: no addrs found for NS's\n"));		}		qfree(qp);#ifdef	DATUMREFCNT		free_nsp(nsp);#endif		return(0);	    }	}	schedretry(qp, retrytime(qp));	if (qp->q_fwd == NULL)		qp->q_addr[0].stime = tt;	/* XXX - why not every? */	dprintf(1, (ddt,		    "sysquery: send -> [%s].%d dfd=%d, nsid=%d id=%d %dms\n",		    inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),		    ntohs(Q_NEXTADDR(qp,0)->sin_port), qp->q_dfd, 		    ntohs(qp->q_nsid), ntohs(qp->q_id),		    (qp->q_addr[0].nsdata != NULL)		    	? qp->q_addr[0].nsdata->d_nstime		    	: (-1)));#ifdef DEBUG	if (debug >= 10)		fp_query(qp->q_msg, ddt);#endif	if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,		   (struct sockaddr *)Q_NEXTADDR(qp,0),		   sizeof(struct sockaddr_in)) < 0) {		/* XXX - syslog or put in stats or something */		dprintf(1, (ddt, "sendto error (%s)\n", strerror(errno)));	}	stats[S_OUTPKTS].cnt++;#ifdef	DATUMREFCNT	free_nsp(nsp);#endif	return(qp);}

⌨️ 快捷键说明

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