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

📄 ns_forw.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#if !defined(lint) && !defined(SABER)static char sccsid[] = "@(#)ns_forw.c	4.32 (Berkeley) 3/3/91";static char rcsid[] = "$Id: ns_forw.c,v 4.9.1.8 1993/12/06 00:43:02 vixie Exp $";#endif /* not lint *//* * ++Copyright++ 1986 * - * Copyright (c) 1986 *    The Regents of the University of California.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: * 	This product includes software developed by the University of * 	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. *  * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. *  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */#include <sys/param.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <syslog.h>#include <resolv.h>#include <stdio.h>#include <errno.h>#include "named.h"/* * Forward the query to get the answer since its not in the database. * Returns FW_OK if a request struct is allocated and the query sent. * Returns FW_DUP if this is a duplicate of a pending request.  * Returns FW_NOSERVER if there were no addresses for the nameservers. * Returns FW_SERVFAIL on malloc error or if asked to do something * dangerous, such as fwd to ourselves or fwd to the host that asked us. * * (no action is taken on errors and qpp is not filled in.) */intns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, dname)	struct databuf *nsp[];	u_char *msg;	int msglen;	struct sockaddr_in *fp;	struct qstream *qsp;	int dfd;	struct qinfo **qpp;	char *dname;{	register struct qinfo *qp;	HEADER *hp;	u_int16_t id;	int n;	dprintf(3, (ddt, "ns_forw()\n"));	hp = (HEADER *) msg;	id = hp->id;	/* Look at them all */	for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {		if (qp->q_id == id &&		    bcmp((char *)&qp->q_from, fp, sizeof(qp->q_from)) == 0 &&		    ((qp->q_cmsglen == 0 && qp->q_msglen == msglen &&		     bcmp((char *)qp->q_msg+2, msg+2, msglen-2) == 0) ||		    (qp->q_cmsglen == msglen &&		     bcmp((char *)qp->q_cmsg+2, msg+2, msglen-2) == 0))) {			dprintf(3, (ddt,				    "forw: dropped DUP id=%d\n", ntohs(id)));			stats[S_DUPQUERIES].cnt++;			return (FW_DUP);		}	}	qp = qnew();	qp->q_from = *fp;	/* nslookup wants to know this */	if ((n = nslookup(nsp, qp, dname, "ns_forw")) < 0) {		dprintf(2, (ddt, "forw: nslookup reports danger\n"));		qfree(qp);		return (FW_SERVFAIL);	} else if (n == 0 && !(forward_only && fwdtab)) {		dprintf(2, (ddt, "forw: no nameservers found\n"));		qfree(qp);		return (FW_NOSERVER);	}	qp->q_stream = qsp;	qp->q_curaddr = 0;	qp->q_fwd = fwdtab;	qp->q_dfd = dfd;	qp->q_id = id;	qp->q_expire = tt.tv_sec + RETRY_TIMEOUT*2;	hp->id = qp->q_nsid = htons((u_int16_t)++nsid);	hp->ancount = 0;	hp->nscount = 0;	hp->arcount = 0;	if ((qp->q_msg = malloc((unsigned)msglen)) == NULL) {		syslog(LOG_ERR, "forw: %m");		qfree(qp);		return (FW_SERVFAIL);	}	bcopy(msg, qp->q_msg, qp->q_msglen = msglen);	if (!qp->q_fwd) {		hp->rd = 0;		qp->q_addr[0].stime = tt;	}#ifdef SLAVE_FORWARD	if (forward_only)		schedretry(qp, (time_t)slave_retry);	else#endif /* SLAVE_FORWARD */	schedretry(qp, qp->q_fwd ?(2*RETRYBASE) :retrytime(qp));	dprintf(1, (ddt,		"forw: forw -> [%s].%d ds=%d nsid=%d id=%d %dms retry %dsec\n",			inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),			ntohs(Q_NEXTADDR(qp,0)->sin_port), ds,			ntohs(qp->q_nsid), ntohs(qp->q_id),			(qp->q_addr[0].nsdata != NULL)				? qp->q_addr[0].nsdata->d_nstime				: -1,			qp->q_time - tt.tv_sec));#ifdef DEBUG	if (debug >= 10)		fp_query((char *)msg, ddt);#endif	if (sendto(ds, msg, msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,0),		   sizeof(struct sockaddr_in)) < 0) {			dprintf(5, (ddt,				    "error returning msg errno=%d\n", errno));	}	stats[S_OUTPKTS].cnt++;	if (qpp)		*qpp = qp;	hp->rd = 1;	return (0);}/* struct qdatagram * * aIsUs(addr) *	scan the datagramq (our list of interface addresses) for "addr" * returns: *	pointer to qdatagram entry or NULL if no match is found * notes: *	INADDR_ANY ([0.0.0.0]) is on the datagramq, so it's considered "us" * author: *	Paul Vixie (DECWRL) April 1991 */struct qdatagram *aIsUs(addr)	struct in_addr addr;{	struct qdatagram *dqp;	for (dqp = datagramq;  dqp != QDATAGRAM_NULL;  dqp = dqp->dq_next) {		if (addr.s_addr == dqp->dq_addr.s_addr) {			return dqp;		}	}	return NULL;}/* haveComplained(tag1, tag2) *	check to see if we have complained about (tag1,tag2) recently *	(note that these are declared as pointers but are never deref'd) * returns: *	boolean: have we complained recently? * side-effects: *	outdated complaint records removed from our static list * author: *	Paul Vixie (DECWRL) April 1991 */inthaveComplained(tag1, tag2)	char *tag1, *tag2;{	struct complaint {		char *tag1, *tag2;		time_t expire;		struct complaint *next;	};	static struct complaint *List = NULL;	struct complaint *cur, *next, *prev;	int r = 0;	for (cur = List, prev = NULL;  cur;  prev = cur, cur = next) {		next = cur->next;		if (tt.tv_sec > cur->expire) {			if (prev)				prev->next = next;			else				List = next;			free((char*) cur);			cur = prev;		} else if ((tag1 == cur->tag1) && (tag2 == cur->tag2)) {			r++;		}	}	if (!r) {		cur = (struct complaint *)malloc(sizeof(struct complaint));		cur->tag1 = tag1;		cur->tag2 = tag2;		cur->expire = tt.tv_sec + INIT_REFRESH;	/* "10 minutes" */		cur->next = NULL;		if (prev)			prev->next = cur;		else			List = cur;	}	return r;}/* void * nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr) *	Issue a complaint about a dangerous situation found by nslookup(). * params: *	sysloginfo is a string identifying the complainant. *	queryname is the domain name associated with the problem. *	complaint is a string describing what is wrong. *	dname and a_rr are the problematic other name server. */voidnslookupComplain(sysloginfo, queryname, complaint, dname, a_rr)	char *sysloginfo, *queryname, *complaint, *dname;	register struct databuf *a_rr;{	dprintf(2, (ddt, "NS '%s' %s\n", dname, complaint));	if (sysloginfo && queryname && !haveComplained(queryname, complaint))	{		char buf[512];		/* syslog only takes 5 params */		sprintf(buf, "%s: query(%s) %s (%s:%s)",			sysloginfo, queryname,			complaint, dname, inet_ntoa(			    *(struct in_addr*)a_rr->d_data			));		syslog(LOG_INFO, buf);	}}/* * nslookup(nsp, qp, syslogdname, sysloginfo) *	Lookup the address for each nameserver in `nsp' and add it to * 	the list saved in the qinfo structure pointed to by `qp'. *	Omits information about nameservers that we shouldn't ask. *	Detects the following dangerous operations: *		One of the A records for one of the nameservers in nsp *		refers to the address of one of our own interfaces; *		One of the A records refers to the nameserver port on *		the host that asked us this question. * returns: the number of addresses added, or -1 if a dangerous operation *	is detected. * side effects: *	if a dangerous situation is detected and (syslogdname && sysloginfo), *	calls syslog. */intnslookup(nsp, qp, syslogdname, sysloginfo)	struct databuf *nsp[];	register struct qinfo *qp;	char *syslogdname;	char *sysloginfo;{	register struct namebuf *np;	register struct databuf *dp, *nsdp;	register struct qserv *qs;	register int n, i;	struct hashbuf *tmphtp;	char *dname, *fname;	int oldn, naddr, class, found_arr;	time_t curtime;	int qcomp();	dprintf(3, (ddt, "nslookup(nsp=0x%x, qp=0x%x, \"%s\")\n",		    nsp, qp, syslogdname));	naddr = n = qp->q_naddr;	curtime = (u_long) tt.tv_sec;	while ((nsdp = *nsp++) != NULL) {		class = nsdp->d_class;		dname = (char *)nsdp->d_data;		dprintf(3, (ddt, "nslookup: NS \"%s\" c=%d t=%d (0x%x)\n",			    dname, class, nsdp->d_type, nsdp->d_flags));		/* don't put in people we have tried */		for (i = 0; i < qp->q_nusedns; i++) {			if (qp->q_usedns[i] == nsdp) {				dprintf(2, (ddt,					    "skipping used NS w/name %s\n",					    nsdp->d_data));				goto skipserver;			}		}		tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);		np = nlookup(dname, &tmphtp, &fname, 1);		if (np == NULL || fname != dname) {			dprintf(3, (ddt, "%s: not found %s %x\n",				    dname, fname, np));			continue;		}		found_arr = 0;		oldn = n;		/* look for name server addresses */		for (dp = np->n_data;  dp != NULL;  dp = dp->d_next) {			if (dp->d_type == T_CNAME && dp->d_class == class)				goto skipserver;			if (dp->d_type != T_A || dp->d_class != class)				continue;#ifdef NCACHE			if (dp->d_rcode)				continue;#endif			/*			 * 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 < (curtime+900)) &&			    !(dp->d_flags & DB_F_HINT) )		        {				dprintf(3, (ddt,					    "nslookup: stale entry '%s'\n",					    np->n_dname));				/* Cache invalidate the NS RR's */				if (dp->d_ttl < curtime)					delete_all(np, class, T_A);				n = oldn;				break;			}#ifdef VALIDATE			/* anant@isi.edu validation procedure, maintains a			 * table of server names-addresses used recently			 */			store_name_addr(dname, (struct in_addr *)dp->d_data,					syslogdname, sysloginfo);#endif /*VALIDATE*/			found_arr++;			/* don't put in duplicates */			qs = qp->q_addr;			for (i = 0; i < n; i++, qs++)				if (qs->ns_addr.sin_addr.s_addr ==				    ((struct in_addr *)dp->d_data)->s_addr)					goto skipaddr;			qs->ns_addr.sin_family = AF_INET;			qs->ns_addr.sin_port = ns_port;			qs->ns_addr.sin_addr = *(struct in_addr *)dp->d_data;			qs->ns = nsdp;			qs->nsdata = dp;			qp->q_addr[n].nretry = 0;	/* XXX - why not qs? */			/*			 * if we are being asked to fwd a query whose			 * nameserver list includes our own name/address(es),			 * then we have detected a lame delegation and rather			 * than melt down the network and hose down the other			 * servers (who will hose us in return), we'll return			 * -1 here which will cause SERVFAIL to be sent to			 * the client's resolver which will hopefully then			 * shut up.			 *			 * (originally done in nsContainsUs by vix@dec mar92;			 * moved into nslookup by apb@und jan1993)			 */			if (aIsUs(*(struct in_addr *)dp->d_data)) {			    static char *complaint = "contains our address";			    nslookupComplain(sysloginfo, syslogdname,					complaint, dname, dp);			    return -1;			}			/*			 * If we want to forward to a host that asked us			 * this question then either we or they are sick			 * (unless they asked from some port other than			 * their nameserver port).  (apb@und jan1993)			 */			if (bcmp((char *)&qp->q_from, &qs->ns_addr,			    sizeof(qp->q_from)) == 0)			{			    static char *complaint = "forwarding loop";			    nslookupComplain(sysloginfo, syslogdname,					complaint, dname, dp);			    return -1;			}			n++;			if (n >= NSMAX)				goto out;	skipaddr:	;		}		dprintf(8, (ddt, "nslookup: %d ns addrs\n", n));		if (found_arr == 0 && !(qp->q_flags & Q_SYSTEM))			(void) sysquery(dname, class, T_A, NULL, 0);

⌨️ 快捷键说明

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