summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named/ns_forw.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/ns_forw.c')
-rw-r--r--contrib/bind/bin/named/ns_forw.c188
1 files changed, 107 insertions, 81 deletions
diff --git a/contrib/bind/bin/named/ns_forw.c b/contrib/bind/bin/named/ns_forw.c
index dac6525..f62ba20 100644
--- a/contrib/bind/bin/named/ns_forw.c
+++ b/contrib/bind/bin/named/ns_forw.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static const char sccsid[] = "@(#)ns_forw.c 4.32 (Berkeley) 3/3/91";
-static const char rcsid[] = "$Id: ns_forw.c,v 8.78 2000/12/23 08:14:37 vixie Exp $";
+static const char rcsid[] = "$Id: ns_forw.c,v 8.89 2002/01/29 03:59:36 marka Exp $";
#endif /* not lint */
/*
@@ -133,10 +133,10 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
HEADER *hp;
u_int16_t id;
int sendto_errno = 0;
- int n, has_tsig, oldqlen;
- u_char *oldqbuf;
- u_char *smsg;
- int smsglen, smsgsize, siglen;
+ int n, has_tsig, oldqlen = 0;
+ u_char *oldqbuf = NULL;
+ u_char *smsg = NULL;
+ int smsglen, smsgsize = 0, siglen;
u_char sig[TSIG_SIG_SIZE];
DST_KEY *key;
@@ -225,39 +225,50 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
if (debug >= 10)
res_pquery(&res, msg, msglen, log_get_stream(packet_channel));
#endif
- key = tsig_key_from_addr(nsa->sin_addr);
- if (key != NULL) {
- smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ key = qp->q_keys[0];
+ if (key == NULL)
+ key = qp->q_keys[0] = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL || !qp->q_addr[0].noedns) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11;
smsg = memget(smsgsize);
if (smsg == NULL)
ns_panic(ns_log_default, 1, "ns_forw: memget failed");
smsglen = qp->q_msglen;
siglen = sizeof(sig);
memcpy(smsg, qp->q_msg, qp->q_msglen);
+ }
+
+ if (!qp->q_addr[0].noedns)
+ smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0,
+ EDNS_MESSAGE_SZ, 0, NULL, 0);
+
+ if (key != NULL) {
n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
sig, &siglen, 0);
if (n == 0) {
- oldqbuf = qp->q_msg;
- oldqlen = qp->q_msglen;
- qp->q_msglen = smsglen;
- qp->q_msg = smsg;
- hp = (HEADER *) qp->q_msg;
has_tsig = 1;
+ free_tsig(qp->q_nstsig);
qp->q_nstsig = new_tsig(key, sig, siglen);
- }
- else {
+ } else {
has_tsig = 0;
free_tsig(qp->q_nstsig);
qp->q_nstsig = NULL;
INSIST(0);
}
- }
- else {
+ } else {
has_tsig = 0;
free_tsig(qp->q_nstsig);
qp->q_nstsig = NULL;
}
+ if (smsg != NULL) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ hp = (HEADER *) qp->q_msg;
+ }
+
if (qp->q_flags & Q_USEVC) {
if (tcp_send(qp) != NOERROR) {
if (!haveComplained(ina_ulong(nsa->sin_addr),
@@ -269,15 +280,16 @@ ns_forw(struct databuf *nsp[], u_char *msg, int msglen,
} else if (sendto(ds, (char *)qp->q_msg, qp->q_msglen, 0,
(struct sockaddr *)nsa,
sizeof(struct sockaddr_in)) < 0) {
- sendto_errno = errno;
+ sendto_errno = errno;
if (!haveComplained(ina_ulong(nsa->sin_addr),
(u_long)sendtoStr))
ns_info(ns_log_default, "ns_forw: sendto(%s): %s",
sin_ntoa(*nsa), strerror(errno));
nameserIncr(nsa->sin_addr, nssSendtoErr);
}
- if (has_tsig == 1) {
- memput(qp->q_msg, smsgsize);
+
+ if (smsgsize != 0) {
+ memput(smsg, smsgsize);
qp->q_msg = oldqbuf;
qp->q_msglen = oldqlen;
hp = (HEADER *) qp->q_msg;
@@ -456,8 +468,8 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
int oldn, naddr, class, found_arr, potential_ns, lame_ns;
time_t curtime;
- ns_debug(ns_log_default, 3, "nslookup(nsp=%#x, qp=%#x, \"%s\")",
- nsp, qp, syslogdname);
+ ns_debug(ns_log_default, 3, "nslookup(nsp=%p, qp=%p, \"%s\", d=%d)",
+ nsp, qp, syslogdname, qp->q_distance);
lame_ns = potential_ns = 0;
naddr = n = qp->q_naddr;
@@ -494,7 +506,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
tmphtp = ((nsdp->d_flags & DB_F_HINT) ?fcachetab :hashtab);
np = nlookup(dname, &tmphtp, &fname, 0);
if (np == NULL) {
- ns_debug(ns_log_default, 3, "%s: not found %s %#x",
+ ns_debug(ns_log_default, 3, "%s: not found %s %p",
dname, fname, np);
found_arr = 0;
goto need_sysquery;
@@ -520,6 +532,8 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
complaint, dname, dp, nsdp);
goto skipserver;
}
+ if (dp->d_rcode == NXDOMAIN && dp->d_class == class)
+ goto skipserver;
if (dp->d_type != T_A || dp->d_class != class)
continue;
if (dp->d_rcode) {
@@ -587,9 +601,11 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
qs->ns_addr.sin_family = AF_INET;
qs->ns_addr.sin_port = ns_port;
qs->ns_addr.sin_addr = nsa;
+ qp->q_keys[n] = NULL;
qs->ns = nsdp;
qs->nsdata = dp;
qs->forwarder = 0;
+ qs->noedns = dp->d_noedns;
qs->nretry = 0;
/*
* If this A RR has no RTT, initialize its RTT to a
@@ -615,7 +631,8 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
* gdonl mar96
*/
if (aIsUs(nsa)) {
- static char *complaint = "contains our address";
+ static const char *complaint =
+ "contains our address";
nslookupComplain(sysloginfo, syslogdname,
complaint, dname, dp, nsdp);
continue;
@@ -632,7 +649,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
if (memcmp(&qp->q_from, &qs->ns_addr,
sizeof(qp->q_from)) == 0)
{
- static char *complaint = "forwarding loop";
+ static const char *complaint = "forwarding loop";
nslookupComplain(sysloginfo, syslogdname,
complaint, dname, dp, nsdp);
continue;
@@ -668,9 +685,10 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
need_sysquery:
if (found_arr == 0) {
potential_ns++;
- if (!(qp->q_flags & Q_SYSTEM))
- (void) sysquery(dname, class, T_A, NULL, 0,
- ns_port, QUERY);
+ if (qp->q_distance < NS_MAX_DISTANCE)
+ (void) sysquery(dname, class, T_A, NULL, NULL,
+ 0, ns_port, QUERY,
+ qp->q_distance + 1);
}
skipserver:
(void)NULL;
@@ -678,7 +696,7 @@ nslookup(struct databuf *nsp[], struct qinfo *qp,
ns_debug(ns_log_default, 3, "nslookup: %d ns addrs total", n);
qp->q_naddr = n;
if (n == 0 && potential_ns == 0 && !NS_ZFWDTAB(qp->q_fzone)) {
- static char *complaint = "No possible A RRs";
+ static const char *complaint = "No possible A RRs";
if (lame_ns != 0)
complaint = "All possible A RR's lame";
if (sysloginfo && syslogdname &&
@@ -784,7 +802,7 @@ qcomp(struct qserv *qs1, struct qserv *qs2) {
strcpy(t, inet_ntoa(qs1->ns_addr.sin_addr));
ns_debug(ns_log_default, 10,
- "qcomp(%s, %s) %lu (%lu) - %lu (%lu) = %lu",
+ "qcomp(%s, %s) %u (%u) - %u (%u) = %u",
t, inet_ntoa(qs2->ns_addr.sin_addr),
rtt1, rttr1, rtt2, rttr2, rtt1 - rtt2);
}
@@ -813,7 +831,7 @@ void
schedretry(struct qinfo *qp, time_t t) {
struct qinfo *qp1, *qp2;
- ns_debug(ns_log_default, 4, "schedretry(%#x, %ld sec)", qp, (long)t);
+ ns_debug(ns_log_default, 4, "schedretry(%p, %ld sec)", qp, (long)t);
if (qp->q_time)
ns_debug(ns_log_default, 4,
"WARNING: schedretry(%#lx, %ld) q_time already %ld",
@@ -885,22 +903,28 @@ reset_retrytimer() {
void
retrytimer(evContext ctx, void *uap, struct timespec due,
struct timespec ival) {
+
+ UNUSED(ctx);
+ UNUSED(uap);
+ UNUSED(due);
+ UNUSED(ival);
+
retry_timer_set = 0;
- retry(retryqp);
+ retry(retryqp, 0);
}
/*
* Retry is called to retransmit query 'qp'.
*/
void
-retry(struct qinfo *qp) {
- int n, has_tsig, oldqlen;
+retry(struct qinfo *qp, int samehost) {
+ int n, has_tsig, oldqlen = 0;
HEADER *hp;
struct sockaddr_in *nsa;
int sendto_errno = 0;
- u_char *oldqbuf;
- u_char *smsg;
- int smsglen, smsgsize, siglen;
+ u_char *oldqbuf = NULL;
+ u_char *smsg = NULL;
+ int smsglen, smsgsize = 0, siglen;
u_char sig[TSIG_SIG_SIZE];
DST_KEY *key;
@@ -923,7 +947,15 @@ retry(struct qinfo *qp) {
/* Try next address. */
n = qp->q_curaddr;
+ if (samehost) {
+ qp->q_addr[n].nretry++;
+ if (qp->q_addr[n].nretry < MAXRETRY)
+ goto found;
+ qp->q_addr[n].nretry--;
+ }
+
if (qp->q_naddr > 0) {
+ qp->q_addr[n].noedns = 1;
++qp->q_addr[n].nretry;
do {
if (++n >= (int)qp->q_naddr)
@@ -970,7 +1002,7 @@ retry(struct qinfo *qp) {
}
ns_debug(ns_log_default, 5, "give up");
if ((qp->q_flags & Q_SYSTEM) == 0) {
- n = ((HEADER *)qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
+ n = (qp->q_cmsg ? qp->q_cmsglen : qp->q_msglen);
hp->id = qp->q_id;
hp->qr = 1;
hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
@@ -1015,24 +1047,29 @@ retry(struct qinfo *qp) {
res_pquery(&res, qp->q_msg, qp->q_msglen,
log_get_stream(packet_channel));
#endif
- key = tsig_key_from_addr(nsa->sin_addr);
- if (key != NULL) {
- smsgsize = qp->q_msglen + TSIG_BUF_SIZE;
+ key = qp->q_keys[n];
+ if (key == NULL)
+ key = qp->q_keys[n] = tsig_key_from_addr(nsa->sin_addr);
+ if (key != NULL || !qp->q_addr[n].noedns) {
+ smsgsize = qp->q_msglen + TSIG_BUF_SIZE + 11;
smsg = memget(smsgsize);
smsglen = qp->q_msglen;
siglen = sizeof(sig);
memcpy(smsg, qp->q_msg, qp->q_msglen);
+ }
+
+ if (!qp->q_addr[n].noedns)
+ smsglen += ns_add_opt(smsg, smsg + smsglen, smsgsize, 0, 0,
+ EDNS_MESSAGE_SZ, 0, NULL, 0);
+
+ if (key != NULL) {
n = ns_sign(smsg, &smsglen, smsgsize, NOERROR, key, NULL, 0,
sig, &siglen, 0);
if (n == 0) {
- oldqbuf = qp->q_msg;
- oldqlen = qp->q_msglen;
- qp->q_msglen = smsglen;
- qp->q_msg = smsg;
has_tsig = 1;
+ free_tsig(qp->q_nstsig);
qp->q_nstsig = new_tsig(key, sig, siglen);
- }
- else {
+ } else {
has_tsig = 0;
free_tsig(qp->q_nstsig);
qp->q_nstsig = NULL;
@@ -1044,6 +1081,13 @@ retry(struct qinfo *qp) {
qp->q_nstsig = NULL;
}
+ if (smsg != NULL) {
+ oldqbuf = qp->q_msg;
+ oldqlen = qp->q_msglen;
+ qp->q_msglen = smsglen;
+ qp->q_msg = smsg;
+ }
+
if (qp->q_flags & Q_USEVC) {
if (tcp_send(qp) != NOERROR)
ns_debug(ns_log_default, 3,
@@ -1057,8 +1101,8 @@ retry(struct qinfo *qp) {
ns_debug(ns_log_default, 3, "error resending msg: %s",
strerror(errno));
}
- if (has_tsig == 1) {
- memput(qp->q_msg, smsgsize);
+ if (smsgsize != 0) {
+ memput(smsg, smsgsize);
qp->q_msg = oldqbuf;
qp->q_msglen = oldqlen;
}
@@ -1171,33 +1215,14 @@ qnew(const char *name, int class, int type, int forward) {
}
void
-ns_freeqns(struct qinfo *qp, char *where) {
- static const char freed[] = "freed", busy[] = "busy";
- const char *result;
- struct databuf *dp;
- int i;
-
- for (i = 0 ; i < (int)qp->q_naddr ; i++) {
- dp = qp->q_addr[i].ns;
- if (dp) {
- DRCNTDEC(dp);
- result = (dp->d_rcnt) ? busy : freed;
- ns_debug(ns_log_default, 3, "%s: ns %s rcnt %d (%s)",
- where, dp->d_data, dp->d_rcnt, result);
- if (result == freed)
- db_freedata(dp);
- }
- dp = qp->q_addr[i].nsdata;
- if (dp) {
- DRCNTDEC(dp);
- result = (dp->d_rcnt) ? busy : freed;
- ns_debug(ns_log_default, 3,
- "%s: nsdata %s rcnt %d (%s)",
- where, inet_ntoa(ina_get(dp->d_data)),
- dp->d_rcnt, result);
- if (result == freed)
- db_freedata(dp);
- }
+ns_freeqns(struct qinfo *qp) {
+ unsigned int i;
+
+ for (i = 0 ; i < qp->q_naddr ; i++) {
+ if (qp->q_addr[i].ns != NULL)
+ db_detach(&qp->q_addr[i].ns);
+ if (qp->q_addr[i].nsdata != NULL)
+ db_detach(&qp->q_addr[i].nsdata);
}
}
@@ -1214,14 +1239,14 @@ ns_freeqry(struct qinfo *qp) {
if (qp->q_cmsg != NULL)
memput(qp->q_cmsg, qp->q_cmsgsize);
if (qp->q_domain != NULL)
- freestr(qp->q_domain);
+ qp->q_domain = freestr(qp->q_domain);
if (qp->q_name != NULL)
- freestr(qp->q_name);
+ qp->q_name = freestr(qp->q_name);
if (qp->q_tsig != NULL)
memput(qp->q_tsig, sizeof(struct tsig_record));
if (qp->q_nstsig != NULL)
memput(qp->q_nstsig, sizeof(struct tsig_record));
- ns_freeqns(qp, "ns_freeqry");
+ ns_freeqns(qp);
if (nsqhead == qp)
nsqhead = qp->q_link;
else {
@@ -1245,7 +1270,7 @@ nsfwdadd(struct qinfo *qp, struct fwdinfo *fwd) {
n = qp->q_naddr;
while (fwd != NULL && n < NSMAX) {
qs = qp->q_addr;
- for (i = 0; i < (u_int)n; i++, qs++)
+ for (i = 0; i < n; i++, qs++)
if (ina_equal(qs->ns_addr.sin_addr,
fwd->fwddata->fwdaddr.sin_addr))
goto nextfwd;
@@ -1253,6 +1278,7 @@ nsfwdadd(struct qinfo *qp, struct fwdinfo *fwd) {
qs->ns = fwd->fwddata->ns;
qs->nsdata = fwd->fwddata->nsdata;
qs->forwarder = 1;
+ qs->noedns = fwd->fwddata->nsdata->d_noedns;
qs->nretry = 0;
n++;
nextfwd:
@@ -1260,7 +1286,7 @@ nsfwdadd(struct qinfo *qp, struct fwdinfo *fwd) {
}
/* Update the refcounts before the sort. */
- for (i = qp->q_naddr; i < (u_int)n; i++) {
+ for (i = qp->q_naddr; i < n; i++) {
DRCNTINC(qp->q_addr[i].nsdata);
DRCNTINC(qp->q_addr[i].ns);
}
OpenPOWER on IntegriCloud