ns_forw.c

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

C
864
字号
#ifndef lintstatic	char	*sccsid = "@(#)ns_forw.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1984-1988 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Copyright (c) 1986 Regents of the University of California *	All Rights Reserved * static char sccsid[] = "@(#)ns_forw.c	4.26 (Berkeley) 3/28/88"; *//* * Modification History: * * 18-Jan-88	logcher *	Added BIND 4.7.2. * * 26-Jan-88	logcher *	Added BIND 4.7.3. * * 08-Mar-88	logcher *	Added a & to the bcmp with a sockaddr in ns_forw per bug fix *	from bind-test mailing list dated, 19-Feb-88 * * 17-May-89	logcher *	Added BIND 4.8. */#include <stdio.h>#include <sys/param.h>#include <sys/time.h>#ifdef ULTRIXFUNC#include <sys/stat.h>#endif ULTRIXFUNC#include <sys/socket.h>#include <netinet/in.h>#include <syslog.h>#include <arpa/nameser.h>#include "ns.h"#include "db.h"struct	qinfo *qhead = QINFO_NULL;	/* head of allocated queries */struct	qinfo *retryqp = QINFO_NULL;	/* list of queries to retry */struct	fwdinfo *fwdtab;		/* list of forwarding hosts */int	nsid;				/* next forwarded query id */extern int forward_only;		/* you are only a slave */extern int errno;extern short ns_port;#ifdef AUTHENextern char *res_dotname_head();#endif AUTHENtime_t	retrytime();#ifdef ULTRIXFUNCstruct fwdinfo *fwd_copy(fwd_src)  struct fwdinfo *fwd_src;{	struct fwdinfo *fwd_dest = NULL;	struct fwdinfo *src_ptr;	struct fwdinfo *dest_ptr;	struct fwdinfo *temp_ptr;	for(src_ptr = fwd_src; src_ptr != NULL; src_ptr = src_ptr->next)	{				if((temp_ptr = (struct fwdinfo *)		    malloc(sizeof(struct fwdinfo))) == NULL)			return(NULL);		if(fwd_dest == NULL) {			fwd_dest = dest_ptr = temp_ptr;		} else {			dest_ptr->next = temp_ptr;			dest_ptr = temp_ptr;					}		*dest_ptr = *src_ptr;		dest_ptr->next = NULL;	}	return(fwd_dest);}#endif ULTRIXFUNC/* * 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. * (no action is taken on errors and qpp is not filled in.) */#ifdef AUTHENns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp, query_in, query_out, authentype_in, authenver_in, authentype_out, authenver_out, ns_ad, query_dname, query_type, query_class)	struct databuf *nsp[];	char *msg;	int msglen;	struct sockaddr_in *fp;	struct qstream *qsp;	int dfd;	struct qinfo **qpp;	int query_in;	int query_out;	int authentype_in;	int authenver_in;	int authentype_out;	int authenver_out;	AUTH_DAT ns_ad;	char *query_dname;	int query_type;	int query_class;{#else AUTHENns_forw(nsp, msg, msglen, fp, qsp, dfd, qpp)	struct databuf *nsp[];	char *msg;	int msglen;	struct sockaddr_in *fp;	struct qstream *qsp;	int dfd;	struct qinfo **qpp;{#endif AUTHEN	register struct qinfo *qp;	HEADER *hp;	u_short id;	extern char *calloc();#ifdef AUTHEN	char *krbnameptr;	char *dnameptr;	int authen_len;#endif AUTHEN#ifdef DEBUG	if (debug >= 3)		fprintf(ddt,"ns_forw()\n");#endif	/* Don't forward if we're already working on it. */	hp = (HEADER *) msg;	id = hp->id;	hp->rd = 0;	/* 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)) {#ifdef DEBUG			if (debug >= 3)				fprintf(ddt,"forw: dropped DUP id=%d\n", ntohs(id));#endif#ifdef STATS			stats[S_DUPQUERIES].cnt++;#endif			return (FW_DUP);		}	}	qp = qnew();#ifdef ULTRIXFUNC	if (nslookup(nsp, qp) == 0 && !(forward_only && fwdtab)) {#else ULTRIXFUNC	if (nslookup(nsp, qp) == 0) {#endif ULTRIXFUNC#ifdef DEBUG		if (debug >= 2)			fprintf(ddt,"forw: no nameservers found\n");#endif		qfree(qp);		hp->rd = 1;		return (FW_NOSERVER);	}	qp->q_stream = qsp;	qp->q_curaddr = 0;#ifdef ULTRIXFUNC	qp->q_fwd = fwd_copy(fwdtab);	qp->q_fwdorig = qp->q_fwd;#else ULTRIXFUNC	qp->q_fwd = fwdtab;#endif ULTRIXFUNC	qp->q_dfd = dfd;	qp->q_id = id;#ifdef AUTHEN	qp->q_ad = ns_ad;	qp->q_type_in = query_in;	qp->q_type_out = query_out;	qp->q_authentype_in =  authentype_in;	qp->q_authenver_in = authenver_in;	qp->q_authentype_out = authentype_out;	qp->q_authenver_out = authenver_out;	strcpy(qp->q_dname, query_dname);	qp->q_type = query_type;	qp->q_class = query_class;	strcpy(qp->q_dname_curr, query_dname);	qp->q_type_curr = query_type;	qp->q_class_curr = query_class;#endif AUTHEN	hp->id = qp->q_nsid = htons((u_short)++nsid);	hp->ancount = 0;	hp->nscount = 0;	hp->arcount = 0;	if (qp->q_fwd)		hp->rd = 1;	else		qp->q_addr[0].stime = tt;	qp->q_from = *fp;#ifdef AUTHEN	if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {		syslog(LOG_ERR, "forw: %m");		qfree(qp);		return (FW_SERVFAIL);	}#else AUTHEN	if ((qp->q_msg = malloc((unsigned)msglen)) == NULL) {		syslog(LOG_ERR, "forw: %m");		qfree(qp);		return (FW_SERVFAIL);	}#endif AUTHEN	bcopy(msg, qp->q_msg, qp->q_msglen = msglen);#ifdef AUTHEN	if((hp->opcode == AQUERY && authentype_out == AUTH_KRB &&		       authenver_out == ONE)) {		krbnameptr = res_dotname_head(Q_NEXTNAME(qp, 0));		dnameptr = query_dname;		if (query_type != T_SOA && query_type != T_AXFR)			res_dotname_rmhead(&dnameptr);		hp->arcount = htons(1);		if((authen_len = res_mkl_krbcred(ONE,						 "named",						 krbnameptr,						 Q_NEXTCRED(qp,0),						 msg,						 msg + msglen,						 BUFSIZ - msglen,						 dnameptr, query_type,						 query_class)) < RET_OK) {			free(krbnameptr);			qfree(qp);			return(FW_SERVFAIL);		}		free(krbnameptr);		msglen += authen_len;	}#endif AUTHEN#ifdef ULTRIXFUNC	schedretry(qp, qp->q_fwd ? (2*RETRYBASE): retrytime(qp) );#else ULTRIXFUNC	schedretry(qp, retrytime(qp));#endif ULTRIXFUNC#ifdef DEBUG	if (debug)#ifdef ULTRIXFUNC		fprintf(ddt,		   "forw: forw -> %s %d (%d) nsid=%d id=%d %dms retry %d sec\n",			inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),			ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),			ntohs(qp->q_nsid), ntohs(qp->q_id),			((qp->q_addr[0].nsdata) ? qp->q_addr[0].nsdata->d_nstime: -1),			qp->q_time - tt.tv_sec);#else ULTRIXFUNC		fprintf(ddt,		   "forw: forw -> %s %d (%d) nsid=%d id=%d %dms retry %d sec\n",			inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),			ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),			ntohs(qp->q_nsid), ntohs(qp->q_id),			qp->q_addr[0].nsdata->d_nstime,			qp->q_time - tt.tv_sec);#endif ULTRIXFUNC	if ( debug >= 10)		fp_query(msg, ddt);#endif	if (sendto(ds, msg, msglen, 0, (struct sockaddr *)Q_NEXTADDR(qp,0),		   sizeof(struct sockaddr_in)) < 0){#ifdef DEBUG	if (debug >= 5)			fprintf(ddt,"error returning msg errno=%d\n",errno);#endif	}#ifdef STATS	stats[S_OUTPKTS].cnt++;#endif	if (qpp)		*qpp = qp;	hp->rd = 0;	return (0);}/* * Lookup the address for each nameserver in `nsp' and add it to * the list saved in the qinfo structure. */nslookup(nsp, qp)	struct databuf *nsp[];	register struct qinfo *qp;{	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();#ifdef DEBUG	if (debug >= 3)		fprintf(ddt,"nslookup(nsp=x%x,qp=x%x)\n",nsp,qp);#endif	naddr = n = qp->q_naddr;	curtime = (u_long) tt.tv_sec;	while ((nsdp = *nsp++) != NULL) {		class = nsdp->d_class;		dname = nsdp->d_data;#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"nslookup: NS %s c%d t%d (x%x)\n",				dname, class, nsdp->d_type, nsdp->d_flags);#endif		/* don't put in people we have tried */		for (i = 0; i < qp->q_nusedns; i++)			if (qp->q_usedns[i] == nsdp) {#ifdef DEBUG				if (debug >= 2)fprintf(ddt, "skipping used NS w/name %s\n", nsdp->d_data);#endif DEBUG				goto skipserver;			}		tmphtp = ((nsdp->d_flags & DB_F_HINT) ? fcachetab : hashtab);		np = nlookup(dname, &tmphtp, &fname, 1);		if (np == NULL || fname != dname) {#ifdef DEBUG			if (debug >= 3)			    fprintf(ddt,"%s: not found %s %x\n",dname,fname,np);#endif			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_A || dp->d_class != class)				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 < (curtime+900)) &&			    !(dp->d_flags & DB_F_HINT) )		        {#ifdef DEBUG				if (debug >= 3)					fprintf(ddt,"nslookup: stale entry '%s'\n",					    np->n_dname);#endif				/* Cache invalidate the NS RR's */				if (dp->d_ttl < curtime)					delete_all(np, class, T_A);				n = oldn;				break;			}			found_arr++;			/* don't put in duplicates */			qs = qp->q_addr;			for (i = 0; i < n; i++, qs++)				if (bcmp((char *)&qs->ns_addr.sin_addr,				    dp->d_data, sizeof(struct in_addr)) == 0)					goto skipaddr;			qs->ns_addr.sin_family = AF_INET;			qs->ns_addr.sin_port = (u_short)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;#ifdef AUTHEN			strcpy(qp->q_addr[n].ns_name,dname);			qp->authen_msglen = 0;#endif AUTHEN			n++;			if (n >= NSMAX)				goto out;	skipaddr:	;		}#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"nslookup: %d ns addrs\n", n);#endif

⌨️ 快捷键说明

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