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 + -
显示快捷键?