diff options
Diffstat (limited to 'contrib/bind/bin/named/db_ixfr.c')
-rw-r--r-- | contrib/bind/bin/named/db_ixfr.c | 216 |
1 files changed, 140 insertions, 76 deletions
diff --git a/contrib/bind/bin/named/db_ixfr.c b/contrib/bind/bin/named/db_ixfr.c index a009f4d..7a50618 100644 --- a/contrib/bind/bin/named/db_ixfr.c +++ b/contrib/bind/bin/named/db_ixfr.c @@ -1,6 +1,6 @@ #if !defined(lint) && !defined(SABER) -static char rcsid[] = "$Id: db_ixfr.c,v 8.18 1999/10/15 19:48:57 vixie Exp $"; -#endif /* not lint */ +static char rcsid[] = "$Id: db_ixfr.c,v 8.20 2000/02/29 05:15:03 vixie Exp $"; +#endif /* * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc. @@ -51,81 +51,137 @@ static char rcsid[] = "$Id: db_ixfr.c,v 8.18 1999/10/15 19:48:57 vixie Exp $ #include <isc/eventlib.h> #include <isc/logging.h> +#include <isc/memcluster.h> #include "port_after.h" #include "named.h" -#define DBIXFR_ERROR -1 -#define DBIXFR_FOUND_RR 2 -#define DBIXFR_END 3 +#define DBIXFR_ERROR (-1) +#define DBIXFR_FOUND_RR 2 +#define DBIXFR_END 3 -static int ixfr_getrr(struct zoneinfo *, FILE *, const char *, char *, - ns_updrec **, u_int32_t *, u_int32_t *); +static int ixfr_getdelta(struct zoneinfo *, FILE *, const char *, char *, + ns_updque *, u_int32_t *, u_int32_t *); -ns_updrec * +ns_deltalist * ixfr_get_change_list(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) { - FILE * fp; + FILE * fp = NULL; u_int32_t old_serial, new_serial; char origin[MAXDNAME]; - struct namebuf *np, *listnp, *finlistnp; - LIST(ns_updrec) listuprec; - int ret, mode; + ns_deltalist *dlhead = NULL; + int ret; ns_updrec *uprec; + ns_delta *dl; if (SEQ_GT(from_serial, to_serial)) return (NULL); - listnp = finlistnp = NULL; - INIT_LIST(listuprec); + + dlhead = memget(sizeof(*dlhead)); + if (dlhead == NULL) + return (NULL); + INIT_LIST(*dlhead); + if ((fp = fopen(zp->z_ixfr_base, "r")) == NULL) { ns_warning(ns_log_db, "%s: %s", zp->z_ixfr_base, strerror(errno)); - return (NULL); + goto cleanup; } strcpy(origin, zp->z_origin); lineno = 1; - np = NULL; - mode = 0; old_serial = new_serial = 0; + for (;;) { - ret = ixfr_getrr(zp, fp, zp->z_ixfr_base, origin, &uprec, - &old_serial, &new_serial); + dl = memget(sizeof *dl); + if (dl == NULL) { + ns_warning(ns_log_db, + "ixfr_get_change_list: out of memory"); + goto cleanup; + } + INIT_LINK(dl, d_link); + INIT_LIST(dl->d_changes); + ret = ixfr_getdelta(zp, fp, zp->z_ixfr_base, origin, &dl->d_changes, + &old_serial, &new_serial); switch (ret) { case DBIXFR_ERROR: - (void) my_fclose(fp); - ns_warning(ns_log_db, "Logical error in %s line %d", - zp->z_ixfr_base, lineno); - return (NULL); + ns_warning(ns_log_db, "Logical error in %s: unlinking", + zp->z_ixfr_base); + unlink(zp->z_ixfr_base); + goto cleanup; + case DBIXFR_FOUND_RR: - if (EMPTY(listuprec)) { + ns_debug(ns_log_default, 4, "ixfr_getdelta DBIXFR_FOUND_RR (%s)", + zp->z_origin); + if (EMPTY(*dlhead)) { /* skip updates prior to the one we want */ - if (uprec->r_zone != from_serial) { - while (uprec != NULL) { - ns_updrec *prev; + uprec = HEAD(dl->d_changes); + INSIST(uprec != NULL); + if ((uprec->r_zone < from_serial) || + (uprec->r_zone > to_serial)) + { + while ((uprec = HEAD(dl->d_changes)) != NULL) { + UNLINK(dl->d_changes, uprec, r_link); if (uprec->r_dp != NULL) - db_freedata(uprec->r_dp); + db_freedata(uprec->r_dp); uprec->r_dp = NULL; - prev = PREV(uprec, r_link); res_freeupdrec(uprec); - uprec = prev; } + memput(dl, sizeof *dl); break; } + else if (uprec->r_zone > from_serial) { + /* missed the boat */ + ns_debug(ns_log_default, 3, + "ixfr_getdelta first SOA is %d, asked for %d (%s)", + uprec->r_zone, + from_serial, + zp->z_origin); + goto cleanup; + } } - APPEND(listuprec, uprec, r_link); - /* continue; */ + ns_debug(ns_log_default, 4, + "adding to change list (%s)", + zp->z_origin); + APPEND(*dlhead, dl, d_link); break; + case DBIXFR_END: + ns_debug(ns_log_default, 4, + "ixfr_getdelta DBIXFR_END (%s)", + zp->z_origin); (void) my_fclose(fp); - return (HEAD(listuprec)); + memput(dl, sizeof *dl); + return (dlhead); + default: (void) my_fclose(fp); + if (dl != NULL) + memput(dl, sizeof *dl); return (NULL); } } + + cleanup: + if (fp != NULL) + (void) my_fclose(fp); + + while ((dl = HEAD(*dlhead)) != NULL) { + UNLINK(*dlhead, dl, d_link); + while ((uprec = HEAD(dl->d_changes)) != NULL) { + UNLINK(dl->d_changes, uprec, r_link); + + if (uprec->r_dp != NULL) + db_freedata(uprec->r_dp); + uprec->r_dp = NULL; + res_freeupdrec(uprec); + } + memput(dl, sizeof *dl); + } + memput(dlhead, sizeof *dlhead); + return (NULL); } /* @@ -137,7 +193,7 @@ ixfr_get_change_list(struct zoneinfo *zp, * * returns: * 0 = serial number is up to date - * 1 = transision is possible + * 1 = transmission is possible * -1 = error while opening the ixfr transaction log * -2 = error in parameters * -3 = logical error in the history file @@ -147,14 +203,17 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) { FILE *fp; u_int32_t old_serial = 0, new_serial = 0; + u_int32_t last_serial = 0; + u_int32_t first_serial = 0; char buf[BUFSIZ]; char *cp; struct stat st; int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, inside_next = 0; int err; + int first = 0; + int rval = 0; int id, rcode = NOERROR; - if (SEQ_GT(from_serial, to_serial)) return (-2); if (from_serial == to_serial) @@ -162,6 +221,10 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) /* If there is no log file, just return. */ if (zp->z_ixfr_base == NULL || zp->z_updatelog == NULL) return (-1); + if (zp->z_serial_ixfr_start > 0) { + if (from_serial >= zp->z_serial_ixfr_start) + return (1); + } if (stat(zp->z_ixfr_base, &st) < 0) { if (errno != ENOENT) ns_error(ns_log_db, @@ -176,17 +239,18 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) } if (fgets(buf, sizeof(buf), fp) == NULL) { ns_error(ns_log_update, "fgets() from %s failed: %s", - zp->z_updatelog, strerror(errno)); + zp->z_ixfr_base, strerror(errno)); fclose(fp); return (-1); } if (strcmp(buf, LogSignature) != 0) { ns_error(ns_log_update, "invalid log file %s", - zp->z_updatelog); + zp->z_ixfr_base); fclose(fp); return (-3); } lineno = 1; + first = 1; for (;;) { if (getword(buf, sizeof buf, fp, 0)) { nonempty_lineno = lineno; @@ -214,12 +278,13 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) if (cp != NULL) lineno++; if (sscanf((char *) cp, "%u", &old_serial)) { + if (first == 1) { + first = 0; + first_serial = old_serial; + } + last_serial = old_serial; if (from_serial >= old_serial) { - fclose(fp); - return (1); - } else { - fclose(fp); - return (-1); + rval = 1; } } prev_pktdone = 1; @@ -232,14 +297,16 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) if (cp == NULL || sscanf((char *) cp, "from %u to %u", &old_serial, &new_serial) != 2) { - fclose(fp); - return (-3); + rval = -3; + break; } else if (from_serial >= old_serial) { - fclose(fp); - return (1); + if (first == 1) { + first = 0; + first_serial = old_serial; + } + last_serial = old_serial; + rval = 1; } - fclose(fp); - return (-1); } if (prev_pktdone) { prev_pktdone = 0; @@ -248,7 +315,19 @@ ixfr_have_log(struct zoneinfo *zp, u_int32_t from_serial, u_int32_t to_serial) } } fclose(fp); - return (0); + if (last_serial +1 < zp->z_serial) { + ns_warning(ns_log_db, + "%s: File Deleted. Found gap between serial:" + " %d and current serial: %d", + zp->z_ixfr_base, last_serial, zp->z_serial); + (void) unlink(zp->z_ixfr_base); + rval = -3; + } + if (from_serial < first_serial || from_serial > last_serial) + rval = -3; + if (rval == 1) + zp->z_serial_ixfr_start = first_serial; + return (rval); } /* from db_load.c */ @@ -278,12 +357,7 @@ static struct map m_opcode[] = { #define M_TYPE_CNT m_type_cnt /* - * int - * ixfr_getrr(struct zoneinfo *zp, FILE *fp, - * const char *filename, char *origin, struct namebuf **np, - * u_int32_t *old_serial, u_int32_t *new_serial) - * - * read a line from the historic of a zone. + * read a line from the history of a zone. * * returns: * @@ -292,8 +366,8 @@ static struct map m_opcode[] = { * DBIXFR_END = end of file */ static int -ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, - ns_updrec **uprec, u_int32_t *old_serial, +ixfr_getdelta(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, + ns_updque *listuprec, u_int32_t *old_serial, u_int32_t *new_serial) { static int read_soa, read_ns, rrcount; @@ -305,7 +379,7 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, u_int32_t serial, ttl; int nonempty_lineno = -1, prev_pktdone = 0, cont = 0, inside_next = 0; - int id, rcode = NOERROR; + int id; int i, c, section, opcode, matches, zonenum, err, multiline; int type, class; u_int32_t n; @@ -316,7 +390,6 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, struct in_addr ina; struct sockaddr_in empty_from; int datasize; - ns_updque listuprec; ns_updrec * rrecp; u_long l; @@ -325,7 +398,6 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, err = 0; transport = primary_trans; lineno = 1; - INIT_LIST(listuprec); for (;;) { if (!getword(buf, sizeof buf, fp, 0)) { if (lineno == (nonempty_lineno + 1) && !(feof(fp))) { @@ -337,11 +409,10 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, } /* * Empty line or EOF. - * - * Marks completion of current update packet. */ + if (feof(fp)) + break; inside_next = 0; - prev_pktdone = 1; cont = 1; } else { nonempty_lineno = lineno; @@ -349,15 +420,12 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, if (!strcasecmp(buf, "[DYNAMIC_UPDATE]") || !strcasecmp(buf, "[IXFR_UPDATE]")) { - err = 0; - rcode = NOERROR; cp = fgets(buf, sizeof buf, fp); if (cp != NULL) lineno++; if (cp == NULL || !sscanf((char *) cp, "id %d", &id)) id = -1; inside_next = 1; - prev_pktdone = 1; cont = 1; } else if (!strcasecmp(buf, "[INCR_SERIAL]")) { /* XXXRTH not enough error checking here */ @@ -380,14 +448,11 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, lineno++; } if (prev_pktdone) { - if (!EMPTY(listuprec)) { + if (!EMPTY(*listuprec)) { n++; - *uprec = TAIL(listuprec); return (DBIXFR_FOUND_RR); } prev_pktdone = 0; - if (feof(fp)) - break; } if (cont) { cont = 0; @@ -800,9 +865,7 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, ns_debug(ns_log_update, 1, "merge of update id %d failed due to error at line %d", id, lineno); - memset(&empty_from, 0, sizeof empty_from); - free_rrecp(&listuprec, rcode, empty_from); - continue; + return (DBIXFR_ERROR); } rrecp = res_mkupdrec(section, dname, class, type, ttl); if (section != S_ZONE) { @@ -822,7 +885,7 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, ns_updrec *arp; int foundmatch; - arp = TAIL(listuprec); + arp = TAIL(*listuprec); foundmatch = 0; while (arp) { if (arp->r_section == S_UPDATE && @@ -837,7 +900,7 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, db_cmp(arp->r_dp, dp) == 0) { db_freedata(dp); db_freedata(arp->r_dp); - UNLINK(listuprec, arp, r_link); + UNLINK(*listuprec, arp, r_link); res_freeupdrec(arp); res_freeupdrec(rrecp); foundmatch = 1; @@ -849,7 +912,7 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, continue; } - APPEND(listuprec, rrecp, r_link); + APPEND(*listuprec, rrecp, r_link); /* Override zone number with current zone serial number */ rrecp->r_zone = serial; } @@ -859,3 +922,4 @@ ixfr_getrr(struct zoneinfo *zp, FILE *fp, const char *filename, char *origin, return (DBIXFR_END); } + |