summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named/ns_xfr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/ns_xfr.c')
-rw-r--r--contrib/bind/bin/named/ns_xfr.c120
1 files changed, 74 insertions, 46 deletions
diff --git a/contrib/bind/bin/named/ns_xfr.c b/contrib/bind/bin/named/ns_xfr.c
index e25a536..f5cbdfa 100644
--- a/contrib/bind/bin/named/ns_xfr.c
+++ b/contrib/bind/bin/named/ns_xfr.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static const char rcsid[] = "$Id: ns_xfr.c,v 8.55 1999/10/13 16:39:13 vixie Exp $";
+static const char rcsid[] = "$Id: ns_xfr.c,v 8.62 2000/04/24 05:20:51 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996-1999 by Internet Software Consortium.
+ * Copyright (c) 1996-2000 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -79,7 +79,7 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
#ifdef SO_SNDLOWAT
static const int sndlowat = XFER_BUFSIZE;
#endif
- ns_updrec *changes;
+ ns_deltalist *changes;
switch (type) {
case ns_t_axfr: /*FALLTHROUGH*/
@@ -123,6 +123,8 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
qsp->xfr.top.axfr = znp;
qsp->xfr.zone = zone;
qsp->xfr.class = class;
+ if (qsp->flags & STREAM_AXFRIXFR)
+ type = ns_t_axfr;
qsp->xfr.type = type;
qsp->xfr.id = id;
qsp->xfr.opcode = opcode;
@@ -186,25 +188,32 @@ ns_xfr(struct qstream *qsp, struct namebuf *znp,
if (type == ns_t_ixfr) {
changes = ixfr_get_change_list(&zones[zone], serial_ixfr,
zones[zone].z_serial);
- if (changes != NULL)
- {
+ ixfr_log_maint(&zones[zone], 1);
+ if (changes != NULL) {
qsp->xfr.serial = serial_ixfr;
qsp->xfr.top.ixfr = changes;
}
- else
- type = ns_t_axfr;
- }
+ else {
+ qsp->xfr.top.ixfr = NULL;
+ goto abort;
+ }
+ } else {
if (sx_pushlev(qsp, znp) < 0) {
abort:
(void) shutdown(qsp->s_rfd, 2);
sq_remove(qsp);
return;
}
- if (type != ns_t_ixfr)
+ }
+ if (type != ns_t_ixfr) {
+ ns_debug(ns_log_default, 3, "sq_writeh sx_sendsoa (%s)",
+ zones[zone].z_origin);
(void) sq_writeh(qsp, sx_sendsoa);
- else
+ } else {
+ ns_debug(ns_log_default, 3, "sq_writeh sx_send_ixfr (%s)",
+ zones[zone].z_origin);
(void) sq_writeh(qsp, sx_send_ixfr);
-
+ }
}
/*
@@ -217,6 +226,8 @@ ns_stopxfrs(struct zoneinfo *zp) {
struct qstream *this, *next;
u_int zone = (u_int)(zp - zones);
+ ns_debug(ns_log_default, 3, "ns_stopxfrs (%s)", zp->z_origin);
+
for (this = streamq; this; this = next) {
next = this->s_next;
if (this->xfr.zone == zone) {
@@ -234,19 +245,37 @@ ns_stopxfrs(struct zoneinfo *zp) {
*/
void
ns_freexfr(struct qstream *qsp) {
+ ns_delta *dp;
+ ns_updrec *rp;
+
if (qsp->xfr.msg != NULL) {
memput(qsp->xfr.msg, XFER_BUFSIZE);
qsp->xfr.msg = NULL;
}
+ if (qsp->xfr.type == ns_t_ixfr && qsp->xfr.top.ixfr != NULL) {
+ while ((dp = HEAD(*qsp->xfr.top.ixfr)) != NULL) {
+ UNLINK(*qsp->xfr.top.ixfr, dp, d_link);
+ while ((rp = HEAD(dp->d_changes)) != NULL) {
+ UNLINK(dp->d_changes, rp, r_link);
+ if (rp->r_dp != NULL)
+ db_freedata(rp->r_dp);
+ rp->r_dp = NULL;
+ res_freeupdrec(rp);
+ }
+ memput(dp, sizeof *dp);
+ }
+ memput(qsp->xfr.top.ixfr, sizeof *qsp->xfr.top.ixfr);
+ qsp->xfr.top.ixfr = NULL;
+ }
while (qsp->xfr.lev)
qsp->xfr.lev = sx_freelev(qsp->xfr.lev);
zones[qsp->xfr.zone].z_numxfrs--;
- qsp->flags &= ~STREAM_AXFR;
+ qsp->flags &= ~(STREAM_AXFR | STREAM_AXFRIXFR);
}
/*
* u_char *
- * renew_msg(msg)
+ * sx_newmsg(msg)
* init the header of a message, reset the compression pointers, and
* reset the write pointer to the first byte following the header.
*/
@@ -315,7 +344,7 @@ sx_flush(struct qstream *qsp) {
* int
* sx_addrr(qsp, name, dp)
* add name/dp's RR to the current assembly message. if it won't fit,
- * write current message out, renew the message, and then RR should fit.
+ * write current message out, renew the message, and then RR *must* fit.
* return:
* -1 = the sx_flush() failed so we could not queue the full message.
* 0 = one way or another, everything is fine.
@@ -339,18 +368,20 @@ sx_addrr(struct qstream *qsp, const char *dname, struct databuf *dp) {
/*
* Add question to first answer.
*/
- if (qsp->xfr.state == s_x_firstsoa && dp->d_type == T_SOA ) {
- if ((qsp->xfr.type == ns_t_ixfr) || (qsp->flags & STREAM_AXFRIXFR)) {
- n = dn_comp(dname, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
- qsp->xfr.ptrs, edp);
- if (n > 0 && (qsp->xfr.cp + n + INT16SZ * 2) <= qsp->xfr.eom) {
- qsp->xfr.cp += n;
- type = (qsp->xfr.type == ns_t_zxfr) ?
- ns_t_axfr : qsp->xfr.type;
- PUTSHORT((u_int16_t) type, qsp->xfr.cp);
- PUTSHORT((u_int16_t) qsp->xfr.class, qsp->xfr.cp);
- hp->qdcount = htons(ntohs(hp->qdcount) + 1);
- }
+ if (qsp->xfr.state == s_x_firstsoa && dp->d_type == T_SOA) {
+ n = dn_comp(dname, qsp->xfr.cp, qsp->xfr.eom - qsp->xfr.cp,
+ qsp->xfr.ptrs, edp);
+ if (n > 0 && (qsp->xfr.cp + n + INT16SZ * 2) <= qsp->xfr.eom) {
+ qsp->xfr.cp += n;
+ if (qsp->xfr.type == ns_t_zxfr)
+ type = ns_t_axfr;
+ else if ((qsp->flags & STREAM_AXFRIXFR) != 0)
+ type = ns_t_ixfr;
+ else
+ type = qsp->xfr.type;
+ PUTSHORT((u_int16_t) type, qsp->xfr.cp);
+ PUTSHORT((u_int16_t) qsp->xfr.class, qsp->xfr.cp);
+ hp->qdcount = htons(ntohs(hp->qdcount) + 1);
}
}
@@ -416,11 +447,9 @@ sx_soarr(struct qstream *qsp) {
/*
* int
* sx_nsrrs(qsp)
- * add the NS RR's at the current level's current np,
- * to the assembly message
- * This function also adds the SIG(NS), KEY, SIG(KEY), NXT, SIG(NXT)
- * the reason for this these records are part of the delegation.
- *
+ * add the NS RR's at the current level's current np to the assembly msg.
+ * This function also adds the SIG(NS), KEY, SIG(KEY), NXT, SIG(NXT),
+ * since these records are also part of the delegation (see DNSSEC).
* return:
* >1 = number of NS RRs added, note that there may be more
* 0 = success, there are no more NS RRs at this level
@@ -438,15 +467,13 @@ sx_nsrrs(struct qstream *qsp) {
struct namebuf *gnp, *tnp, *top;
struct hashbuf *htp;
const char *fname;
- int rrcount, class;
+ int class;
class = qsp->xfr.class;
top = qsp->xfr.top.axfr;
- rrcount = 0;
for ((void)NULL;
(dp = qsp->xfr.lev->dp) != NULL;
qsp->xfr.lev->dp = db_next(dp)) {
- /* XYZZY foreach_rr? */
if (dp->d_class != class && class != C_ANY)
continue;
if (dp->d_rcode)
@@ -475,7 +502,9 @@ sx_nsrrs(struct qstream *qsp) {
}
if (dp->d_type != T_NS) /* no glue processing */
continue;
- rrcount++; /* only count NS records */
+ /* Remember we have found a zone cut */
+ if (qsp->xfr.top.axfr != qsp->xfr.lev->np)
+ qsp->xfr.lev->flags |= SXL_ZONECUT;
}
/*
@@ -528,9 +557,17 @@ sx_nsrrs(struct qstream *qsp) {
*/
return (-1);
}
+ foreach_rr(gdp, gnp, ns_t_a6, class, DB_Z_CACHE)
+ if (sx_addrr(qsp, fname, gdp) < 0) {
+ /*
+ * Rats. We already sent the NS RR, too.
+ * Note that SXL_GLUING is being left on.
+ */
+ return (-1);
+ }
qsp->xfr.lev->flags &= ~SXL_GLUING;
}
- return (rrcount);
+ return (0);
}
/*
@@ -565,7 +602,6 @@ sx_allrrs(struct qstream *qsp) {
for ((void)NULL;
(dp = qsp->xfr.lev->dp) != NULL;
qsp->xfr.lev->dp = db_next(dp)) {
- /* XYZZY foreach_rr? */
if (dp->d_class != class && class != C_ANY)
continue;
if (dp->d_rcode)
@@ -605,7 +641,6 @@ sx_allrrs(struct qstream *qsp) {
void
sx_sendlev(struct qstream *qsp) {
struct qs_x_lev *lev;
- int rrcount;
again:
lev = qsp->xfr.lev;
@@ -618,16 +653,9 @@ sx_sendlev(struct qstream *qsp) {
sq_remove(qsp);
return;
}
- rrcount = sx_nsrrs(qsp);
/* If we can't pack this one in, come back later. */
- if (rrcount < 0)
+ if (sx_nsrrs(qsp) < 0)
return;
- /*
- * NS RRs other than those at the
- * zone top are zone cuts.
- */
- if (rrcount > 0 && qsp->xfr.top.axfr != lev->np)
- lev->flags |= SXL_ZONECUT;
}
/* No more DP's for the NS RR pass on this NP. */
if (lev->flags & SXL_ZONECUT) {
OpenPOWER on IntegriCloud