summaryrefslogtreecommitdiff
path: root/contrib/bind/bin/named/db_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/db_load.c')
-rw-r--r--contrib/bind/bin/named/db_load.c2749
1 files changed, 0 insertions, 2749 deletions
diff --git a/contrib/bind/bin/named/db_load.c b/contrib/bind/bin/named/db_load.c
deleted file mode 100644
index 12d01979ceff..000000000000
--- a/contrib/bind/bin/named/db_load.c
+++ /dev/null
@@ -1,2749 +0,0 @@
-#if !defined(lint) && !defined(SABER)
-static const char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
-static const char rcsid[] = "$Id: db_load.c,v 8.121 2001/11/12 21:22:22 marka Exp $";
-#endif /* not lint */
-
-/*
- * Copyright (c) 1986, 1988, 1990
- * 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.
- */
-
-/*
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Portions Copyright (c) 1995 by International Business Machines, Inc.
- *
- * International Business Machines, Inc. (hereinafter called IBM) grants
- * permission under its copyrights to use, copy, modify, and distribute this
- * Software with or without fee, provided that the above copyright notice and
- * all paragraphs of this notice appear in all copies, and that the name of IBM
- * not be used in connection with the marketing of any product incorporating
- * the Software or modifications thereof, without specific, written prior
- * permission.
- *
- * To the extent it has a right to do so, IBM grants an immunity from suit
- * under its patents, if any, for the use, sale or manufacture of products to
- * the extent that such products are used for performing Domain Name System
- * dynamic updates in TCP/IP networks by means of the Software. No immunity is
- * granted for any product per se or for any other function of any product.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
-
-/*
- * Portions 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
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Load zone from ASCII file on local host. Format similar to RFC 883.
- */
-
-/* Import. */
-
-#include "port_before.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <netdb.h>
-#include <resolv.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-
-#include <isc/eventlib.h>
-#include <isc/logging.h>
-#include <isc/memcluster.h>
-#include <isc/misc.h>
-
-#include "port_after.h"
-
-#include "named.h"
-
-/* Forward. */
-
-static int gettoken(FILE *, const char *);
-static int getcharstring(char *, char *, int, int, int, FILE *,
- const char *);
-static int genname(char *, int, const char *, char *, int);
-static int getmlword(char *, size_t, FILE *, int);
-static int getallwords(char *, size_t, FILE *, int);
-static u_int32_t wordtouint32(char *);
-static void fixup_soa(const char *fn, struct zoneinfo *zp);
-static int get_nxt_types(u_char *, FILE *, const char *);
-
-static int parse_sig_rr(char *, int, u_char *, int, FILE *,
- struct zoneinfo *, char *, u_int32_t ,
- enum context, enum transport,
- const char **);
-static int parse_key_rr(char *, int, u_char *, int, FILE *,
- const char **);
-
-static int parse_cert_rr(char *, int, u_char *, int, FILE *,
- const char **);
-static int parse_nxt_rr(char *, u_char *, int, FILE *,
- struct zoneinfo *, char *, enum context,
- enum transport, const char **);
-
-
-static int wordtouint32_error = 0;
-static int empty_token = 0;
-static int getmlword_nesting = 0;
-
-/* Global. */
-
-static int clev; /* a zone deeper in a hierarchy has more credibility */
-
-/*
- * Parser token values
- */
-#define CURRENT 1
-#define DOT 2
-#define AT 3
-#define DNAME 4
-#define INCLUDE 5
-#define ORIGIN 6
-#define GENERATE 7
-#define DEFAULTTTL 8
-#define ERRTOK 9
-
-#define MAKENAME_OK(N) \
- do { \
- if (!makename_ok(N, origin, class, zp, \
- transport, context, \
- domain, filename, lineno, \
- data_size - ((u_char*)N - data))) { \
- errs++; \
- sprintf(buf, "bad name \"%s\"", N); \
- goto err; \
- } \
- } while (0)
-
-#define MAKENAME_OKZP(N, SI) \
- do { \
- if (!makename_ok(N, zp->z_origin, zp->z_class, zp, \
- transport, context, \
- domain, zp->z_source, lineno, \
- SI - ((u_char*)N - data))) { \
- errs++; \
- sprintf(buf, "bad name \"%s\"", N); \
- goto err; \
- } \
- } while (0)
-
-#define RANGE(x, min, max) \
- (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
-
-/* Public. */
-
-/* int
- * db_load(filename, in_origin, zp, def_domain, isixfr)
- * load a database from `filename' into zone `zp'. append `in_origin'
- * to all nonterminal domain names in the file. `def_domain' is the
- * default domain for include files or NULL for zone base files.
- * returns:
- * -1 = can't open file
- * 0 = success
- * >0 = number of errors encountered
- */
-int
-db_load(const char *filename, const char *in_origin,
- struct zoneinfo *zp, const char *def_domain, int isixfr)
-{
- static int read_soa, read_ns, rrcount;
- static u_int32_t default_ttl, default_warn;
- static struct filenames {
- struct filenames *next;
- char *name;
- } *filenames, *fn;
-
- const char *errtype = "Database";
- char *cp;
- char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME];
- char buf[MAXDATA];
- char genlhs[MAXDNAME], genrhs[MAXDNAME];
- u_char data[MAXDATA];
- unsigned int data_size = sizeof(data);
- int c, someclass, class, type, dbflags, dataflags, multiline = 0;
- int slineno, i, errs, didinclude, ininclude, escape, success;
- u_int32_t ttl, n, serial;
- u_long tmplong;
- struct databuf *dp;
- FILE *fp;
- struct stat sb;
- struct in_addr ina;
- enum transport transport;
- enum context context;
- struct sockaddr_in empty_from;
- int genstart, genend, genstep;
- char *thisfile;
- void *state = NULL;
- int loggenerr;
-
- empty_from.sin_family = AF_INET;
- empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
- empty_from.sin_port = htons(0);
-
-/*
- * We use an 'if' inside of the 'do' below because otherwise the Solaris
- * compiler detects that the 'while' is never executed because of the 'goto'
- * and complains.
- */
-#define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0)
-#define ERRTOZ(msg) do { if (1) { errtype = msg; buf[0] = '\0'; goto err; } } while (0)
-
- switch (zp->z_type) {
- case Z_PRIMARY:
- /* Any updates should be saved before we attempt to reload. */
- INSIST((zp->z_flags & (Z_NEED_DUMP|Z_NEED_SOAUPDATE)) == 0);
- case Z_HINT:
- if (filename == NULL) {
- ns_error(ns_log_load,
- "Required filename not specified for Hint zone");
- zp->z_flags |= Z_DB_BAD;
- zp->z_ftime = 0;
- return (0);
- }
- transport = primary_trans;
- break;
- case Z_SECONDARY:
- case Z_STUB:
- transport = secondary_trans;
- break;
- case Z_CACHE:
- transport = response_trans;
- break;
- default:
- transport = response_trans; /*guessing*/
- break;
- }
- errs = 0;
- didinclude = 0;
- ininclude = (def_domain != NULL);
- if (!ininclude) {
- rrcount = 0;
- read_soa = 0;
- read_ns = 0;
- default_ttl = USE_MINIMUM;
- default_warn = 1;
- clev = nlabels(in_origin);
- filenames = NULL;
- zp->z_minimum = USE_MINIMUM;
- }
- ttl = default_ttl;
-
- ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s, %s)",
- filename, in_origin, zp - zones,
- def_domain ? def_domain : "Nil", isixfr ? "IXFR" : "Normal");
-
- fn = (struct filenames *)memget(sizeof *filenames);
- if (fn == NULL)
- ns_panic(ns_log_db, 0, "db_load: memget failed");
- thisfile = fn->name = savestr(filename, 1);
- fn->next = filenames;
- filenames = fn;
-
- strcpy(origin, in_origin);
- if ((fp = fopen(filename, "r")) == NULL) {
- ns_warning(ns_log_load, "db_load could not open: %s: %s",
- filename, strerror(errno));
- zp->z_ftime = 0;
- if (ininclude)
- return (-1);
- errs = -1;
- goto cleanup;
- }
- if (zp->z_type == Z_HINT) {
- dbflags = DB_NODATA | DB_NOHINTS;
- dataflags = DB_F_HINT;
-#ifdef STUBS
- } else if (zp->z_type == Z_STUB && clev == 0) {
- dbflags = DB_NODATA | DB_NOHINTS;
- dataflags = DB_F_HINT;
-#endif
- } else {
- dbflags = DB_NODATA;
- dataflags = 0;
- }
- gettime(&tt);
- if (fstat(fileno(fp), &sb) < 0) {
- ns_warning(ns_log_load, "fstat failed: %s: %s",
- filename, strerror(errno));
- sb.st_mtime = (int)tt.tv_sec;
- }
- slineno = lineno;
- lineno = 1;
- if (def_domain)
- strcpy(domain, def_domain);
- else
- domain[0] = '\0';
- class = zp->z_class;
- zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD);
- while ((c = gettoken(fp, filename)) != EOF) {
- switch (c) {
- case INCLUDE:
- if (isixfr) {
- c = ERRTOK;
- break;
- }
- if (!getword(buf, sizeof buf, fp, 0))
- /* file name*/
- break;
- if (!getword(tmporigin, sizeof(tmporigin), fp, 1))
- strcpy(tmporigin, origin);
- else {
- if (makename(tmporigin, origin,
- sizeof(tmporigin)) == -1)
- ERRTO("$INCLUDE makename failed");
- endline(fp);
- }
- didinclude = 1;
- i = db_load(buf, tmporigin, zp, domain, ISNOTIXFR);
- errs += (i == -1) ? 1 : i;
- continue;
-
- case ORIGIN:
- (void) strcpy(buf, origin);
- if (!getword(origin, sizeof(origin), fp, 1))
- break;
- ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s",
- origin, buf);
- if (makename(origin, buf, sizeof(origin)) == -1)
- ERRTO("$ORIGIN makename failed");
- ns_debug(ns_log_load, 3, "db_load: origin now %s",
- origin);
- continue;
-
- case GENERATE:
- if (!getword(buf, sizeof(buf), fp, 0))
- ERRTOZ("$GENERATE missing RANGE");
- n = sscanf(buf, "%d-%d/%d", &genstart, &genend,
- &genstep);
- if (n != 2 && n != 3)
- ERRTO("$GENERATE invalid range");
- if (n == 2)
- genstep = 1;
- if ((genend < genstart) || (genstart < 0) ||
- (genstep < 0))
- ERRTO("$GENERATE invalid range");
- if (!getword(genlhs, sizeof(genlhs), fp, 2))
- ERRTOZ("$GENERATE missing LHS");
- if (!getword(buf, sizeof(buf), fp, 0))
- ERRTOZ("GENERATE missing TYPE");
- type = res_nametotype(buf, &success);
- if (success == 0 || type == ns_t_any) {
- ns_info(ns_log_load,
- "%s: Line %d: $GENERATE unknown type: %s.",
- filename, lineno, buf);
- errs++;
- endline(fp);
- continue;
- }
- switch (type) {
- case ns_t_ns:
- case ns_t_ptr:
- case ns_t_cname:
- case ns_t_a:
- case ns_t_aaaa:
- break;
- default:
- ERRTO("$GENERATE unsupported type");
- }
- if (!getword(genrhs, sizeof(genrhs), fp, 2))
- ERRTOZ("$GENERATE missing RHS");
- loggenerr = 1;
- for (i = genstart; i <= genend; i += genstep) {
- if (genname(genlhs, i, origin, domain,
- sizeof domain) == -1)
- ERRTOZ("$GENERATE genname LHS failed");
- if (!ns_samedomain(domain, zp->z_origin)) {
- /* Log first per $GENERATE. */
- if (loggenerr) {
- ns_info(ns_log_load,
- "%s:%d: $GENERATE LHS out of zone (ignored)",
- filename, lineno);
- loggenerr = 0;
- }
- continue;
- }
- context = ns_ownercontext(type, transport);
- if (!ns_nameok(NULL, domain, class, zp, transport,
- context, domain, inaddr_any)) {
- strcpy(buf, domain);
- ERRTO("$GENERATE owner name error");
- }
- switch (type) {
- case ns_t_ns:
- case ns_t_ptr:
- case ns_t_cname:
- if (genname(genrhs, i, origin, (char *)data,
- sizeof data) == -1)
- ERRTOZ("$GENERATE genname RHS failed");
- switch (type) {
- case ns_t_ns:
- context = hostname_ctx;
- break;
- case ns_t_ptr:
- context = ns_ptrcontext(domain);
- break;
- case ns_t_cname:
- context = domain_ctx;
- break;
- }
- if (!ns_nameok(NULL, (char *)data, class, zp,
- transport, context,
- domain, inaddr_any)) {
- strncpy(buf, domain, sizeof(buf));
- buf[sizeof(buf)-1] = '\0';
- ERRTO("$GENERATE name error");
- }
- n = strlen((char *)data) + 1;
- break;
- case ns_t_a:
- case ns_t_aaaa:
- if (genname(genrhs, i, NULL, (char *)data,
- sizeof data) == -1)
- ERRTOZ("$GENERATE genname RHS failed");
- strncpy(buf, (char*)data, sizeof(buf));
- buf[sizeof(buf)-1] = '\0';
- switch (type) {
- case ns_t_a:
- if (!inet_aton(buf, &ina))
- ERRTO("IP Address");
- (void) ina_put(ina, data);
- n = NS_INT32SZ;
- break;
- case ns_t_aaaa:
- if (inet_pton(AF_INET6, buf, data) <= 0)
- ERRTO("IPv6 Address");
- n = NS_IN6ADDRSZ;
- break;
- }
- break;
- default:
- ERRTOZ("$GENERATE unsupported context");
- }
- dp = savedata(class, type, (u_int32_t)ttl,
- (u_char *)data, (int)n);
- dp->d_zone = zp - zones;
- dp->d_flags = dataflags;
- dp->d_cred = DB_C_ZONE;
- dp->d_clev = clev;
- c = db_set_update(domain, dp, &state, dbflags,
- (dataflags & DB_F_HINT) != 0 ?
- &fcachetab : &hashtab,
- empty_from, &rrcount, lineno,
- filename);
- if (c != OK) {
- if (c == CNAMEANDOTHER || c == NONGLUE)
- errs++;
- }
- db_detach(&dp);
- }
- endline(fp);
- continue;
-
- case DNAME:
- if (!getword(domain, sizeof(domain), fp, 1))
- break;
- if (makename(domain, origin, sizeof(domain)) == -1)
- ERRTO("ownername makename failed");
- goto gotdomain;
-
- case DEFAULTTTL:
- if (getttl(fp, filename, lineno, &n,
- &multiline) <= 0 || n > MAXIMUM_TTL) {
- ERRTO("$TTL bad TTL value");
- }
- ttl = default_ttl = n;
- continue;
-
- case AT:
- (void) strcpy(domain, origin);
- goto gotdomain;
-
- case DOT:
- domain[0] = '\0';
- /* FALLTHROUGH */
- case CURRENT:
- gotdomain:
- if (!getword(buf, sizeof buf, fp, 0)) {
- if (c == CURRENT)
- continue;
- break;
- }
- if (ns_parse_ttl(buf, &tmplong) < 0) {
- if (zp->z_type == z_master &&
- default_warn &&
- (default_ttl == USE_MINIMUM)) {
- ns_warning(ns_log_load,
- "Zone \"%s\" (file %s): %s",
- zp->z_origin, filename,
- "No default TTL ($TTL <value>) set, using SOA minimum instead");
- default_warn = 0;
- }
- ttl = (u_int32_t)default_ttl;
- } else {
- ttl = tmplong;
- if (ttl > MAXIMUM_TTL) {
- ns_info(ns_log_load,
- "%s: Line %d: TTL > %u; converted to 0",
- filename, lineno, MAXIMUM_TTL);
- ttl = 0;
- }
- if (zp->z_type == Z_CACHE) {
- /*
- * This allows the cache entry to age
- * while sitting on disk (powered off).
- */
- if (ttl > max_cache_ttl)
- ttl = max_cache_ttl;
- ttl += sb.st_mtime;
- }
- if (!getword(buf, sizeof buf, fp, 0))
- break;
- }
-
- /* Parse class (IN, etc) */
- someclass = res_nametoclass(buf, &success);
- if (success && someclass != zp->z_class) {
- ns_info(ns_log_load,
- "%s: Line %d: wrong class: %s.",
- filename, lineno,
- p_class(someclass));
- errs++;
- break;
- }
- if (success && someclass != C_ANY) {
- class = someclass;
- (void) getword(buf, sizeof buf, fp, 0);
- }
-
- /* Parse RR type (A, MX, etc) */
- type = res_nametotype(buf, &success);
- if (success == 0 || type == ns_t_any) {
- ns_info(ns_log_load,
- "%s: Line %d: Unknown type: %s.",
- filename, lineno, buf);
- errs++;
- break;
- }
- if (ttl == USE_MINIMUM)
- ttl = zp->z_minimum;
- context = ns_ownercontext(type, transport);
- if (!ns_nameok(NULL, domain, class, zp, transport, context,
- domain, inaddr_any)) {
- errs++;
- ns_notice(ns_log_load,
- "%s:%d: owner name error",
- filename, lineno);
- break;
- }
- context = domain_ctx;
- switch (type) {
- case ns_t_key:
- case ns_t_sig:
- case ns_t_nxt:
- case ns_t_cert:
- /*
- * Don't do anything here for these types --
- * they read their own input separately later.
- */
- goto dont_get_word;
-
- case ns_t_soa:
- case ns_t_minfo:
- case ns_t_rp:
- case ns_t_ns:
- case ns_t_cname:
- case ns_t_mb:
- case ns_t_mg:
- case ns_t_mr:
- case ns_t_ptr:
- escape = 1;
- break;
- case ns_t_a:
- case ns_t_md:
- case ns_t_mf:
- case ns_t_null:
- case ns_t_hinfo:
- case ns_t_mx:
- case ns_t_txt:
- case ns_t_afsdb:
- case ns_t_x25:
- case ns_t_isdn:
- case ns_t_rt:
- case ns_t_nsap:
- case ns_t_nsap_ptr:
- case ns_t_px:
- case ns_t_gpos:
- case ns_t_aaaa:
- case ns_t_loc:
- case ns_t_eid:
- case ns_t_nimloc:
- case ns_t_srv:
- case ns_t_atma:
- case ns_t_naptr:
- case ns_t_kx:
- case ns_t_dname:
- case ns_t_sink:
- escape = 0;
- break;
- case ns_t_opt:
- case ns_t_tkey:
- case ns_t_tsig:
- case ns_t_ixfr:
- case ns_t_axfr:
- case ns_t_mailb:
- case ns_t_maila:
- case ns_t_any:
- case ns_t_zxfr:
- escape = 0;
- ns_info(ns_log_load,
- "%s: Line %d: meta type: %s.",
- filename, lineno, p_type(type));
- errs++;
- break;
- case ns_t_a6: /* not implemented */
- default:
- escape = 1;
- break;
- }
- if (!getword(buf, sizeof buf, fp, escape))
- break;
- ns_debug(ns_log_load, 3,
- "d='%s', c=%d, t=%d, ttl=%u, data='%s'",
- domain, class, type, ttl, buf);
- /*
- * Convert the ascii data 'buf' to the proper format
- * based on the type and pack into 'data'.
- */
- dont_get_word:
- switch (type) {
- case ns_t_a:
- if (!inet_aton(buf, &ina))
- ERRTO("IP Address");
- (void) ina_put(ina, data);
- n = NS_INT32SZ;
- break;
-
- case ns_t_soa:
- context = hostname_ctx;
- goto soa_rp_minfo;
- case ns_t_rp:
- case ns_t_minfo:
- context = mailname_ctx;
- /* FALLTHROUGH */
- soa_rp_minfo:
- (void) strcpy((char *)data, buf);
-
- MAKENAME_OK((char *)data);
- cp = (char *)(data + strlen((char *)data) + 1);
- if (!getword(cp,
- (sizeof data) -
- (cp - (char*)data),
- fp, 1))
- ERRTO("Domain Name");
- if (type == ns_t_rp)
- context = domain_ctx;
- else
- context = mailname_ctx;
- MAKENAME_OK(cp);
- cp += strlen((char *)cp) + 1;
- if (type != ns_t_soa) {
- n = cp - (char *)data;
- break;
- }
- if (ns_samename(zp->z_origin, domain) != 1) {
- errs++;
- ns_error(ns_log_load,
- "%s:%d: SOA for \"%s\" not at zone top \"%s\"",
- filename, lineno, domain,
- zp->z_origin);
- }
- c = getnonblank(fp, filename, 0);
- if (c == '(') {
- multiline = 1;
- } else {
- multiline = 0;
- ungetc(c, fp);
- }
- serial = zp->z_serial;
- zp->z_serial = getnum(fp, filename,
- GETNUM_SERIAL,
- &multiline);
- if (getnum_error)
- errs++;
- n = (u_int32_t) zp->z_serial;
- PUTLONG(n, cp);
- if (serial != 0 &&
- SEQ_GT(serial, zp->z_serial)) {
- ns_notice(ns_log_load,
- "%s:%d: WARNING: new serial number < old (%lu < %lu)",
- filename , lineno,
- (unsigned long)zp->z_serial,
- (unsigned long)serial);
- }
- if (getttl(fp, filename, lineno, &n,
- &multiline) <= 0) {
- errs++;
- n = INIT_REFRESH;
- }
- PUTLONG(n, cp);
- zp->z_refresh = RANGE(n, MIN_REFRESH,
- MAX_REFRESH);
- if (zp->z_type == Z_SECONDARY
-#if defined(STUBS)
- || zp->z_type == Z_STUB
-#endif
- ) {
- ns_refreshtime(zp, MIN(sb.st_mtime,
- tt.tv_sec));
- sched_zone_maint(zp);
- }
-#ifdef BIND_UPDATE
- if ((zp->z_type == Z_PRIMARY) &&
- (zp->z_flags & Z_DYNAMIC))
- if ((u_int32_t)zp->z_soaincrintvl >
- zp->z_refresh/3) {
- ns_info(ns_log_load,
- "zone soa update time truncated to 1/3rd of refresh time");
- zp->z_soaincrintvl =
- zp->z_refresh / 3;
- }
-#endif
-
- if (getttl(fp, filename, lineno, &n,
- &multiline) <= 0) {
- errs++;
- n = INIT_REFRESH;
- }
- PUTLONG(n, cp);
- zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY);
- if (getttl(fp, filename, lineno,
- &n, &multiline) <= 0) {
- errs++;
- n = INIT_REFRESH;
- }
- PUTLONG(n, cp);
- zp->z_expire = RANGE(n, zp->z_refresh,
- MAX_EXPIRE);
- if (getttl(fp, filename, lineno, &n,
- &multiline) <= 0) {
- errs++;
- n = 120;
- }
- PUTLONG(n, cp);
- if (n > MAXIMUM_TTL) {
- ns_info(ns_log_load,
- "%s: Line %d: SOA minimum TTL > %u; converted to 0",
- filename, lineno, MAXIMUM_TTL);
- zp->z_minimum = 0;
- } else
- zp->z_minimum = n;
- if (ttl == USE_MINIMUM)
- ttl = n;
- n = cp - (char *)data;
- if (multiline) {
- buf[0] = getnonblank(fp, filename, 1);
- buf[1] = '\0';
- if (buf[0] != ')')
- ERRTO("SOA \")\"");
- multiline = 0;
- endline(fp);
- }
- read_soa++;
- if (zp->z_type == Z_PRIMARY)
- fixup_soa(filename, zp);
- break;
-
- case ns_t_wks:
- /* Address */
- if (!inet_aton(buf, &ina))
- ERRTO("WKS IP Address");
- (void) ina_put(ina, data);
- /* Protocol */
- data[INADDRSZ] = getprotocol(fp, filename);
- /* Services */
- n = getservices(NS_INT32SZ + sizeof(char),
- (char *)data, fp, filename);
- break;
-
- case ns_t_ns:
- if (ns_samename(zp->z_origin, domain) == 1)
- read_ns++;
- context = hostname_ctx;
- goto cname_etc;
- case ns_t_cname:
- case ns_t_mb:
- case ns_t_mg:
- case ns_t_mr:
- context = domain_ctx;
- goto cname_etc;
- case ns_t_ptr:
- context = ns_ptrcontext(domain);
- cname_etc:
- (void) strcpy((char *)data, buf);
- MAKENAME_OK((char *)data);
- n = strlen((char *)data) + 1;
- break;
-
- case ns_t_naptr:
- /* Order Preference Flags Service Replacement Regexp */
- n = 0;
- cp = buf;
- /* Order */
- while (isdigit(*cp))
- n = n * 10 + (*cp++ - '0');
- /* catch bad values */
- if (cp == buf || n > 65535)
- ERRTO("NAPTR Order");
- cp = (char *)data;
- PUTSHORT((u_int16_t)n, cp);
-
- /* Preference */
- n = getnum(fp, filename, GETNUM_NONE,
- &multiline);
- if (getnum_error || n > 65536)
- ERRTO("NAPTR Preference");
- PUTSHORT((u_int16_t)n, cp);
-
- /* Flags */
- if (!getword(buf, sizeof buf, fp, 0))
- ERRTO("NAPTR Flags");
- n = strlen(buf);
- if (n > 255)
- ERRTO("NAPTR Flags too big");
- *cp++ = n;
- memcpy(cp, buf, (int)n);
- cp += n;
-
- /* Service Classes */
- if (!getword(buf, sizeof buf, fp, 0))
- ERRTO("NAPTR Service Classes");
- n = strlen(buf);
- if (n > 255)
- ERRTO("NAPTR Service Classes too big");
- *cp++ = n;
- memcpy(cp, buf, (int)n);
- cp += n;
-
- /* Pattern */
- if (!getword(buf, sizeof buf, fp, 0))
- ERRTO("NAPTR Pattern");
- n = strlen(buf);
- if (n > 255)
- ERRTO("NAPTR Pattern too big");
- *cp++ = n;
- memcpy(cp, buf, (int)n);
- cp += n;
-
- /* Replacement */
- if (!getword(buf, sizeof buf, fp, 1))
- ERRTO("NAPTR Replacement");
- n = strlen(buf);
- if (n > data_size - ((u_char *)cp - data))
- ERRTO("NAPTR Replacement too big");
- (void) strcpy((char *)cp, buf);
- context = domain_ctx;
- MAKENAME_OK(cp);
- /* advance pointer to end of data */
- cp += strlen((char *)cp) +1;
-
- /* now save length */
- n = (cp - (char *)data);
- break;
-
-
- case ns_t_mx:
- case ns_t_afsdb:
- case ns_t_rt:
- case ns_t_srv:
- n = 0;
- cp = buf;
- while (isdigit(*cp))
- n = n * 10 + (*cp++ - '0');
- /* catch bad values */
- if ((cp == buf) || (n > 65535))
- ERRTO("Priority");
- cp = (char *)data;
- PUTSHORT((u_int16_t)n, cp);
-
- if (type == ns_t_srv) {
- n = getnum(fp, filename, GETNUM_NONE,
- &multiline);
- if (getnum_error || n > 65536)
- ERRTO("SRV RR");
- PUTSHORT((u_int16_t)n, cp);
-
- n = getnum(fp, filename, GETNUM_NONE,
- &multiline);
- if (getnum_error || n > 65536)
- ERRTO("SRV RR");
- PUTSHORT((u_int16_t)n, cp);
- }
-
- if (!getword(buf, sizeof buf, fp, 1))
- ERRTO("Domain Name");
- (void) strcpy((char *)cp, buf);
- context = hostname_ctx;
- MAKENAME_OK(cp);
- /* advance pointer to end of data */
- cp += strlen((char *)cp) +1;
-
- /* now save length */
- n = (cp - (char *)data);
- break;
-
- case ns_t_px:
- context = domain_ctx;
- n = 0;
- data[0] = '\0';
- cp = buf;
- while (isdigit(*cp))
- n = n * 10 + (*cp++ - '0');
- /* catch bad values */
- if ((cp == buf) || (n > 65535))
- ERRTO("PX Priority");
- cp = (char *)data;
- PUTSHORT((u_int16_t)n, cp);
-
- if (!getword(buf, sizeof buf, fp, 0))
- ERRTO("PX Domain1");
- (void) strcpy((char *)cp, buf);
- MAKENAME_OK(cp);
- /* advance pointer to next field */
- cp += strlen((char *)cp) + 1;
- if (!getword(buf, sizeof buf, fp, 0))
- ERRTO("PX Domain2");
- (void) strcpy((char *)cp, buf);
- MAKENAME_OK(cp);
- /* advance pointer to end of data */
- cp += strlen((char *)cp) + 1;
-
- /* now save length */
- n = (cp - (char *)data);
- break;
-
- case ns_t_hinfo:
- n = getcharstring(buf, (char *)data, type,
- 2, 2, fp, filename);
- if (n == 0)
- ERRTO("HINFO RR");
- break;
-
- case ns_t_isdn:
- n = getcharstring(buf, (char *)data, type,
- 1, 2, fp, filename);
- if (n == 0)
- ERRTO("ISDN RR");
- break;
-
- case ns_t_txt:
- n = getcharstring(buf, (char *)data, type,
- 1, 0, fp, filename);
- if (n == 0)
- ERRTO("TXT RR");
- break;
-
-
- case ns_t_x25:
- n = getcharstring(buf, (char *)data, type,
- 1, 1, fp, filename);
- if (n == 0)
- ERRTO("X25 RR");
- break;
-
- case ns_t_nsap:
- if (buf[0] != '0' ||
- (buf[1] != 'x' && buf[1] != 'X'))
- ERRTO("NSAP RR: no leading 0x");
- n = inet_nsap_addr(buf, (u_char *)data,
- sizeof data);
- if (n == 0)
- ERRTO("NSAP RR");
- endline(fp);
- break;
-
- case ns_t_aaaa:
- if (inet_pton(AF_INET6, buf, data) <= 0)
- ERRTO("IPv4 Address");
- n = NS_IN6ADDRSZ;
- endline(fp);
- break;
-
- case ns_t_nxt:
- case ns_t_key:
- case ns_t_cert:
- case ns_t_sig: {
- const char *errmsg = NULL;
- int ret;
- if (ttl == USE_MINIMUM) /* no ttl set */
- ttl = 0;
- ret = parse_sec_rdata(buf, sizeof(buf), 0,
- data, sizeof(data),
- fp, zp, domain, ttl,
- type, domain_ctx,
- transport, &errmsg);
- if (ret < 0) {
- errtype = errmsg;
- goto err;
- }
- else
- n = ret;
- break;
- }
-
-
- case ns_t_loc:
- cp = buf + (n = strlen(buf));
- *cp = ' ';
- cp++;
- n++;
- while ((i = getc(fp), *cp = i, i != EOF)
- && *cp != '\n'
- && (n < MAXDATA)) {
- cp++; n++;
- }
- if (*cp == '\n') /* leave \n for getword */
- ungetc(*cp, fp);
- *cp = '\0';
- /* now process the whole line */
- n = loc_aton(buf, (u_char *)data);
- if (n == 0)
- goto err;
- endline(fp);
- break;
-
- default:
- if (strcmp(buf, "\\#") != 0)
- goto err;
- if (!getword(buf, sizeof buf, fp, 0) ||
- !isdigit((unsigned char)buf[0]))
- ERRTO("opaque length");
- n = strtoul(buf, &cp, 10);
- if (n > 0xffff || *cp != '\0')
- ERRTO("opaque length");
- multiline = 0;
- i = isc_gethexstring(data, sizeof(data), n, fp,
- &multiline);
- if (i == -1)
- ERRTO("opaque data read failed");
- if (multiline) {
- buf[0] = getnonblank(fp, filename, 1);
- buf[1] = '\0';
- if (buf[0] != ')')
- ERRTO("\")\" expected");
- multiline = 0;
- }
- endline(fp);
- }
- /*
- * Ignore data outside the zone.
- */
- if (zp->z_type != Z_CACHE &&
- !ns_samedomain(domain, zp->z_origin))
- {
- ns_info(ns_log_load,
- "%s:%d: data \"%s\" outside zone \"%s\" (ignored)",
- filename, lineno, domain,
- zp->z_origin);
- continue;
- }
- if (ttl == USE_MINIMUM) /* no ttl set */
- ttl = 0;
- dp = savedata(class, type, (u_int32_t)ttl,
- (u_char *)data, (int)n);
- dp->d_zone = zp - zones;
- dp->d_flags = dataflags;
- dp->d_cred = DB_C_ZONE;
- dp->d_clev = clev;
- c = db_set_update(domain, dp, &state, dbflags,
- (dataflags & DB_F_HINT) != 0 ?
- &fcachetab : &hashtab,
- empty_from, &rrcount, lineno,
- filename);
- if (c == CNAMEANDOTHER || c == NONGLUE)
- errs++;
- db_detach(&dp);
- continue;
-
- case ERRTOK:
- break;
- }
- err:
- errs++;
- ns_notice(ns_log_load, "%s:%d: %s error near (%s)",
- filename, empty_token ? (lineno - 1) : lineno,
- errtype, buf);
- if (!empty_token)
- endline(fp);
- }
- c = db_set_update(NULL, NULL, &state, dbflags,
- (dataflags & DB_F_HINT) ? &fcachetab : &hashtab,
- empty_from, &rrcount, lineno, filename);
- if (c != OK) {
- if (c == CNAMEANDOTHER || c == NONGLUE)
- errs++;
- }
-
- (void) my_fclose(fp);
- lineno = slineno;
- if (!ininclude) {
- if (didinclude) {
- zp->z_flags |= Z_INCLUDE;
- zp->z_ftime = 0;
- } else
- zp->z_ftime = sb.st_mtime;
- zp->z_lastupdate = sb.st_mtime;
- if (zp->z_type != Z_CACHE && zp->z_type != Z_HINT) {
- const char *msg = NULL;
-
- if (read_soa == 0)
- msg = "no SOA RR found";
- else if (read_soa != 1)
- msg = "multiple SOA RRs found";
- else if (read_ns == 0)
- msg = "no NS RRs found at zone top";
- else if (!rrcount)
- msg = "no relevant RRs found";
- if (msg != NULL) {
- errs++;
- ns_warning(ns_log_load,
- "Zone \"%s\" (file %s): %s",
- zp->z_origin, filename, msg);
- }
- }
- errs += purge_nonglue(zp->z_origin,
- (dataflags & DB_F_HINT) ? fcachetab :
- hashtab, zp->z_class,
- zp->z_type == z_master);
- cleanup:
- while (filenames) {
- fn = filenames;
- filenames = filenames->next;
- fn->name = freestr(fn->name);
- memput(fn, sizeof *fn);
- }
- if (errs != 0) {
- if (errs != -1)
- ns_error(ns_log_load,
- "%s zone \"%s\" (%s) rejected due to errors (serial %u)",
- zoneTypeString(zp->z_type),
- zp->z_origin,
- p_class(zp->z_class), zp->z_serial);
- if ((zp->z_flags & Z_NOTIFY) != 0)
- ns_stopnotify(zp->z_origin, zp->z_class);
- do_reload(zp->z_origin, zp->z_type, zp->z_class,
- loading);
- } else
- ns_info(ns_log_load,
- "%s zone \"%s\" (%s) loaded (serial %u)",
- zoneTypeString(zp->z_type), zp->z_origin,
- p_class(zp->z_class), zp->z_serial);
- }
- if (errs != 0) {
- zp->z_flags |= Z_DB_BAD;
- zp->z_ftime = 0;
- }
-#ifdef BIND_NOTIFY
- if (errs == 0 && (!ininclude) && (initial_configuration == 0 ||
- !NS_OPTION_P(OPTION_SUPNOTIFY_INITIAL)) &&
- (zp->z_type == z_master || zp->z_type == z_slave))
- ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
-#endif
- return (errs);
-}
-
-void
-db_err(int err, char *domain, int type, const char *filename, int lineno) {
- if (filename != NULL && err == CNAMEANDOTHER)
- ns_warning(ns_log_load, "%s:%d:%s: CNAME and OTHER data error",
- filename, lineno, domain);
- if (err != DATAEXISTS)
- ns_debug(ns_log_load, 1, "update failed %s %d",
- domain, type);
-}
-
-static int
-gettoken(FILE *fp, const char *src) {
- int c;
- char op[32];
-
- for (;;) {
- c = getc(fp);
- top:
- switch (c) {
- case EOF:
- return (EOF);
-
- case '$':
- if (getword(op, sizeof op, fp, 0)) {
- if (!strcasecmp("include", op))
- return (INCLUDE);
- if (!strcasecmp("origin", op))
- return (ORIGIN);
- if (!strcasecmp("generate", op))
- return (GENERATE);
- if (!strcasecmp("ttl", op))
- return (DEFAULTTTL);
- }
- ns_notice(ns_log_db,
- "%s:%d: Unknown $ option: $%s",
- src, lineno, op);
- return (ERRTOK);
-
- case ';':
- while ((c = getc(fp)) != EOF && c != '\n')
- ;
- goto top;
-
- case ' ':
- case '\t':
- return (CURRENT);
-
- case '.':
- return (DOT);
-
- case '@':
- return (AT);
-
- case '\n':
- lineno++;
- continue;
-
- case '\r':
- if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0)
- return (CURRENT);
-
- default:
- (void) ungetc(c, fp);
- return (DNAME);
- }
- }
-}
-
-/* int
- * getword(buf, size, fp, preserve)
- * get next word, skipping blanks & comments.
- * '\' '\n' outside of "quotes" is considered a blank.
- * parameters:
- * buf - destination
- * size - of destination
- * fp - file to read from
- * preserve - should we preserve \ before \\ and \.?
- * if preserve == 2, then keep all \
- * return value:
- * 0 = no word; perhaps EOL or EOF; lineno was incremented.
- * 1 = word was read
- */
-int
-getword(char *buf, size_t size, FILE *fp, int preserve) {
- char *cp = buf;
- int c, spaceok, once;
-
- empty_token = 0; /* XXX global side effect. */
- once = 0;
- while ((c = getc(fp)) != EOF) {
- once++;
- if (c == ';') {
- /* Comment. Skip to end of line. */
- while ((c = getc(fp)) != EOF && c != '\n')
- (void)NULL;
- c = '\n';
- }
- if (c == '\n') {
- /*
- * Unescaped newline. It's a terminator unless we're
- * already midway into a token.
- */
- if (cp != buf)
- ungetc(c, fp);
- else
- lineno++;
- break;
- }
- if (c == '"') {
- /* "Quoted string." Gather the whole string here. */
- while ((c = getc(fp)) != EOF && c!='"' && c!='\n') {
- if (c == '\\') {
- if ((c = getc(fp)) == EOF)
- c = '\\';
- if (preserve)
- switch (c) {
- default:
- if (preserve == 1)
- break;
- case '\\':
- case '.':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (cp >= buf+size-1)
- break;
- *cp++ = '\\';
- }
- if (c == '\n')
- lineno++;
- }
- if (cp >= buf+size-1)
- break;
- *cp++ = c;
- }
- /*
- * Newline string terminators are
- * not token terminators.
- */
- if (c == '\n') {
- lineno++;
- break;
- }
- /* Sample following character, check for terminator. */
- if ((c = getc(fp)) != EOF)
- ungetc(c, fp);
- if (c == EOF || isspace(c)) {
- *cp = '\0';
- return (1);
- }
- continue;
- }
- spaceok = 0;
- if (c == '\\') {
- /* Do escape processing. */
- if ((c = getc(fp)) == EOF)
- c = '\\';
- if (preserve)
- switch (c) {
- default:
- if (preserve == 1)
- break;
- case '\\':
- case '#':
- case '.':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (cp >= buf+size-1)
- break;
- *cp++ = '\\';
- }
- if (c == ' ' || c == '\t')
- spaceok++;
- }
- if (isspace(c) && !spaceok) {
- /* Blank of some kind. Skip run. */
- while (isspace(c = getc(fp)) && c != '\n')
- (void)NULL;
- ungetc(c, fp);
- /* Blank means terminator if the token is nonempty. */
- if (cp != buf) /* Trailing whitespace */
- break;
- continue; /* Leading whitespace */
- }
- if (cp >= buf + size - 1)
- break;
- *cp++ = (char)c;
- }
- *cp = '\0';
- if (cp == buf)
- empty_token = 1;
- if (!once)
- lineno++;
- return (cp != buf);
-}
-
-/*
- * int
- * getttl(fp, fn, ln, ttl, multiline)
- * read a word from the file and parse it as a TTL.
- * return:
- * 1 ttl found
- * 0 word not read (EOF or EOL?)
- * -1 word read but it wasn't a ttl
- * side effects:
- * *ttl is written if the return value is to be 1.
- */
-int
-getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) {
- char buf[MAXDATA];
- u_long tmp;
- int ch;
- int len;
-
- while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline)
- (void)NULL;
- len = strlen(buf);
- if (*multiline && len && buf[len-1] == ')') {
- buf[len-1] = '\0';
- *multiline = 0;
- }
- if (ns_parse_ttl(buf, &tmp) < 0) {
- ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"",
- fn, lineno, buf);
- return (-1);
- }
- if (*multiline) {
- ch = getnonblank(fp, fn, 1);
- if (ch == EOF)
- return (-1);
- if (ch == ';')
- endline(fp);
- else
- ungetc(ch, fp);
- }
- *ttl = (u_int32_t)tmp;
- return (1);
-}
-
-/* Get multiline words. Same parameters as getword. Handles any
- number of leading ('s or )'s in the words it sees.
- FIXME: We kludge recognition of ( and ) for multiline input.
- Each paren must appear at the start of a (blank-separated) word,
- which is particularly counter-intuitive for ). Good enough for now,
- until Paul rewrites the parser. (gnu@toad.com, oct96)
-*/
-static int
-getmlword(char *buf, size_t size, FILE *fp, int preserve) {
- char *p;
-
- do {
- while (!getword (buf, size, fp, preserve)) {
- /* No more words on this line. See if doing the
- multiline thing. */
- if (!getmlword_nesting) { /* Nope... */
- ungetc('\n', fp); /* Push back newline */
- lineno--; /* Unbump the lineno */
- empty_token = 0; /* Undo this botch */
- return 0;
- }
- if (feof(fp) || ferror(fp))
- return 0; /* Error, no terminating ')' */
- /* Continue reading til we get a word... */
- }
- while ('(' == *buf) {
- /* Word starts with paren. Multiline mode.
- Move the rest of the word down over the paren. */
- getmlword_nesting++;
- p = buf;
- while (0 != (p[0]=p[1])) p++;
- }
- while (')' == *buf) {
- getmlword_nesting--;
- p = buf;
- while (0 != (p[0]=p[1])) p++;
- }
- } while (buf[0] == 0); /* loop til we get a non-( non-) word */
-
- return 1; /* Got a word... */
-}
-
-/* Get all the remaining words on a line, concatenated into one big
- long (not too long!) string, with the whitespace squeezed out.
- This routine, like getword(), does not swallow the newline if words seen.
- This routine, unlike getword(), never swallows the newline if no words.
- Parameters are the same as getword(). Result is:
- 0 got no words at all
- 1 got one or more words
- -1 got too many words, they don't all fit; or missing close paren
-*/
-static int
-getallwords(char *buf, size_t size, FILE *fp, int preserve) {
- char *runningbuf = buf;
- int runningsize = size;
- int len;
-
- while (runningsize > 0) {
- if (!getmlword (runningbuf, runningsize, fp, preserve)) {
- return runningbuf!=buf; /* 1 or 0 */
- }
- len = strlen(runningbuf);
- runningbuf += len;
- runningsize -= len;
- }
- return -1; /* Error, String too long */
-}
-
-int
-getnum(FILE *fp, const char *src, int opt, int *multiline) {
- int c, n;
- int seendigit = 0;
- int seendecimal = 0;
- int m = 0;
- int allow_dots = 0;
-
- getnum_error = 0;
-#ifdef DOTTED_SERIAL
- if (opt & GETNUM_SERIAL)
- allow_dots++;
-#endif
- for (n = 0; (c = getc(fp)) != EOF; ) {
- if (isspace(c)) {
- if (c == '\n') {
- if (*multiline)
- lineno++;
- else if (!seendigit)
- goto eol;
- }
- if (seendigit)
- break;
- continue;
- }
- if (c == ';') {
- while ((c = getc(fp)) != EOF && c != '\n')
- ;
- if (c == '\n') {
- if (*multiline)
- lineno++;
- else if (!seendigit)
- goto eol;
- }
- if (seendigit)
- break;
- continue;
- }
- if (getnum_error)
- continue;
- if (!isdigit(c)) {
- if (c == ')' && seendigit) {
- (void) ungetc(c, fp);
- break;
- }
- if (seendigit && (opt & GETNUM_SCALED) &&
- strchr("KkMmGg", c) != NULL) {
- switch (c) {
- case 'K': case 'k':
- n *= 1024;
- break;
- case 'M': case 'm':
- n *= (1024 * 1024);
- break;
- case 'G': case 'g':
- n *= (1024 * 1024 * 1024);
- break;
- }
- break;
- }
- if (seendecimal || c != '.' || !allow_dots) {
- ns_notice(ns_log_db,
- "%s:%d: expected a number",
- src, lineno);
- getnum_error = 1;
- } else {
- if (!seendigit)
- n = 1;
-#ifdef SENSIBLE_DOTS
- n *= 10000;
-#else
- n *= 1000;
-#endif
- seendigit = 1;
- seendecimal = 1;
- }
- continue;
- }
-#ifdef SENSIBLE_DOTS
- if (seendecimal)
- m = m * 10 + (c - '0');
- else
- n = n * 10 + (c - '0');
-#else
- n = n * 10 + (c - '0');
-#endif
- seendigit = 1;
- }
- if (getnum_error)
- return (0);
- if (m > 9999) {
- ns_info(ns_log_db,
- "%s:%d: number after the decimal point exceeds 9999",
- src, lineno);
- getnum_error = 1;
- return (0);
- }
- if (seendecimal) {
- ns_info(ns_log_db,
- "%s:%d: decimal serial number interpreted as %d",
- src, lineno, n+m);
- }
- return (n + m);
-
- eol:
- ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno);
- getnum_error = 1;
- (void) ungetc(c, fp);
- return (0);
-}
-
-#ifndef BIND_UPDATE
-static
-#endif
-int
-getnonblank(FILE *fp, const char *src, int multiline) {
- int c;
-
- while ((c = getc(fp)) != EOF) {
- if (isspace(c)) {
- if (c == '\n') {
- if (multiline)
- lineno++;
- else
- goto eol;
- }
- continue;
- }
- if (c == ';') {
- while ((c = getc(fp)) != EOF && c != '\n')
- ;
- if (c == '\n') {
- if (multiline)
- lineno++;
- else
- goto eol;
- }
- continue;
- }
- return (c);
- }
- ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno);
- return (EOF);
- eol:
- ns_error(ns_log_db, "%s:%d: unexpected end of line", src, lineno);
- /* don't ungetc(c, fp); as the caller will do this. */
- return(c);
-}
-
-/*
- * Replace all single "$"'s in "name" with "it".
- * ${delta} will add delta to "it" before printing.
- * ${delta,width} will change print width as well, zero fill is implied
- * ${delta,width,radix} will change radix as well, can be d, o, x, X.
- * i.e. ${0,2,X} will produce a two digit hex (upper case) with zero fill.
- * Append "origin" to name if required and validate result with makename.
- * To get a "$" or "{" in the output use \ before it.
- * Return 0 on no error or -1 on error.
- * Resulting name stored in "buf".
- */
-
-static int
-genname(char *name, int it, const char *origin, char *buf, int size) {
- char *bp = buf;
- char *eom = buf + size;
- char *cp;
- char numbuf[32];
- char fmt[32];
- int delta = 0;
- int width;
-
- while (*name) {
- if (*name == '$') {
- if (*(++name) == '$') {
- /* should be deprecated. how? */
- if (bp >= eom)
- return (-1);
- *bp++ = *name++;
- } else {
- strcpy(fmt, "%d");
- if (*name == '{') {
- switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) {
- case 1:
- break;
- case 2:
- sprintf(fmt, "%%0%dd", width);
- break;
- case 3:
- sprintf(fmt, "%%0%d%c", width, numbuf[0]);
- break;
- default:
- return (-1);
- }
- while (*name && *name++ != '}') {
- continue;
- }
- }
- sprintf(numbuf, fmt, it + delta);
- cp = numbuf;
- while (*cp) {
- if (bp >= eom)
- return (-1);
- *bp++ = *cp++;
- }
- }
- } else if (*name == '\\') {
- if (*(++name) == '\0') {
- if (bp >= eom)
- return (-1);
- *bp++ = '\\';
- } else {
- switch (*name) {
- case '\\':
- case '.':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (bp >= eom)
- return (-1);
- *bp++ = '\\';
- default:
- if (bp >= eom)
- return (-1);
- *bp++ = *name++;
- }
- }
- } else {
- if (bp >= eom)
- return (-1);
- *bp++ = *name++;
- }
- }
- if (bp >= eom)
- return (-1);
- *bp = '\0';
- return (origin == NULL ? 0 : makename(buf, origin, size));
-}
-
-
-/*
- * Take name and fix it according to following rules:
- * "." means root.
- * "@" means current origin.
- * "name." means no changes.
- * "name" means append origin.
- */
-int
-makename(char *name, const char *origin, int size) {
- int n;
- u_char domain[MAXCDNAME];
-
- switch (ns_name_pton(name, domain, sizeof(domain))) {
- case -1:
- return (-1);
- case 1: /* FULLY QUALIFIED */
- break;
- case 0: /* UNQUALIFIED */
- if (strcmp(name, "@") == 0) /* must test raw name */
- domain[0] = 0;
- if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1)
- return (-1);
- /* step back over root, append origin */
- switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) {
- case -1:
- return (-1);
- case 0:
- case 1:
- break;
- }
- break;
- }
- if (ns_name_ntop(domain, name, size) == -1)
- return (-1);
- if (name[0] == '.') /* root */
- name[0] = '\0';
- return (0);
-}
-
-int
-makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp,
- enum transport transport, enum context context,
- const char *owner, const char *filename, int lineno, int size)
-{
- int ret = 1;
-
- if (makename(name, origin, size) == -1) {
- ns_info(ns_log_db, "%s:%d: makename failed",
- filename, lineno);
- return (0);
- }
- if (!ns_nameok(NULL, name, class, zp, transport, context, owner,
- inaddr_any)) {
- ns_info(ns_log_db, "%s:%d: database naming error",
- filename, lineno);
- ret = 0;
- }
- return (ret);
-}
-
-void
-endline(FILE *fp) {
- int c;
-
- while ((c = getc(fp)) != '\0') {
- if (c == '\n') {
- (void) ungetc(c,fp);
- break;
- } else if (c == EOF) {
- break;
- }
- }
-}
-
-#define MAXPORT 1024
-#define MAXLEN 24
-
-#ifndef BIND_UPDATE
-static
-#endif
-char
-getprotocol(FILE *fp, const char *src) {
- int k;
- char b[MAXLEN];
-
- (void) getword(b, sizeof(b), fp, 0);
-
- k = protocolnumber(b);
- if (k == -1)
- ns_info(ns_log_db, "%s:%d: unknown protocol: %s.",
- src, lineno, b);
- return ((char) k);
-}
-
-#ifndef BIND_UPDATE
-static
-#endif
-int
-getservices(int offset, char *data, FILE *fp, const char *src) {
- int j, ch, k, maxl, bracket;
- char bm[MAXPORT/8];
- char b[MAXLEN];
-
- for (j = 0; j < MAXPORT/8; j++)
- bm[j] = 0;
- maxl = 0;
- bracket = 0;
- while (getword(b, sizeof(b), fp, 0) || bracket) {
- if (feof(fp) || ferror(fp))
- break;
- if (strlen(b) == 0)
- continue;
- if (b[0] == '(') {
- bracket++;
- continue;
- }
- if (b[0] == ')') {
- bracket = 0;
- while ((ch = getc(fp)) != EOF && ch != '\n')
- (void)NULL;
- if (ch == '\n')
- lineno++;
- break;
- }
- k = servicenumber(b);
- if (k == -1) {
- ns_info(ns_log_db,
- "%s:%d: Unknown service '%s'",
- src, lineno, b);
- continue;
- }
- if ((k < MAXPORT) && (k)) {
- bm[k/8] |= (0x80>>(k%8));
- if (k > maxl)
- maxl = k;
- } else {
- ns_info(ns_log_db,
- "%s:%d: port no. (%d) too big",
- src, lineno, k);
- }
- }
- if (bracket)
- ns_info(ns_log_db, "%s:%d: missing close paren",
- src, lineno);
- maxl = maxl/8+1;
- memcpy(data+offset, bm, maxl);
- return (maxl+offset);
-}
-
-/*
- * Converts a word to a u_int32_t. Error if any non-numeric
- * characters in the word, except leading or trailing white space.
- */
-static u_int32_t
-wordtouint32(buf)
- char *buf;
-{
- u_long result;
- u_int32_t res2;
- char *bufend;
-
- wordtouint32_error = 0;
- result = strtoul(buf, &bufend, 0);
- if (bufend == buf)
- wordtouint32_error = 1;
- else
- while ('\0' != *bufend) {
- if (isspace(*bufend))
- bufend++;
- else {
- wordtouint32_error = 1;
- break;
- }
- }
- /* Check for truncation between u_long and u_int32_t */
- res2 = result;
- if (res2 != result)
- wordtouint32_error = 1;
- return (res2);
-}
-
-static int
-getcharstring(char *buf, char *data, int type,
- int minfields, int maxfields,
- FILE *fp, const char *src)
-{
- int nfield = 0, done = 0, n = 0, i;
- char *b = buf;
-
- do {
- nfield++;
- i = strlen(buf);
-#ifdef ALLOW_LONG_TXT_RDATA
- b = buf;
- if (type == ns_t_txt || type == ns_t_x25) {
- while (i > MAXCHARSTRING
- && n + MAXCHARSTRING + 1 < MAXDATA) {
- data[n] = (char)MAXCHARSTRING;
- memmove(data + n + 1, b, MAXCHARSTRING);
- n += MAXCHARSTRING + 1;
- b += MAXCHARSTRING;
- i -= MAXCHARSTRING;
- }
- }
-#endif /* ALLOW_LONG_TXT_RDATA */
- if (i > MAXCHARSTRING) {
- ns_info(ns_log_db,
- "%s:%d: RDATA field %d too long",
- src, lineno -1, nfield);
- return (0);
- }
- if (n + i + 1 > MAXDATA) {
- ns_info(ns_log_db,
- "%s:%d: total RDATA too long",
- src, lineno -1);
- return (0);
- }
- data[n] = i;
- memmove(data + n + 1, b, (int)i);
- n += i + 1;
- done = (maxfields && nfield >= maxfields);
- } while (!done && getword(buf, MAXDATA, fp, 0));
-
- if (nfield < minfields) {
- ns_info(ns_log_db,
- "%s:%d: expected %d RDATA fields, only saw %d",
- src, lineno -1, minfields, nfield);
- return (0);
- }
-
- if (done)
- endline(fp);
-
- return (n);
-}
-
-
-/*
- * get_nxt_types(): Read the list of types in the NXT record.
- *
- * Data is the array where the bit flags are stored; it must
- * contain at least ns_t_any/NS_NXT_BITS bytes.
- * FP is the input FILE *.
- * Filename is the sourcefile
- *
- * The result is how many bytes are significant in the result.
- * ogud@tis.com 1995
- */
-static int
-get_nxt_types(u_char *data, FILE *fp, const char *filename) {
- char b[MAXLABEL]; /* Not quite the right size, but good enough */
- int maxtype=0;
- int success;
- int type;
- int errs = 0;
-
- memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1);
-
- while (getmlword(b, sizeof(b), fp, 0)) {
- if (feof(fp) || ferror(fp))
- break;
- if (strlen(b) == 0 || b[0] == '\n')
- continue;
-
- /* Parse RR type (A, MX, etc) */
- type = res_nametotype((char *)b, &success);
- if ((!success) || type == ns_t_any) {
- errs++;
- ns_info(ns_log_db,
- "%s: Line %d: Unknown type: %s in NXT record.",
- filename, lineno, b);
- continue;
- }
- NS_NXT_BIT_SET(type, data);
- if (type > maxtype)
- maxtype = type;
- }
- if (errs)
- return (0);
- else
- return (maxtype/NS_NXT_BITS+1);
-}
-
-/* sanity checks PRIMARY ONLY */
-static void
-fixup_soa(const char *fn, struct zoneinfo *zp) {
- /* Sanity: give enough time for the zone to transfer (retry). */
- if (zp->z_expire < (zp->z_refresh + zp->z_retry))
- ns_notice(ns_log_db,
- "%s: WARNING SOA expire value is less than SOA refresh+retry (%u < %u+%u)",
- fn, zp->z_expire, zp->z_refresh, zp->z_retry);
-
- /* Sanity. */
- if (zp->z_expire < (zp->z_refresh + 10 * zp->z_retry))
- ns_warning(ns_log_db,
-"%s: WARNING SOA expire value is less than refresh + 10 * retry \
-(%u < (%u + 10 * %u))",
- fn, zp->z_expire, zp->z_refresh, zp->z_retry);
-
- /*
- * Sanity: most hardware/telco faults are detected and fixed within
- * a week, secondaries should continue to operate for this time.
- * (minimum of 4 days for long weekends)
- */
- if (zp->z_expire < (7 * 24 * 3600))
- ns_warning(ns_log_db,
- "%s: WARNING SOA expire value is less than 7 days (%u)",
- fn, zp->z_expire);
-
- /*
- * Sanity: maximum down time if we havn't talked for six months
- * war must have broken out.
- */
- if (zp->z_expire > ( 183 * 24 * 3600))
- ns_warning(ns_log_db,
- "%s: WARNING SOA expire value is greater than 6 months (%u)",
- fn, zp->z_expire);
-
- /* Sanity. */
- if (zp->z_refresh < (zp->z_retry * 2))
- ns_warning(ns_log_db,
- "%s: WARNING SOA refresh value is less than 2 * retry (%u < %u * 2)",
- fn, zp->z_refresh, zp->z_retry);
-}
-
-/* this function reads in the sig record rdata from the input file and
- * returns the following codes
- * > 0 length of the recrod
- * ERR_EOF end of file
- *
- */
-
-static int
-parse_sig_rr(char *buf, int buf_len, u_char *data, int data_size,
- FILE *fp, struct zoneinfo *zp, char *domain, u_int32_t ttl,
- enum context domain_ctx, enum transport transport,
- const char **errmsg)
-{
-/* The SIG record looks like this in the db file:
- Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig
-
- where: Name and Cl are as usual
- SIG is a keyword
- RRtype is a char string
- ALGid is 8 bit u_int
- Labels is 8 bit u_int
- OTTL is 32 bit u_int (optionally present)
- Texp is YYYYMMDDHHMMSS
- Tsig is YYYYMMDDHHMMSS
- Kfoot is 16-bit unsigned decimal integer
- Signer is a char string
- Sig is 64 to 319 base-64 digits
- A missing OTTL is detected by the magnitude of the Texp value
- that follows it, which is larger than any u_int.
- The Labels field in the binary RR does not appear in the
- text RR.
-
- It's too crazy to run these pages of SIG code at the right
- margin. I'm exdenting them for readability.
-*/
- u_int32_t sig_type;
- int dateerror;
- int siglen, success;
- u_char *cp;
- u_int32_t al, la, n;
- u_int32_t signtime, exptime, timetilexp;
- u_int32_t origTTL;
- enum context context;
- time_t now;
- const char *errtype = "SIG error";
- int i, my_buf_size = MAXDATA, errs = 0;
-
-
- /* The TTL gets checked against the Original TTL,
- and bounded by the signature expiration time, which
- are both under the signature. We can't let TTL drift
- based on the SOA record. If defaulted, fix it now.
- (It's not clear to me why USE_MINIMUM isn't eliminated
- before putting ALL RR's into the database. -gnu@toad.com) */
- if (ttl == USE_MINIMUM)
- ttl = zp->z_minimum;
-
- i = 0;
- data[i] = '\0';
-
- getmlword_nesting = 0; /* KLUDGE err recovery */
-
- /* RRtype (char *)
- * if old style inp will contain the next token
- *copy that into buffer, otherwise read from file
- */
- if (buf && buf_len == 0)
- if (!getmlword((char*)buf, my_buf_size, fp, 0))
- ERRTO("SIG record doesn't specify type");
- sig_type = res_nametotype(buf, &success);
- if (!success || sig_type == ns_t_any) {
- /*
- * We'll also accept a numeric RR type,
- * for signing RR types that this version
- * of named doesn't yet understand.
- * In the ns_t_any case, we rely on wordtouint32
- * to fail when scanning the string "ANY".
- */
- sig_type = wordtouint32 (buf);
- if (wordtouint32_error || sig_type > 0xFFFF)
- ERRTO("Unknown RR type in SIG record");
- }
- cp = &data[i];
- PUTSHORT((u_int16_t)sig_type, cp);
- i += 2;
-
- /* Algorithm id (8-bit decimal) */
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("Missing algorithm ID");
- al = wordtouint32(buf);
- if (0 == al || wordtouint32_error || 255 <= al)
- ERRTO("Bad algorithm number");
- data[i] = (u_char) al;
- i++;
-
- /*
- * Labels (8-bit decimal)
- */
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("Missing label count");
- la = wordtouint32(buf);
- if (wordtouint32_error || 255 <= la ||
- (0 == la && *domain != '\0'))
- ERRTO("Bad label count number");
- data[i] = (u_char) la;
- i++;
-
- /*
- * OTTL (optional u_int32_t) and
- * Texp (u_int32_t date)
- */
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("OTTL and expiration time missing");
- /*
- * See if OTTL is missing and this is a date.
- * This relies on good, silent error checking
- * in ns_datetosecs.
- */
- exptime = ns_datetosecs(buf, &dateerror);
- if (!dateerror) {
- /* Output TTL as OTTL */
- origTTL = ttl;
- cp = &data[i];
- PUTLONG (origTTL, cp);
- i += 4;
- } else {
- /* Parse and output OTTL; scan TEXP */
- origTTL = wordtouint32(buf);
- if (wordtouint32_error || (origTTL > 0x7fffffffU))
- ERRTO("Original TTL value bad");
- cp = &data[i];
- PUTLONG(origTTL, cp);
- i += 4;
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("Expiration time missing");
- exptime = ns_datetosecs(buf, &dateerror);
- }
- if (dateerror || exptime > 0x7fffffff || exptime <= 0)
- ERRTO("Invalid expiration time");
- cp = &data[i];
- PUTLONG(exptime, cp);
- i += 4;
-
- /* Tsig (u_int32_t) */
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("Missing signature time");
- signtime = ns_datetosecs(buf, &dateerror);
- if (0 == signtime || dateerror)
- ERRTO("Invalid signature time");
- cp = &data[i];
- PUTLONG(signtime, cp);
- i += 4;
-
- /* Kfootprint (unsigned_16) */
- if (!getmlword(buf, my_buf_size, fp, 0))
- ERRTO("Missing key footprint");
- n = wordtouint32(buf);
- if (wordtouint32_error || n >= 0x0ffff)
- ERRTO("Invalid key footprint");
- cp = &data[i];
- PUTSHORT((u_int16_t)n, cp);
- i += 2;
-
- /* Signer's Name */
- if (!getmlword((char*)buf, my_buf_size, fp, 0))
- ERRTO("Missing signer's name");
- cp = &data[i];
- strcpy((char *)cp, buf);
- context = domain_ctx;
- MAKENAME_OKZP((char *)cp, data_size);
- i += strlen((char *)cp) + 1;
-
- /*
- * Signature (base64 of any length)
- * We don't care what algorithm it uses or what
- * the internal structure of the BASE64 data is.
- */
- if (!getallwords(buf, my_buf_size, fp, 0)) {
- siglen = 0;
- } else {
- cp = &data[i];
- siglen = b64_pton(buf, (u_char*)cp, data_size - i);
- if (siglen < 0)
- ERRTO("Signature block bad");
- }
-
- /* set total length and we're done! */
- n = i + siglen;
-
- /*
- * Check signature time, expiration, and adjust TTL. Note
- * that all time values are in GMT (UTC), *not* local time.
- */
-
- now = time (0); /* need to find a better place for this XXX ogud */
- /* Don't let bogus name servers increase the signed TTL */
- if (ttl > origTTL)
- ERRTO("TTL is greater than signed original TTL");
-
- /* Don't let bogus signers "sign" in the future. */
- if (signtime > (u_int32_t)now)
- ERRTO("signature time is in the future");
-
- /* Ignore received SIG RR's that are already expired. */
- if (exptime <= (u_int32_t)now)
- ERRTO("expiration time is in the past");
-
- /* Lop off the TTL at the expiration time. */
- timetilexp = exptime - now;
- if (timetilexp < ttl) {
- ns_debug(ns_log_load, 1,
- "shrinking expiring %s SIG TTL from %d to %d",
- p_secstodate(exptime), ttl, timetilexp);
- ttl = timetilexp;
- }
-
- /*
- * Check algorithm-ID and key structure, for
- * the algorithm-ID's that we know about.
- */
- switch (al) {
- case NS_ALG_MD5RSA:
- if (siglen == 0)
- ERRTO("No key for RSA algorithm");
- if (siglen < 1)
- ERRTO("Signature too short");
- if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8)
- ERRTO("Signature too long");
- break;
-
- case NS_ALG_DH:
- if (siglen < 1)
- ERRTO("DH Signature too short");
- break; /* need more tests here */
-
- case NS_ALG_DSA:
- if (siglen < NS_DSA_SIG_SIZE)
- ERRTO("DSS Signature too short");
- else if (siglen > NS_DSA_SIG_SIZE)
- ERRTO("DSS Signature too long ");
- break; /* need more tests here */
-
- case NS_ALG_EXPIRE_ONLY:
- if (siglen != 0)
- ERRTO(
- "Signature supplied to expire-only algorithm");
- break;
- case NS_ALG_PRIVATE_OID:
- if (siglen == 0)
- ERRTO("No ObjectID in key");
- break;
- default:
- ERRTO("UNKOWN SIG algorithm");
- }
-
- /* Should we complain about algorithm-ID's that we
- don't understand? It may help debug some obscure
- cases, but in general we should accept any RR whether
- we could cryptographically process it or not; it
- may be being published for some newer DNS clients
- to validate themselves. */
-
- endline(fp); /* flush the rest of the line */
-
- return (n);
- err:
- *errmsg = errtype;
- return (-1);
-}
-
-static int
-parse_nxt_rr(char *buf, u_char *data, int data_size, FILE *fp,
- struct zoneinfo *zp, char *domain, enum context context,
- enum transport transport, const char **errmsg)
-{
-
- /* The NXT record looks like:
- Name Cl NXT nextname RRT1 RRT2 MX A SOA ...
-
- where: Name and Cl are as usual
- NXT is a keyword
- nextname is the next valid name in the zone after "Name".
- All names between the two are known to be nonexistent.
- RRT's... are a series of RR type names, which indicate that
- RR's of these types are published for "Name", and
- that no RR's of any other types are published for "Name".
-
- When a NXT record is cryptographically signed, it proves the
- nonexistence of an RR (actually a whole set of RR's).
- */
- int n, errs = 0, i;
- u_char *cp;
-/* char *origin = zp->z_origin;
- int class = zp->z_class; */
- *errmsg = "NXT name error";
-
- (void) strcpy((char *)data, buf);
- MAKENAME_OKZP((char *)data, data_size);
- n = strlen((char *)data) + 1;
- cp = n + data;
- i = get_nxt_types(cp, fp, zp->z_source);
- if( i > 0)
- return (n + i);
- *errmsg = "NXT type error";
- err:
- return (-1);
-}
-
-
-static int
-parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size,
- FILE *fp, const char **errmsg)
-{
- /* Cert record looks like:
- * Type Key_tag Alg Cert
- * Type: certification type number (16)
- * Key_tag: tag of corresponding KEY RR (16)
- * Alg: algorithm of the KEY RR (8)
- * Cert: base64 enocded block
- */
- u_char *cp;
- u_int32_t cert_type, key_tag, alg;
- const char *errtype = "CERT parse error";
- int certlen, i, n, success;
-
- i = 0;
- cp = &data[i];
- cert_type = sym_ston(__p_cert_syms, buf, &success);
- if (!success) {
- cert_type = wordtouint32(buf);
- if (wordtouint32_error || cert_type > 0xFFFF)
- ERRTO("CERT type out of range");
- }
- if (i + INT16SZ > data_size)
- ERRTO("CERT no space");
- PUTSHORT((u_int16_t)cert_type, cp);
- i += INT16SZ;
-
- if (!getmlword((char*)buf, buf_len, fp, 0))
- ERRTO("CERT doesn't specify type");
-
- key_tag = wordtouint32(buf);
- if (wordtouint32_error || key_tag > 0xFFFF)
- ERRTO("CERT KEY tag out of range");
-
- if (i + INT16SZ > data_size)
- ERRTO("CERT no space");
- PUTSHORT((u_int16_t)key_tag, cp);
- i += INT16SZ;
-
- if (!getmlword(buf, buf_len, fp, 0))
- ERRTO("CERT missing algorithm ID");
-
- alg = sym_ston(__p_key_syms, buf, &success);
- if (!success) {
- alg = wordtouint32(buf);
- if (wordtouint32_error || alg > 0xFF)
- ERRTO("CERT KEY alg out of range");
- }
- if (i + 1 > data_size)
- ERRTO("CERT no space");
- data[i++] = (u_char)alg;
-
- if (!getallwords(buf, buf_len, fp, 0)) {
- certlen = 0;
- }
- else {
- cp = &data[i];
- certlen = b64_pton(buf, (u_char*)cp, data_size - i);
- if (certlen < 0)
- ERRTO("CERT blob has encoding error");
- }
- /* set total length */
- n = i + certlen;
- return (n);
- err:
- *errmsg = errtype;
- return (-1);
-
-}
-
-static int
-parse_key_rr(char *buf, int buf_len, u_char *data, int data_size,
- FILE *fp, const char **errmsg)
-{
- /* The KEY record looks like this in the db file:
- * Name Cl KEY Flags Proto Algid PublicKeyData
- * where:
- * Name,Cl per usual
- * KEY RR type
- * Flags 4 digit hex value (unsigned_16)
- * Proto 8 bit u_int
- * Algid 8 bit u_int
- * PublicKeyData
- * a string of base64 digits,
- * skipping any embedded whitespace.
- */
- u_int32_t al, pr;
- int nk, klen,i, n;
- u_int32_t keyflags;
- const char *errtype = "KEY error";
- u_char *cp, *expstart;
- u_int expbytes, modbytes;
-
- i = n = 0;
- data[i] = '\0';
- cp = data;
- getmlword_nesting = 0; /* KLUDGE err recov. */
-
- /*>>> Flags (unsigned_16) */
- keyflags = wordtouint32(buf);
- if (wordtouint32_error || 0xFFFF < keyflags)
- ERRTO("KEY flags error");
- if (keyflags & NS_KEY_RESERVED_BITMASK)
- ERRTO("KEY Reserved Flag Bit");
- PUTSHORT(keyflags, cp);
-
- /*>>> Protocol (8-bit decimal) */
- if (!getmlword((char*)buf, buf_len, fp, 0))
- ERRTO("KEY Protocol Field");
- pr = wordtouint32(buf);
- if (wordtouint32_error || 255 < pr)
- ERRTO("KEY Protocol Field");
- *cp++ = (u_char) pr;
-
- /*>>> Algorithm id (8-bit decimal) */
- if (!getmlword((char*)buf, buf_len, fp, 0))
- ERRTO("KEY Algorithm ID");
- al = wordtouint32(buf);
- if (wordtouint32_error || 0 == al || 255 == al || 255 < al)
- ERRTO("KEY Algorithm ID");
- *cp++ = (u_char) al;
-
- /*>>> Extended KEY flag field in bytes 5 and 6 */
- if (NS_KEY_EXTENDED_FLAGS & keyflags) {
- u_int32_t keyflags2;
-
- if (!getmlword((char*)buf, buf_len, fp, 0))
- ERRTO("KEY Flags Field");
- keyflags2 = wordtouint32(buf);
- if (wordtouint32_error || 0xFFFF < keyflags2)
- ERRTO("Extended key flags error");
- if (keyflags2 & NS_KEY_RESERVED_BITMASK2)
- ERRTO("KEY Reserved Flag2 Bit");
- PUTSHORT(keyflags2, cp);
- }
-
- /*>>> Public Key data is in BASE64.
- * We don't care what algorithm it uses or what
- * the internal structure of the BASE64 data is.
- */
- if (!getallwords(buf, MAXDATA, fp, 0))
- klen = 0;
- else {
- /* Convert from BASE64 to binary. */
- klen = b64_pton(buf, (u_char*)cp,
- data_size - (cp - data));
- if (klen < 0)
- ERRTO("KEY Public Key");
- }
-
- /* set total length */
- n = klen + (cp - data);
-
- /*
- * Now check for valid key flags & algs & etc, from the RFC.
- */
-
- if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK))
- nk = 1; /* No-key */
- else
- nk = 0; /* have a key */
-
- if ((keyflags & (NS_KEY_NAME_TYPE | NS_KEY_TYPEMASK)) ==
- (NS_KEY_NAME_ZONE | NS_KEY_TYPE_CONF_ONLY))
- /* Zone key must have Auth bit set. */
- ERRTO("KEY Zone Key Auth. bit");
-
- if (al == 0 && nk == 0)
- ERRTO("KEY Algorithm");
- if (al != 0 && pr == 0)
- ERRTO("KEY Protocols");
-
- if (nk == 1 && klen != 0)
- ERRTO("KEY No-Key Flags Set");
-
- if (nk == 0 && klen == 0)
- ERRTO("KEY Type Spec'd");
-
- /*
- * Check algorithm-ID and key structure, for the algorithm-ID's
- * that we know about.
- */
- switch (al) {
- case NS_ALG_MD5RSA:
- if (klen == 0)
- break;
- expstart = cp;
- expbytes = *expstart++;
- if (expbytes == 0)
- GETSHORT(expbytes, expstart);
-
- if (expbytes < 1)
- ERRTO("Exponent too short");
- if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
- ERRTO("Exponent too long");
- if (*expstart == 0)
- ERRTO("Exponent w/ 0");
-
- modbytes = klen - (expbytes + (expstart - cp));
- if (modbytes < (NS_MD5RSA_MIN_BITS + 7) / 8)
- ERRTO("Modulus too short");
- if (modbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
- ERRTO("Modulus too long");
- if (*(expstart+expbytes) == 0)
- ERRTO("Modulus starts w/ 0");
- break;
-
- case NS_ALG_DH: {
- u_char *dh_cp;
- u_int16_t dh_len, plen, glen, ulen;
-
- dh_cp = (u_char *)cp;
- GETSHORT(plen, dh_cp);
- if(plen < 16)
- ERRTO("DH short plen");
- dh_len = 2 + plen;
- if(dh_len > klen)
- ERRTO("DH plen > klen");
-
- GETSHORT(glen, dh_cp);
- if(glen <= 0 || glen > plen)
- ERRTO("DH glen bad");
- dh_len = 2 + glen;
- if(dh_len > klen)
- ERRTO("DH glen > klen");
-
- GETSHORT(ulen, dh_cp);
- if(ulen <= 0 || ulen > plen)
- ERRTO("DH ulen bad");
- dh_len = 2 + ulen;
- if(dh_len > klen)
- ERRTO("DH ulen > klen");
- else if (dh_len < klen)
- ERRTO("DH *len < klen");
- break;
- }
-
- case NS_ALG_DSA: {
- u_int8_t t;
-
- if ( klen == 0)
- break;
- t = *cp;
- if (t > 8)
- ERRTO("DSA T value");
- if (klen != (1 + 20 + 3 *(64+8*t)))
- ERRTO("DSA length");
- break;
- }
-
- case NS_ALG_PRIVATE_OID:
- if (klen == 0)
- ERRTO("No ObjectID in key");
- break;
- default:
- ERRTO("Unknown Key algorithm");
- }
-
- endline(fp); /* flush the rest of the line */
- return (n);
- err:
- *errmsg = errtype;
- return (-1);
-} /*T_KEY*/
-
-/*
- * function to invoke DNSSEC specific parsing routines.
- * this is simpler than copying these complicated blocks into the
- * multiple souce files that read files (ixfr, nsupdate etc..).
- * this code should be in a library rather than in this file but
- * what the heck for now (ogud@tislabs.com)
- */
-int
-parse_sec_rdata(char *buf, int buf_len, int buf_full, u_char *data,
- int data_size, FILE *fp, struct zoneinfo *zp,
- char *domain, u_int32_t ttl, int type, enum context context,
- enum transport transport, const char **errmsg)
-{
- int ret = -1;
-
- getmlword_nesting = 0; /* KLUDGE err recov. */
- if (!buf_full && buf && buf_len != 0) /* check if any data in buf */
- if (!getmlword(buf, buf_len, fp, 1)) {
- *errmsg = "unexpected end of input";
- goto err;
- }
-
- switch (type) {
- case ns_t_sig:
- ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp,
- domain, ttl, context, transport, errmsg);
- break;
- case ns_t_key:
- ret = parse_key_rr(buf, buf_len, data, data_size, fp, errmsg);
- break;
- case ns_t_nxt:
- ret = parse_nxt_rr(buf, data, data_size, fp, zp,
- domain, context, transport, errmsg);
- break;
- case ns_t_cert:
- ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg);
- break;
- default:
- ret = -1;
- *errmsg = "parse_sec_rdata():Unsupported SEC type type";
- goto err;
- }
- return (ret);
- err:
- endline(fp);
- return (ret);
-}