summaryrefslogtreecommitdiff
path: root/usr.sbin/named/ns_forw.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/named/ns_forw.c')
-rw-r--r--usr.sbin/named/ns_forw.c579
1 files changed, 0 insertions, 579 deletions
diff --git a/usr.sbin/named/ns_forw.c b/usr.sbin/named/ns_forw.c
deleted file mode 100644
index 9f2e8202050..00000000000
--- a/usr.sbin/named/ns_forw.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*-
- * 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.
- */
-
-#ifndef lint
-/*static char sccsid[] = "from: @(#)ns_forw.c 4.32 (Berkeley) 3/3/91";*/
-static char rcsid[] = "$Id: ns_forw.c,v 1.1 1995/10/18 08:47:50 deraadt Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <syslog.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <stdio.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 u_short ns_port;
-
-time_t retrytime();
-
-/*
- * 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.)
- */
-ns_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;
-{
- register struct qinfo *qp;
- HEADER *hp;
- u_short id;
- extern char *calloc();
-
-#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;
- /* 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();
- if (nslookup(nsp, qp) == 0) {
-#ifdef DEBUG
- if (debug >= 2)
- fprintf(ddt,"forw: no nameservers found\n");
-#endif
- 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;
- hp->id = qp->q_nsid = htons((u_short)++nsid);
- hp->ancount = 0;
- hp->nscount = 0;
- hp->arcount = 0;
- qp->q_from = *fp;
- 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;
- }
-
- schedretry(qp, retrytime(qp));
-#ifdef DEBUG
- if (debug)
- 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);
- 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 = 1;
- 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 = 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;
- n++;
- if (n >= NSMAX)
- goto out;
- skipaddr: ;
- }
-#ifdef DEBUG
- if (debug >= 3)
- fprintf(ddt,"nslookup: %d ns addrs\n", n);
-#endif
- if (found_arr == 0 && qp->q_system == 0)
- (void) sysquery(dname, class, T_A);
-skipserver: ;
- }
-out:
-#ifdef DEBUG
- if (debug >= 3)
- fprintf(ddt,"nslookup: %d ns addrs total\n", n);
-#endif
- qp->q_naddr = n;
- if (n > 1)
- qsort((char *)qp->q_addr, n, sizeof(struct qserv), qcomp);
- return (n - naddr);
-}
-
-qcomp(qs1, qs2)
- struct qserv *qs1, *qs2;
-{
-
- return (qs1->nsdata->d_nstime - qs2->nsdata->d_nstime);
-}
-
-/*
- * Arrange that forwarded query (qp) is retried after t seconds.
- */
-schedretry(qp, t)
- struct qinfo *qp;
- time_t t;
-{
- register struct qinfo *qp1, *qp2;
-
-#ifdef DEBUG
- if (debug > 3) {
- fprintf(ddt,"schedretry(%#x, %dsec)\n", qp, t);
- if (qp->q_time)
- fprintf(ddt,"WARNING: schedretry(%x,%d) q_time already %d\n", qp->q_time);
- }
-#endif
- t += (u_long) tt.tv_sec;
- qp->q_time = t;
-
- if ((qp1 = retryqp) == NULL) {
- retryqp = qp;
- qp->q_next = NULL;
- return;
- }
- if (t < qp1->q_time) {
- qp->q_next = qp1;
- retryqp = qp;
- return;
- }
- while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t)
- qp1 = qp2;
- qp1->q_next = qp;
- qp->q_next = qp2;
-}
-
-/*
- * Unsched is called to remove a forwarded query entry.
- */
-unsched(qp)
- struct qinfo *qp;
-{
- register struct qinfo *np;
-
-#ifdef DEBUG
- if (debug > 3) {
- fprintf(ddt,"unsched(%#x, %d )\n", qp, ntohs(qp->q_id));
- }
-#endif
- if( retryqp == qp ) {
- retryqp = qp->q_next;
- } else {
- for( np=retryqp; np->q_next != QINFO_NULL; np = np->q_next ) {
- if( np->q_next != qp)
- continue;
- np->q_next = qp->q_next; /* dequeue */
- break;
- }
- }
- qp->q_next = QINFO_NULL; /* sanity check */
- qp->q_time = 0;
-}
-
-/*
- * Retry is called to retransmit query 'qp'.
- */
-retry(qp)
- register struct qinfo *qp;
-{
- register int n;
- register HEADER *hp;
-
-#ifdef DEBUG
- if (debug > 3)
- fprintf(ddt,"retry(x%x) id=%d\n", qp, ntohs(qp->q_id));
-#endif
- if((HEADER *)qp->q_msg == NULL) { /*** XXX ***/
- qremove(qp);
- return;
- } /*** XXX ***/
-
- /* try next address */
- n = qp->q_curaddr;
- if (qp->q_fwd) {
- qp->q_fwd = qp->q_fwd->next;
- if (qp->q_fwd)
- goto found;
- /* out of forwarders, try direct queries */
- } else
- ++qp->q_addr[n].nretry;
- if (!forward_only) {
- do {
- if (++n >= qp->q_naddr)
- n = 0;
- if (qp->q_addr[n].nretry < MAXRETRY)
- goto found;
- } while (n != qp->q_curaddr);
- }
- /*
- * Give up. Can't reach destination.
- */
- hp = (HEADER *)(qp->q_cmsg ? qp->q_cmsg : qp->q_msg);
- if (qp->q_system == PRIMING_CACHE) {
- /* Can't give up priming */
- unsched(qp);
- schedretry(qp, (time_t)60*60); /* 1 hour */
- hp->rcode = NOERROR; /* Lets be safe, reset the query */
- hp->qr = hp->aa = 0;
- qp->q_fwd = fwdtab;
- for (n = 0; n < qp->q_naddr; n++)
- qp->q_addr[n].nretry = 0;
- return;
- }
-#ifdef DEBUG
- if (debug >= 5)
- fprintf(ddt,"give up\n");
-#endif
- n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
- hp->id = qp->q_id;
- hp->qr = 1;
- hp->ra = 1;
- hp->rd = 1;
- hp->rcode = SERVFAIL;
-#ifdef DEBUG
- if (debug >= 10)
- fp_query(qp->q_msg, ddt);
-#endif
- if (send_msg((char *)hp, n, qp)) {
-#ifdef DEBUG
- if (debug)
- fprintf(ddt,"gave up retry(x%x) nsid=%d id=%d\n",
- qp, ntohs(qp->q_nsid), ntohs(qp->q_id));
-#endif
- }
- qremove(qp);
- return;
-
-found:
- if (qp->q_fwd == 0 && qp->q_addr[n].nretry == 0)
- qp->q_addr[n].stime = tt;
- qp->q_curaddr = n;
- hp = (HEADER *)qp->q_msg;
- hp->rd = (qp->q_fwd ? 1 : 0);
-#ifdef DEBUG
- if (debug)
- fprintf(ddt,"%s(addr=%d n=%d) -> %s %d (%d) nsid=%d id=%d %dms\n",
- (qp->q_fwd ? "reforw" : "resend"),
- n, qp->q_addr[n].nretry,
- inet_ntoa(Q_NEXTADDR(qp,n)->sin_addr),
- ds, ntohs(Q_NEXTADDR(qp,n)->sin_port),
- ntohs(qp->q_nsid), ntohs(qp->q_id),
- qp->q_addr[n].nsdata->d_nstime);
- if ( debug >= 10)
- fp_query(qp->q_msg, ddt);
-#endif
- /* NOSTRICT */
- if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
- (struct sockaddr *)Q_NEXTADDR(qp,n),
- sizeof(struct sockaddr_in)) < 0){
-#ifdef DEBUG
- if (debug > 3)
- fprintf(ddt,"error resending msg errno=%d\n",errno);
-#endif
- }
- hp->rd = 1; /* leave set to 1 for dup detection */
-#ifdef STATS
- stats[S_OUTPKTS].cnt++;
-#endif
- unsched(qp);
- schedretry(qp, qp->q_fwd ? (2*RETRYBASE) : retrytime(qp));
-}
-
-/*
- * Compute retry time for the next server for a query.
- * Use a minimum time of RETRYBASE (4 sec.) or twice the estimated
- * service time; * back off exponentially on retries, but place a 45-sec.
- * ceiling on retry times for now. (This is because we don't hold a reference
- * on servers or their addresses, and we have to finish before they time out.)
- */
-time_t
-retrytime(qp)
-register struct qinfo *qp;
-{
- time_t t;
- struct qserv *ns = &qp->q_addr[qp->q_curaddr];
-
-#ifdef DEBUG
- if (debug > 3)
- fprintf(ddt,"retrytime: nstime %dms.\n",
- ns->nsdata->d_nstime / 1000);
-#endif
- t = (time_t) MAX(RETRYBASE, 2 * ns->nsdata->d_nstime / 1000);
- t <<= ns->nretry;
- t = MIN(t, 45); /* max. retry timeout for now */
-#ifdef notdef
- if (qp->q_system)
- return ((2 * t) + 5); /* system queries can wait. */
-#endif
- return (t);
-}
-
-qflush()
-{
- while (qhead)
- qremove(qhead);
- qhead = QINFO_NULL;
-}
-
-qremove(qp)
-register struct qinfo *qp;
-{
-#ifdef DEBUG
- if(debug > 3)
- fprintf(ddt,"qremove(x%x)\n", qp);
-#endif
- unsched(qp); /* get off queue first */
- qfree(qp);
-}
-
-struct qinfo *
-qfindid(id)
-register u_short id;
-{
- register struct qinfo *qp;
-
-#ifdef DEBUG
- if(debug > 3)
- fprintf(ddt,"qfindid(%d)\n", ntohs(id));
-#endif
- for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
- if (qp->q_nsid == id)
- return(qp);
- }
-#ifdef DEBUG
- if (debug >= 5)
- fprintf(ddt,"qp not found\n");
-#endif
- return(NULL);
-}
-
-struct qinfo *
-qnew()
-{
- register struct qinfo *qp;
-
- if ((qp = (struct qinfo *)calloc(1, sizeof(struct qinfo))) == NULL) {
-#ifdef DEBUG
- if (debug >= 5)
- fprintf(ddt,"qnew: calloc error\n");
-#endif
- syslog(LOG_ERR, "forw: %m");
- exit(12);
- }
-#ifdef DEBUG
- if (debug >= 5)
- fprintf(ddt,"qnew(x%x)\n", qp);
-#endif
- qp->q_link = qhead;
- qhead = qp;
- return( qp );
-}
-
-qfree(qp)
-struct qinfo *qp;
-{
- register struct qinfo *np;
-
-#ifdef DEBUG
- if(debug > 3)
- fprintf(ddt,"qfree( x%x )\n", qp);
- if(debug && qp->q_next)
- fprintf(ddt,"WARNING: qfree of linked ptr x%x\n", qp);
-#endif
- if (qp->q_msg)
- free(qp->q_msg);
- if (qp->q_cmsg)
- free(qp->q_cmsg);
- if( qhead == qp ) {
- qhead = qp->q_link;
- } else {
- for( np=qhead; np->q_link != QINFO_NULL; np = np->q_link ) {
- if( np->q_link != qp ) continue;
- np->q_link = qp->q_link; /* dequeue */
- break;
- }
- }
- (void)free((char *)qp);
-}