1 #if !defined(lint) && !defined(SABER)
2 static const char sccsid[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
3 static const char rcsid[] = "$Id: db_load.c,v 8.97 1999/10/30 03:21:35 vixie Exp $";
7 * Copyright (c) 1986, 1988, 1990
8 * The Regents of the University of California. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
42 * Permission to use, copy, modify, and distribute this software for any
43 * purpose with or without fee is hereby granted, provided that the above
44 * copyright notice and this permission notice appear in all copies, and that
45 * the name of Digital Equipment Corporation not be used in advertising or
46 * publicity pertaining to distribution of the document or software without
47 * specific, written prior permission.
49 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
50 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
52 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
53 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
54 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
55 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
60 * Portions Copyright (c) 1995 by International Business Machines, Inc.
62 * International Business Machines, Inc. (hereinafter called IBM) grants
63 * permission under its copyrights to use, copy, modify, and distribute this
64 * Software with or without fee, provided that the above copyright notice and
65 * all paragraphs of this notice appear in all copies, and that the name of IBM
66 * not be used in connection with the marketing of any product incorporating
67 * the Software or modifications thereof, without specific, written prior
70 * To the extent it has a right to do so, IBM grants an immunity from suit
71 * under its patents, if any, for the use, sale or manufacture of products to
72 * the extent that such products are used for performing Domain Name System
73 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
74 * granted for any product per se or for any other function of any product.
76 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
77 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
78 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
79 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
80 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
81 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
85 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
87 * Permission to use, copy, modify, and distribute this software for any
88 * purpose with or without fee is hereby granted, provided that the above
89 * copyright notice and this permission notice appear in all copies.
91 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
92 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
93 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
94 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
95 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
96 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
97 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
102 * Load zone from ASCII file on local host. Format similar to RFC 883.
107 #include "port_before.h"
109 #include <sys/types.h>
110 #include <sys/param.h>
111 #include <sys/stat.h>
112 #include <sys/socket.h>
115 #include <netinet/in.h>
116 #include <arpa/nameser.h>
117 #include <arpa/inet.h>
130 #include <isc/eventlib.h>
131 #include <isc/logging.h>
132 #include <isc/memcluster.h>
134 #include "port_after.h"
140 static int gettoken(FILE *, const char *);
141 static int getcharstring(char *, char *, int, int, int, FILE *,
143 static int genname(char *, int, const char *, char *, int);
144 static int getmlword(char *, size_t, FILE *, int);
145 static int getallwords(char *, size_t, FILE *, int);
146 static u_int32_t wordtouint32(char *);
147 static void fixup_soa(const char *fn, struct zoneinfo *zp);
148 static int get_nxt_types(u_char *, FILE *, const char *);
150 static int parse_sig_rr(char *, int, u_char *, int, FILE *,
151 struct zoneinfo *, char *, u_int32_t ,
152 enum context , enum transport , char **);
153 static int parse_key_rr(char *, int, u_char *, int, FILE *,
154 struct zoneinfo *, char *, enum context,
155 enum transport, char **);
157 static int parse_cert_rr(char *, int, u_char *, int, FILE *, char **);
158 static int parse_nxt_rr(char *, int, u_char *, int, FILE *,
159 struct zoneinfo *, char *, enum context,
160 enum transport, char **);
163 static int wordtouint32_error = 0;
164 static int empty_token = 0;
165 static int getmlword_nesting = 0;
169 static int clev; /* a zone deeper in a hierarchy has more credibility */
172 * Parser token values
184 #define MAKENAME_OK(N) \
186 if (!makename_ok(N, origin, class, zp, \
187 transport, context, \
188 domain, filename, lineno, \
189 data_size - ((u_char*)N - data))) { \
191 sprintf(buf, "bad name \"%s\"", N); \
196 #define MAKENAME_OKZP(N, SI) \
198 if (!makename_ok(N, zp->z_origin, zp->z_class, zp, \
199 transport, context, \
200 domain, zp->z_source, lineno, \
201 SI - ((u_char*)N - data))) { \
203 sprintf(buf, "bad name \"%s\"", N); \
208 #define RANGE(x, min, max) \
209 (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
214 * db_load(filename, in_origin, zp, def_domain, isixfr)
215 * load a database from `filename' into zone `zp'. append `in_origin'
216 * to all nonterminal domain names in the file. `def_domain' is the
217 * default domain for include files or NULL for zone base files.
219 * -1 = can't open file
221 * >0 = number of errors encountered
224 db_load(const char *filename, const char *in_origin,
225 struct zoneinfo *zp, const char *def_domain, int isixfr)
227 static int read_soa, read_ns, rrcount;
228 static u_int32_t default_ttl, default_warn;
229 static struct filenames {
230 struct filenames *next;
234 const char *errtype = "Database";
236 char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME];
238 char genlhs[MAXDNAME], genrhs[MAXDNAME];
239 u_char data[MAXDATA];
240 int data_size = sizeof(data);
241 int c, someclass, class, type, dbflags, dataflags, multiline = 0;
242 int slineno, i, errs, didinclude, ininclude, escape, success;
243 u_int32_t ttl, n, serial;
249 enum transport transport;
250 enum context context;
251 struct sockaddr_in empty_from;
252 int genstart, genend, genstep;
256 empty_from.sin_family = AF_INET;
257 empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
258 empty_from.sin_port = htons(0);
261 * We use an 'if' inside of the 'do' below because otherwise the Solaris
262 * compiler detects that the 'while' is never executed because of the 'goto'
265 #define ERRTO(msg) do { if (1) { errtype = msg; goto err; } } while (0)
266 #define ERRTOZ(msg) do { if (1) { errtype = msg; buf[0] = '\0'; goto err; } } while (0)
268 switch (zp->z_type) {
271 transport = primary_trans;
275 transport = secondary_trans;
278 transport = response_trans;
281 transport = response_trans; /*guessing*/
286 ininclude = (def_domain != NULL);
291 default_ttl = USE_MINIMUM;
293 clev = nlabels(in_origin);
298 ns_debug(ns_log_load, 1, "db_load(%s, %s, %d, %s, %s)",
299 filename, in_origin, zp - zones,
300 def_domain ? def_domain : "Nil", isixfr ? "IXFR" : "Normal");
302 fn = (struct filenames *)memget(sizeof *filenames);
304 ns_panic(ns_log_db, 0, "db_load: memget failed");
305 thisfile = fn->name = savestr(filename, 1);
306 fn->next = filenames;
309 strcpy(origin, in_origin);
310 if ((fp = fopen(filename, "r")) == NULL) {
311 ns_warning(ns_log_load, "db_load could not open: %s: %s",
312 filename, strerror(errno));
316 if (zp->z_type == Z_HINT) {
317 dbflags = DB_NODATA | DB_NOHINTS;
318 dataflags = DB_F_HINT;
320 } else if (zp->z_type == Z_STUB && clev == 0) {
321 dbflags = DB_NODATA | DB_NOHINTS;
322 dataflags = DB_F_HINT;
329 if (fstat(fileno(fp), &sb) < 0) {
330 ns_warning(ns_log_load, "fstat failed: %s: %s",
331 filename, strerror(errno));
332 sb.st_mtime = (int)tt.tv_sec;
337 strcpy(domain, def_domain);
341 zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD);
342 while ((c = gettoken(fp, filename)) != EOF) {
349 if (!getword(buf, sizeof buf, fp, 0))
352 if (!getword(tmporigin, sizeof(tmporigin), fp, 1))
353 strcpy(tmporigin, origin);
355 if (makename(tmporigin, origin,
356 sizeof(tmporigin)) == -1)
357 ERRTO("$INCLUDE makename failed");
361 errs += db_load(buf, tmporigin, zp, domain, ISNOTIXFR);
365 (void) strcpy(buf, origin);
366 if (!getword(origin, sizeof(origin), fp, 1))
368 ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s",
370 if (makename(origin, buf, sizeof(origin)) == -1)
371 ERRTO("$ORIGIN makename failed");
372 ns_debug(ns_log_load, 3, "db_load: origin now %s",
377 if (!getword(buf, sizeof(buf), fp, 0))
378 ERRTOZ("$GENERATE missing RANGE");
379 n = sscanf(buf, "%d-%d/%d", &genstart, &genend,
381 if (n != 2 && n != 3)
382 ERRTO("$GENERATE invalid range");
385 if ((genend < genstart) || (genstart < 0) ||
387 ERRTO("$GENERATE invalid range");
388 if (!getword(genlhs, sizeof(genlhs), fp, 2))
389 ERRTOZ("$GENERATE missing LHS");
390 if (!getword(buf, sizeof(buf), fp, 0))
391 ERRTOZ("GENERATE missing TYPE");
392 type = sym_ston(__p_type_syms, buf, &success);
393 if (success == 0 || type == ns_t_any) {
395 "%s: Line %d: $GENERATE unknown type: %s.",
396 filename, lineno, buf);
409 ERRTO("$GENERATE unsupported type");
411 if (!getword(genrhs, sizeof(genrhs), fp, 2))
412 ERRTOZ("$GENERATE missing RHS");
413 for (i = genstart; i <= genend; i += genstep) {
414 if (genname(genlhs, i, origin, domain,
415 sizeof domain) == -1)
416 ERRTOZ("$GENERATE genname LHS failed");
417 context = ns_ownercontext(type, transport);
418 if (!ns_nameok(NULL, domain, class, zp, transport,
419 context, domain, inaddr_any)) {
421 ERRTO("$GENERATE owner name error");
427 if (genname(genrhs, i, origin, (char *)data,
429 ERRTOZ("$GENERATE genname RHS failed");
432 context = hostname_ctx;
435 context = ns_ptrcontext(domain);
438 context = domain_ctx;
441 if (!ns_nameok(NULL, (char *)data, class, zp,
443 domain, inaddr_any)) {
444 strncpy(buf, domain, sizeof(buf));
445 buf[sizeof(buf)-1] = '\0';
446 ERRTO("$GENERATE name error");
448 n = strlen((char *)data) + 1;
452 if (genname(genrhs, i, NULL, (char *)data,
454 ERRTOZ("$GENERATE genname RHS failed");
455 strncpy(buf, (char*)data, sizeof(buf));
456 buf[sizeof(buf)-1] = '\0';
459 if (!inet_aton(buf, &ina))
461 (void) ina_put(ina, data);
465 if (inet_pton(AF_INET6, buf, data) <= 0)
466 ERRTO("IPv6 Address");
472 ERRTOZ("$GENERATE unsupported context");
474 dp = savedata(class, type, (u_int32_t)ttl,
475 (u_char *)data, (int)n);
476 dp->d_zone = zp - zones;
477 dp->d_flags = dataflags;
478 dp->d_cred = DB_C_ZONE;
480 c = db_set_update(domain, dp, &state, dbflags,
481 (dataflags & DB_F_HINT) != 0 ?
482 &fcachetab : &hashtab,
483 empty_from, &rrcount, lineno,
486 if (c == CNAMEANDOTHER)
494 if (!getword(domain, sizeof(domain), fp, 1))
496 if (makename(domain, origin, sizeof(domain)) == -1)
497 ERRTO("ownername makename failed");
501 if (getttl(fp, filename, lineno, &n,
502 &multiline) <= 0 || n > MAXIMUM_TTL) {
503 ERRTO("$TTL bad TTL value");
505 ttl = default_ttl = n;
509 (void) strcpy(domain, origin);
517 if (!getword(buf, sizeof buf, fp, 0)) {
522 if (ns_parse_ttl(buf, &tmplong) < 0) {
523 if (zp->z_type == z_master &&
525 (default_ttl == USE_MINIMUM)) {
526 ns_warning(ns_log_load,
527 "Zone \"%s\" (file %s): %s",
528 zp->z_origin, filename,
529 "No default TTL set using SOA minimum instead");
532 ttl = (u_int32_t)default_ttl;
535 if (ttl > MAXIMUM_TTL) {
537 "%s: Line %d: TTL > %u; converted to 0",
538 filename, lineno, MAXIMUM_TTL);
541 if (zp->z_type == Z_CACHE) {
543 * This allows the cache entry to age
544 * while sitting on disk (powered off).
546 if (ttl > max_cache_ttl)
550 if (!getword(buf, sizeof buf, fp, 0))
554 /* Parse class (IN, etc) */
555 someclass = sym_ston(__p_class_syms, buf, &success);
556 if (success && someclass != zp->z_class) {
558 "%s: Line %d: wrong class: %s.",
564 if (success && someclass != C_ANY) {
566 (void) getword(buf, sizeof buf, fp, 0);
569 /* Parse RR type (A, MX, etc) */
570 type = sym_ston(__p_type_syms, buf, &success);
571 if (success == 0 || type == ns_t_any) {
573 "%s: Line %d: Unknown type: %s.",
574 filename, lineno, buf);
578 if (ttl == USE_MINIMUM)
580 context = ns_ownercontext(type, transport);
581 if (!ns_nameok(NULL, domain, class, zp, transport, context,
582 domain, inaddr_any)) {
584 ns_notice(ns_log_load,
585 "%s:%d: owner name error",
589 context = domain_ctx;
596 * Don't do anything here for these types --
597 * they read their own input separately later.
615 if (!getword(buf, sizeof buf, fp, escape))
617 ns_debug(ns_log_load, 3,
618 "d='%s', c=%d, t=%d, ttl=%u, data='%s'",
619 domain, class, type, ttl, buf);
621 * Convert the ascii data 'buf' to the proper format
622 * based on the type and pack into 'data'.
627 if (!inet_aton(buf, &ina))
629 (void) ina_put(ina, data);
634 context = hostname_ctx;
638 context = mailname_ctx;
641 (void) strcpy((char *)data, buf);
643 MAKENAME_OK((char *)data);
644 cp = (char *)(data + strlen((char *)data) + 1);
649 ERRTO("Domain Name");
651 context = domain_ctx;
653 context = mailname_ctx;
655 cp += strlen((char *)cp) + 1;
656 if (type != ns_t_soa) {
657 n = cp - (char *)data;
660 if (ns_samename(zp->z_origin, domain) != 1) {
662 ns_error(ns_log_load,
663 "%s:%d: SOA for \"%s\" not at zone top \"%s\"",
664 filename, lineno, domain,
667 c = getnonblank(fp, filename);
674 serial = zp->z_serial;
675 zp->z_serial = getnum(fp, filename,
679 n = (u_int32_t) zp->z_serial;
682 SEQ_GT(serial, zp->z_serial)) {
683 ns_notice(ns_log_load,
684 "%s:%d: WARNING: new serial number < old (%lu < %lu)",
686 zp->z_serial, serial);
688 if (getttl(fp, filename, lineno, &n,
694 zp->z_refresh = RANGE(n, MIN_REFRESH,
696 if (zp->z_type == Z_SECONDARY
698 || zp->z_type == Z_STUB
701 ns_refreshtime(zp, MIN(sb.st_mtime,
703 sched_zone_maint(zp);
706 if ((zp->z_type == Z_PRIMARY) &&
707 (zp->z_flags & Z_DYNAMIC))
708 if ((u_int32_t)zp->z_soaincrintvl >
711 "zone soa update time truncated to 1/3rd of refresh time");
717 if (getttl(fp, filename, lineno, &n,
723 zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY);
724 if (getttl(fp, filename, lineno,
725 &n, &multiline) <= 0) {
730 zp->z_expire = RANGE(n, zp->z_refresh,
732 if (getttl(fp, filename, lineno, &n,
738 if (n > MAXIMUM_TTL) {
740 "%s: Line %d: SOA minimum TTL > %u; converted to 0",
741 filename, lineno, MAXIMUM_TTL);
745 if (default_ttl == USE_MINIMUM)
747 n = cp - (char *)data;
749 buf[0] = getnonblank(fp, filename);
756 if (zp->z_type == Z_PRIMARY)
757 fixup_soa(filename, zp);
762 if (!inet_aton(buf, &ina))
763 ERRTO("WKS IP Address");
764 (void) ina_put(ina, data);
766 data[INADDRSZ] = getprotocol(fp, filename);
768 n = getservices(NS_INT32SZ + sizeof(char),
769 (char *)data, fp, filename);
773 if (ns_samename(zp->z_origin, domain) == 1)
775 context = hostname_ctx;
781 context = domain_ctx;
784 context = ns_ptrcontext(domain);
786 (void) strcpy((char *)data, buf);
787 MAKENAME_OK((char *)data);
788 n = strlen((char *)data) + 1;
792 /* Order Preference Flags Service Replacement Regexp */
797 n = n * 10 + (*cp++ - '0');
798 /* catch bad values */
799 if (cp == buf || n > 65535)
800 ERRTO("NAPTR Order");
802 PUTSHORT((u_int16_t)n, cp);
805 n = getnum(fp, filename, GETNUM_NONE);
806 if (getnum_error || n > 65536)
807 ERRTO("NAPTR Preference");
808 PUTSHORT((u_int16_t)n, cp);
811 if (!getword(buf, sizeof buf, fp, 0))
812 ERRTO("NAPTR Flags");
815 ERRTO("NAPTR Flags too big");
817 memcpy(cp, buf, (int)n);
820 /* Service Classes */
821 if (!getword(buf, sizeof buf, fp, 0))
822 ERRTO("NAPTR Service Classes");
825 ERRTO("NAPTR Service Classes too big");
827 memcpy(cp, buf, (int)n);
831 if (!getword(buf, sizeof buf, fp, 0))
832 ERRTO("NAPTR Pattern");
835 ERRTO("NAPTR Pattern too big");
837 memcpy(cp, buf, (int)n);
841 if (!getword(buf, sizeof buf, fp, 1))
842 ERRTO("NAPTR Replacement");
844 if (n > data_size - ((u_char *)cp - data))
845 ERRTO("NAPTR Replacement too big");
846 (void) strcpy((char *)cp, buf);
847 context = domain_ctx;
849 /* advance pointer to end of data */
850 cp += strlen((char *)cp) +1;
852 /* now save length */
853 n = (cp - (char *)data);
864 n = n * 10 + (*cp++ - '0');
865 /* catch bad values */
866 if ((cp == buf) || (n > 65535))
869 PUTSHORT((u_int16_t)n, cp);
871 if (type == ns_t_srv) {
872 n = getnum(fp, filename, GETNUM_NONE);
873 if (getnum_error || n > 65536)
875 PUTSHORT((u_int16_t)n, cp);
877 n = getnum(fp, filename, GETNUM_NONE);
878 if (getnum_error || n > 65536)
880 PUTSHORT((u_int16_t)n, cp);
883 if (!getword(buf, sizeof buf, fp, 1))
884 ERRTO("Domain Name");
885 (void) strcpy((char *)cp, buf);
886 context = hostname_ctx;
888 /* advance pointer to end of data */
889 cp += strlen((char *)cp) +1;
891 /* now save length */
892 n = (cp - (char *)data);
896 context = domain_ctx;
901 n = n * 10 + (*cp++ - '0');
902 /* catch bad values */
903 if ((cp == buf) || (n > 65535))
904 ERRTO("PX Priority");
906 PUTSHORT((u_int16_t)n, cp);
908 if (!getword(buf, sizeof buf, fp, 0))
910 (void) strcpy((char *)cp, buf);
912 /* advance pointer to next field */
913 cp += strlen((char *)cp) + 1;
914 if (!getword(buf, sizeof buf, fp, 0))
916 (void) strcpy((char *)cp, buf);
918 /* advance pointer to end of data */
919 cp += strlen((char *)cp) + 1;
921 /* now save length */
922 n = (cp - (char *)data);
926 n = getcharstring(buf, (char *)data, type,
933 n = getcharstring(buf, (char *)data, type,
940 n = getcharstring(buf, (char *)data, type,
948 n = getcharstring(buf, (char *)data, type,
955 n = inet_nsap_addr(buf, (u_char *)data,
963 if (inet_pton(AF_INET6, buf, data) <= 0)
964 ERRTO("IPv4 Address");
974 int ret = parse_sec_rdata(buf, sizeof(buf), 0,
990 cp = buf + (n = strlen(buf));
994 while ((i = getc(fp), *cp = i, i != EOF)
999 if (*cp == '\n') /* leave \n for getword */
1002 /* now process the whole line */
1003 n = loc_aton(buf, (u_char *)data);
1014 * Ignore data outside the zone.
1016 if (zp->z_type != Z_CACHE &&
1017 !ns_samedomain(domain, zp->z_origin))
1019 ns_info(ns_log_load,
1020 "%s:%d: data \"%s\" outside zone \"%s\" (ignored)",
1021 filename, lineno, domain,
1025 dp = savedata(class, type, (u_int32_t)ttl,
1026 (u_char *)data, (int)n);
1027 dp->d_zone = zp - zones;
1028 dp->d_flags = dataflags;
1029 dp->d_cred = DB_C_ZONE;
1031 c = db_set_update(domain, dp, &state, dbflags,
1032 (dataflags & DB_F_HINT) != 0 ?
1033 &fcachetab : &hashtab,
1034 empty_from, &rrcount, lineno,
1036 if (c == CNAMEANDOTHER)
1045 ns_notice(ns_log_load, "%s:%d: %s error near (%s)",
1046 filename, empty_token ? (lineno - 1) : lineno,
1051 c = db_set_update(NULL, NULL, &state, dbflags,
1052 (dataflags & DB_F_HINT) ? &fcachetab : &hashtab,
1053 empty_from, &rrcount, lineno, filename);
1055 if (c == CNAMEANDOTHER)
1059 (void) my_fclose(fp);
1063 zp->z_flags |= Z_INCLUDE;
1066 zp->z_ftime = sb.st_mtime;
1067 zp->z_lastupdate = sb.st_mtime;
1068 if (zp->z_type != Z_CACHE && zp->z_type != Z_HINT) {
1069 const char *msg = NULL;
1072 msg = "no SOA RR found";
1073 else if (read_soa != 1)
1074 msg = "multiple SOA RRs found";
1075 else if (read_ns == 0)
1076 msg = "no NS RRs found at zone top";
1078 msg = "no relevant RRs found";
1081 ns_warning(ns_log_load,
1082 "Zone \"%s\" (file %s): %s",
1083 zp->z_origin, filename, msg);
1088 filenames = filenames->next;
1090 memput(fn, sizeof *fn);
1093 ns_warning(ns_log_load,
1094 "%s zone \"%s\" (%s) rejected due to errors (serial %u)",
1095 zoneTypeString(zp->z_type), zp->z_origin,
1096 p_class(zp->z_class), zp->z_serial);
1098 ns_info(ns_log_load,
1099 "%s zone \"%s\" (%s) loaded (serial %u)",
1100 zoneTypeString(zp->z_type), zp->z_origin,
1101 p_class(zp->z_class), zp->z_serial);
1104 zp->z_flags |= Z_DB_BAD;
1108 if (errs == 0 && (!ininclude) &&
1109 (zp->z_type == z_master || zp->z_type == z_slave))
1110 ns_notify(zp->z_origin, zp->z_class, ns_t_soa);
1116 db_err(int err, char *domain, int type, const char *filename, int lineno) {
1117 if (filename != NULL && err == CNAMEANDOTHER)
1118 ns_notice(ns_log_load, "%s:%d:%s: CNAME and OTHER data error",
1119 filename, lineno, domain);
1120 if (err != DATAEXISTS)
1121 ns_debug(ns_log_load, 1, "update failed %s %d",
1126 gettoken(FILE *fp, const char *src) {
1138 if (getword(op, sizeof op, fp, 0)) {
1139 if (!strcasecmp("include", op))
1141 if (!strcasecmp("origin", op))
1143 if (!strcasecmp("generate", op))
1145 if (!strcasecmp("ttl", op))
1146 return (DEFAULTTTL);
1148 ns_notice(ns_log_db,
1149 "%s:%d: Unknown $ option: $%s",
1154 while ((c = getc(fp)) != EOF && c != '\n')
1173 if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0)
1177 (void) ungetc(c, fp);
1184 * getword(buf, size, fp, preserve)
1185 * get next word, skipping blanks & comments.
1186 * '\' '\n' outside of "quotes" is considered a blank.
1189 * size - of destination
1190 * fp - file to read from
1191 * preserve - should we preserve \ before \\ and \.?
1192 * if preserve == 2, then keep all \
1194 * 0 = no word; perhaps EOL or EOF; lineno was incremented.
1198 getword(char *buf, size_t size, FILE *fp, int preserve) {
1200 int c, spaceok, once;
1202 empty_token = 0; /* XXX global side effect. */
1204 while ((c = getc(fp)) != EOF) {
1207 /* Comment. Skip to end of line. */
1208 while ((c = getc(fp)) != EOF && c != '\n')
1214 * Unescaped newline. It's a terminator unless we're
1215 * already midway into a token.
1224 /* "Quoted string." Gather the whole string here. */
1225 while ((c = getc(fp)) != EOF && c!='"' && c!='\n') {
1227 if ((c = getc(fp)) == EOF)
1246 if (cp >= buf+size-1)
1253 if (cp >= buf+size-1)
1258 * Newline string terminators are
1259 * not token terminators.
1265 /* Sample following character, check for terminator. */
1266 if ((c = getc(fp)) != EOF)
1268 if (c == EOF || isspace(c)) {
1276 /* Do escape processing. */
1277 if ((c = getc(fp)) == EOF)
1296 if (cp >= buf+size-1)
1300 if (c == ' ' || c == '\t')
1303 if (isspace(c) && !spaceok) {
1304 /* Blank of some kind. Skip run. */
1305 while (isspace(c = getc(fp)) && c != '\n')
1308 /* Blank means terminator if the token is nonempty. */
1309 if (cp != buf) /* Trailing whitespace */
1311 continue; /* Leading whitespace */
1313 if (cp >= buf + size - 1)
1327 * getttl(fp, fn, ln, ttl, multiline)
1328 * read a word from the file and parse it as a TTL.
1331 * 0 word not read (EOF or EOL?)
1332 * -1 word read but it wasn't a ttl
1334 * *ttl is written if the return value is to be 1.
1337 getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) {
1343 while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline)
1346 if (*multiline && len && buf[len-1] == ')') {
1350 if (ns_parse_ttl(buf, &tmp) < 0) {
1351 ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"",
1356 ch = getnonblank(fp, fn);
1364 *ttl = (u_int32_t)tmp;
1368 /* Get multiline words. Same parameters as getword. Handles any
1369 number of leading ('s or )'s in the words it sees.
1370 FIXME: We kludge recognition of ( and ) for multiline input.
1371 Each paren must appear at the start of a (blank-separated) word,
1372 which is particularly counter-intuitive for ). Good enough for now,
1373 until Paul rewrites the parser. (gnu@toad.com, oct96)
1376 getmlword(char *buf, size_t size, FILE *fp, int preserve) {
1380 while (!getword (buf, size, fp, preserve)) {
1381 /* No more words on this line. See if doing the
1383 if (!getmlword_nesting) { /* Nope... */
1384 ungetc('\n', fp); /* Push back newline */
1385 lineno--; /* Unbump the lineno */
1386 empty_token = 0; /* Undo this botch */
1389 if (feof(fp) || ferror(fp))
1390 return 0; /* Error, no terminating ')' */
1391 /* Continue reading til we get a word... */
1393 while ('(' == *buf) {
1394 /* Word starts with paren. Multiline mode.
1395 Move the rest of the word down over the paren. */
1396 getmlword_nesting++;
1398 while (0 != (p[0]=p[1])) p++;
1400 while (')' == *buf) {
1401 getmlword_nesting--;
1403 while (0 != (p[0]=p[1])) p++;
1405 } while (buf[0] == 0); /* loop til we get a non-( non-) word */
1407 return 1; /* Got a word... */
1410 /* Get all the remaining words on a line, concatenated into one big
1411 long (not too long!) string, with the whitespace squeezed out.
1412 This routine, like getword(), does not swallow the newline if words seen.
1413 This routine, unlike getword(), never swallows the newline if no words.
1414 Parameters are the same as getword(). Result is:
1415 0 got no words at all
1416 1 got one or more words
1417 -1 got too many words, they don't all fit; or missing close paren
1420 getallwords(char *buf, size_t size, FILE *fp, int preserve) {
1421 char *runningbuf = buf;
1422 int runningsize = size;
1425 while (runningsize > 0) {
1426 if (!getmlword (runningbuf, runningsize, fp, preserve)) {
1427 return runningbuf!=buf; /* 1 or 0 */
1429 len = strlen(runningbuf);
1433 return -1; /* Error, String too long */
1437 getnum(FILE *fp, const char *src, int opt) {
1440 int seendecimal = 0;
1445 #ifdef DOTTED_SERIAL
1446 if (opt & GETNUM_SERIAL)
1449 for (n = 0; (c = getc(fp)) != EOF; ) {
1458 while ((c = getc(fp)) != EOF && c != '\n')
1469 if (c == ')' && seendigit) {
1470 (void) ungetc(c, fp);
1473 if (seendigit && (opt & GETNUM_SCALED) &&
1474 strchr("KkMmGg", c) != NULL) {
1483 n *= (1024 * 1024 * 1024);
1488 if (seendecimal || c != '.' || !allow_dots) {
1489 ns_notice(ns_log_db,
1490 "%s:%d: expected a number",
1496 #ifdef SENSIBLE_DOTS
1506 #ifdef SENSIBLE_DOTS
1508 m = m * 10 + (c - '0');
1510 n = n * 10 + (c - '0');
1512 n = n * 10 + (c - '0');
1520 "%s:%d: number after the decimal point exceeds 9999",
1527 "%s:%d: decimal serial number interpreted as %d",
1537 getnonblank(FILE *fp, const char *src) {
1540 while ((c = getc(fp)) != EOF) {
1547 while ((c = getc(fp)) != EOF && c != '\n')
1555 ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno);
1560 * Replace all single "$"'s in "name" with "it".
1561 * ${delta} will add delta to "it" before printing.
1562 * ${delta,width} will change print width as well, zero fill is implied
1563 * ${delta,width,radix} will change radix as well, can be d, o, x, X.
1564 * i.e. ${0,2,X} will produce a two digit hex (upper case) with zero fill.
1565 * Append "origin" to name if required and validate result with makename.
1566 * To get a "$" or "{" in the output use \ before it.
1567 * Return 0 on no error or -1 on error.
1568 * Resulting name stored in "buf".
1572 genname(char *name, int it, const char *origin, char *buf, int size) {
1574 char *eom = buf + size;
1583 if (*(++name) == '$') {
1584 /* should be deprecated. how? */
1591 switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) {
1595 sprintf(fmt, "%%0%dd", width);
1598 sprintf(fmt, "%%0%d%c", width, numbuf[0]);
1603 while (*name && *name++ != '}') {
1607 sprintf(numbuf, fmt, it + delta);
1615 } else if (*name == '\\') {
1616 if (*(++name) == '\0') {
1652 return (origin == NULL ? 0 : makename(buf, origin, size));
1657 * Take name and fix it according to following rules:
1659 * "@" means current origin.
1660 * "name." means no changes.
1661 * "name" means append origin.
1664 makename(char *name, const char *origin, int size) {
1666 u_char domain[MAXCDNAME];
1668 switch (ns_name_pton(name, domain, sizeof(domain))) {
1671 case 1: /* FULLY QUALIFIED */
1673 case 0: /* UNQUALIFIED */
1674 if (strcmp(name, "@") == 0) /* must test raw name */
1676 if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1)
1678 /* step back over root, append origin */
1679 switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) {
1688 if (ns_name_ntop(domain, name, size) == -1)
1690 if (name[0] == '.') /* root */
1696 makename_ok(char *name, const char *origin, int class, struct zoneinfo *zp,
1697 enum transport transport, enum context context,
1698 const char *owner, const char *filename, int lineno, int size)
1702 if (makename(name, origin, size) == -1) {
1703 ns_info(ns_log_db, "%s:%d: makename failed",
1707 if (!ns_nameok(NULL, name, class, zp, transport, context, owner,
1709 ns_info(ns_log_db, "%s:%d: database naming error",
1720 while ((c = getc(fp)) != '\0') {
1722 (void) ungetc(c,fp);
1724 } else if (c == EOF) {
1730 #define MAXPORT 1024
1737 getprotocol(FILE *fp, const char *src) {
1741 (void) getword(b, sizeof(b), fp, 0);
1743 k = protocolnumber(b);
1745 ns_info(ns_log_db, "%s:%d: unknown protocol: %s.",
1754 getservices(int offset, char *data, FILE *fp, const char *src) {
1755 int j, ch, k, maxl, bracket;
1759 for (j = 0; j < MAXPORT/8; j++)
1763 while (getword(b, sizeof(b), fp, 0) || bracket) {
1764 if (feof(fp) || ferror(fp))
1774 while ((ch = getc(fp)) != EOF && ch != '\n')
1780 k = servicenumber(b);
1783 "%s:%d: Unknown service '%s'",
1787 if ((k < MAXPORT) && (k)) {
1788 bm[k/8] |= (0x80>>(k%8));
1793 "%s:%d: port no. (%d) too big",
1798 ns_info(ns_log_db, "%s:%d: missing close paren",
1801 memcpy(data+offset, bm, maxl);
1802 return (maxl+offset);
1806 * Converts a word to a u_int32_t. Error if any non-numeric
1807 * characters in the word, except leading or trailing white space.
1817 wordtouint32_error = 0;
1818 result = strtoul(buf, &bufend, 0);
1820 wordtouint32_error = 1;
1822 while ('\0' != *bufend) {
1823 if (isspace(*bufend))
1826 wordtouint32_error = 1;
1830 /* Check for truncation between u_long and u_int32_t */
1833 wordtouint32_error = 1;
1838 getcharstring(char *buf, char *data, int type,
1839 int minfields, int maxfields,
1840 FILE *fp, const char *src)
1842 int nfield = 0, done = 0, n = 0, i;
1848 #ifdef ALLOW_LONG_TXT_RDATA
1850 if (type == ns_t_txt || type == ns_t_x25) {
1851 while (i > MAXCHARSTRING
1852 && n + MAXCHARSTRING + 1 < MAXDATA) {
1853 data[n] = (char)MAXCHARSTRING;
1854 memmove(data + n + 1, b, MAXCHARSTRING);
1855 n += MAXCHARSTRING + 1;
1860 #endif /* ALLOW_LONG_TXT_RDATA */
1861 if (i > MAXCHARSTRING) {
1863 "%s:%d: RDATA field %d too long",
1864 src, lineno -1, nfield);
1867 if (n + i + 1 > MAXDATA) {
1869 "%s:%d: total RDATA too long",
1874 memmove(data + n + 1, b, (int)i);
1876 done = (maxfields && nfield >= maxfields);
1877 } while (!done && getword(buf, MAXDATA, fp, 0));
1879 if (nfield < minfields) {
1881 "%s:%d: expected %d RDATA fields, only saw %d",
1882 src, lineno -1, minfields, nfield);
1894 * get_nxt_types(): Read the list of types in the NXT record.
1896 * Data is the array where the bit flags are stored; it must
1897 * contain at least ns_t_any/NS_NXT_BITS bytes.
1898 * FP is the input FILE *.
1899 * Filename is the sourcefile
1901 * The result is how many bytes are significant in the result.
1905 get_nxt_types(u_char *data, FILE *fp, const char *filename) {
1906 char b[MAXLABEL]; /* Not quite the right size, but good enough */
1912 memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1);
1914 while (getmlword(b, sizeof(b), fp, 0)) {
1915 if (feof(fp) || ferror(fp))
1917 if (strlen(b) == 0 || b[0] == '\n')
1920 /* Parse RR type (A, MX, etc) */
1921 type = sym_ston(__p_type_syms, (char *)b, &success);
1922 if ((!success) || type == ns_t_any) {
1925 "%s: Line %d: Unknown type: %s in NXT record.",
1926 filename, lineno, b);
1929 NS_NXT_BIT_SET(type, data);
1936 return (maxtype/NS_NXT_BITS+1);
1939 /* sanity checks PRIMARY ONLY */
1941 fixup_soa(const char *fn, struct zoneinfo *zp) {
1942 /* Sanity: give enough time for the zone to transfer (retry). */
1943 if (zp->z_expire < (zp->z_refresh + zp->z_retry))
1944 ns_notice(ns_log_db,
1945 "%s: WARNING SOA expire value is less than SOA refresh+retry (%u < %u+%u)",
1946 fn, zp->z_expire, zp->z_refresh, zp->z_retry);
1949 if (zp->z_expire < (zp->z_refresh + 10 * zp->z_retry))
1950 ns_warning(ns_log_db,
1951 "%s: WARNING SOA expire value is less than refresh + 10 * retry \
1952 (%u < (%u + 10 * %u))",
1953 fn, zp->z_expire, zp->z_refresh, zp->z_retry);
1956 * Sanity: most hardware/telco faults are detected and fixed within
1957 * a week, secondaries should continue to operate for this time.
1958 * (minimum of 4 days for long weekends)
1960 if (zp->z_expire < (7 * 24 * 3600))
1961 ns_warning(ns_log_db,
1962 "%s: WARNING SOA expire value is less than 7 days (%u)",
1966 * Sanity: maximum down time if we havn't talked for six months
1967 * war must have broken out.
1969 if (zp->z_expire > ( 183 * 24 * 3600))
1970 ns_warning(ns_log_db,
1971 "%s: WARNING SOA expire value is greater than 6 months (%u)",
1975 if (zp->z_refresh < (zp->z_retry * 2))
1976 ns_warning(ns_log_db,
1977 "%s: WARNING SOA refresh value is less than 2 * retry (%u < %u * 2)",
1978 fn, zp->z_refresh, zp->z_retry);
1981 /* this function reads in the sig record rdata from the input file and
1982 * returns the following codes
1983 * > 0 length of the recrod
1984 * ERR_EOF end of file
1989 parse_sig_rr(char *buf, int buf_len, u_char *data, int data_size,
1990 FILE *fp, struct zoneinfo *zp, char *domain, u_int32_t ttl,
1991 enum context domain_ctx, enum transport transport, char **errmsg)
1993 /* The SIG record looks like this in the db file:
1994 Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig
1996 where: Name and Cl are as usual
1998 RRtype is a char string
1999 ALGid is 8 bit u_int
2000 Labels is 8 bit u_int
2001 OTTL is 32 bit u_int (optionally present)
2002 Texp is YYYYMMDDHHMMSS
2003 Tsig is YYYYMMDDHHMMSS
2004 Kfoot is 16-bit unsigned decimal integer
2005 Signer is a char string
2006 Sig is 64 to 319 base-64 digits
2007 A missing OTTL is detected by the magnitude of the Texp value
2008 that follows it, which is larger than any u_int.
2009 The Labels field in the binary RR does not appear in the
2012 It's too crazy to run these pages of SIG code at the right
2013 margin. I'm exdenting them for readability.
2017 int siglen, success;
2019 u_int32_t al, la, n;
2020 u_int32_t signtime, exptime, timetilexp;
2022 enum context context;
2024 char *errtype = "SIG error";
2025 int i, my_buf_size = MAXDATA, errs = 0;
2028 /* The TTL gets checked against the Original TTL,
2029 and bounded by the signature expiration time, which
2030 are both under the signature. We can't let TTL drift
2031 based on the SOA record. If defaulted, fix it now.
2032 (It's not clear to me why USE_MINIMUM isn't eliminated
2033 before putting ALL RR's into the database. -gnu@toad.com) */
2034 if (ttl == USE_MINIMUM)
2035 ttl = zp->z_minimum;
2040 getmlword_nesting = 0; /* KLUDGE err recovery */
2043 * if old style inp will contain the next token
2044 *copy that into buffer, otherwise read from file
2046 if (buf && buf_len == 0)
2047 if (!getmlword((char*)buf, my_buf_size, fp, 0))
2048 ERRTO("SIG record doesn't specify type");
2049 sig_type = sym_ston(__p_type_syms, buf, &success);
2050 if (!success || sig_type == ns_t_any) {
2052 * We'll also accept a numeric RR type,
2053 * for signing RR types that this version
2054 * of named doesn't yet understand.
2055 * In the ns_t_any case, we rely on wordtouint32
2056 * to fail when scanning the string "ANY".
2058 sig_type = wordtouint32 (buf);
2059 if (wordtouint32_error || sig_type > 0xFFFF)
2060 ERRTO("Unknown RR type in SIG record");
2063 PUTSHORT((u_int16_t)sig_type, cp);
2066 /* Algorithm id (8-bit decimal) */
2067 if (!getmlword(buf, my_buf_size, fp, 0))
2068 ERRTO("Missing algorithm ID");
2069 al = wordtouint32(buf);
2070 if (0 == al || wordtouint32_error || 255 <= al)
2071 ERRTO("Bad algorithm number");
2072 data[i] = (u_char) al;
2076 * Labels (8-bit decimal)
2078 if (!getmlword(buf, my_buf_size, fp, 0))
2079 ERRTO("Missing label count");
2080 la = wordtouint32(buf);
2081 if (0 == la || wordtouint32_error || 255 <= la)
2082 ERRTO("Bad label count number");
2083 data[i] = (u_char) la;
2087 * OTTL (optional u_int32_t) and
2088 * Texp (u_int32_t date)
2090 if (!getmlword(buf, my_buf_size, fp, 0))
2091 ERRTO("OTTL and expiration time missing");
2093 * See if OTTL is missing and this is a date.
2094 * This relies on good, silent error checking
2097 exptime = ns_datetosecs(buf, &dateerror);
2099 /* Output TTL as OTTL */
2102 PUTLONG (origTTL, cp);
2105 /* Parse and output OTTL; scan TEXP */
2106 origTTL = wordtouint32(buf);
2107 if (0 >= origTTL || wordtouint32_error ||
2108 (origTTL > 0x7fffffff))
2109 ERRTO("Original TTL value bad");
2111 PUTLONG(origTTL, cp);
2113 if (!getmlword(buf, my_buf_size, fp, 0))
2114 ERRTO("Expiration time missing");
2115 exptime = ns_datetosecs(buf, &dateerror);
2117 if (dateerror || exptime > 0x7fffffff || exptime <= 0)
2118 ERRTO("Invalid expiration time");
2120 PUTLONG(exptime, cp);
2123 /* Tsig (u_int32_t) */
2124 if (!getmlword(buf, my_buf_size, fp, 0))
2125 ERRTO("Missing signature time");
2126 signtime = ns_datetosecs(buf, &dateerror);
2127 if (0 == signtime || dateerror)
2128 ERRTO("Invalid signature time");
2130 PUTLONG(signtime, cp);
2133 /* Kfootprint (unsigned_16) */
2134 if (!getmlword(buf, my_buf_size, fp, 0))
2135 ERRTO("Missing key footprint");
2136 n = wordtouint32(buf);
2137 if (wordtouint32_error || n >= 0x0ffff)
2138 ERRTO("Invalid key footprint");
2140 PUTSHORT((u_int16_t)n, cp);
2144 if (!getmlword((char*)buf, my_buf_size, fp, 0))
2145 ERRTO("Missing signer's name");
2147 strcpy((char *)cp, buf);
2148 context = domain_ctx;
2149 MAKENAME_OKZP((char *)cp, data_size);
2150 i += strlen((char *)cp) + 1;
2153 * Signature (base64 of any length)
2154 * We don't care what algorithm it uses or what
2155 * the internal structure of the BASE64 data is.
2157 if (!getallwords(buf, my_buf_size, fp, 0)) {
2161 siglen = b64_pton(buf, (u_char*)cp, data_size - i);
2163 ERRTO("Signature block bad");
2166 /* set total length and we're done! */
2170 * Check signature time, expiration, and adjust TTL. Note
2171 * that all time values are in GMT (UTC), *not* local time.
2174 now = time (0); /* need to find a better place for this XXX ogud */
2175 /* Don't let bogus name servers increase the signed TTL */
2177 ERRTO("TTL is greater than signed original TTL");
2179 /* Don't let bogus signers "sign" in the future. */
2180 if (signtime > (u_int32_t)now)
2181 ERRTO("signature time is in the future");
2183 /* Ignore received SIG RR's that are already expired. */
2184 if (exptime <= (u_int32_t)now)
2185 ERRTO("expiration time is in the past");
2187 /* Lop off the TTL at the expiration time. */
2188 timetilexp = exptime - now;
2189 if (timetilexp < ttl) {
2190 ns_debug(ns_log_load, 1,
2191 "shrinking expiring %s SIG TTL from %d to %d",
2192 p_secstodate(exptime), ttl, timetilexp);
2197 * Check algorithm-ID and key structure, for
2198 * the algorithm-ID's that we know about.
2203 ERRTO("No key for RSA algorithm");
2205 ERRTO("Signature too short");
2206 if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8)
2207 ERRTO("Signature too long");
2212 ERRTO("DH Signature too short");
2213 break; /* need more tests here */
2216 if (siglen < NS_DSA_SIG_SIZE)
2217 ERRTO("DSS Signature too short");
2218 else if (siglen > NS_DSA_SIG_SIZE)
2219 ERRTO("DSS Signature too long ");
2220 break; /* need more tests here */
2222 case NS_ALG_EXPIRE_ONLY:
2225 "Signature supplied to expire-only algorithm");
2227 case NS_ALG_PRIVATE_OID:
2229 ERRTO("No ObjectID in key");
2232 ERRTO("UNKOWN SIG algorithm");
2235 /* Should we complain about algorithm-ID's that we
2236 don't understand? It may help debug some obscure
2237 cases, but in general we should accept any RR whether
2238 we could cryptographically process it or not; it
2239 may be being published for some newer DNS clients
2240 to validate themselves. */
2242 endline(fp); /* flush the rest of the line */
2251 parse_nxt_rr(char *buf, int buf_len, u_char *data, int data_size,
2252 FILE *fp, struct zoneinfo *zp, char *domain, enum context context,
2253 enum transport transport, char **errmsg)
2256 /* The NXT record looks like:
2257 Name Cl NXT nextname RRT1 RRT2 MX A SOA ...
2259 where: Name and Cl are as usual
2261 nextname is the next valid name in the zone after "Name".
2262 All names between the two are known to be nonexistent.
2263 RRT's... are a series of RR type names, which indicate that
2264 RR's of these types are published for "Name", and
2265 that no RR's of any other types are published for "Name".
2267 When a NXT record is cryptographically signed, it proves the
2268 nonexistence of an RR (actually a whole set of RR's).
2272 /* char *origin = zp->z_origin;
2273 int class = zp->z_class; */
2274 *errmsg = "NXT name error";
2276 (void) strcpy((char *)data, buf);
2277 MAKENAME_OKZP((char *)data, data_size);
2278 n = strlen((char *)data) + 1;
2280 i = get_nxt_types(cp, fp, zp->z_source);
2283 *errmsg = "NXT type error";
2290 parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size,
2291 FILE *fp, char **errmsg)
2293 /* Cert record looks like:
2294 * Type Key_tag Alg Cert
2295 * Type: certification type number (16)
2296 * Key_tag: tag of corresponding KEY RR (16)
2297 * Alg: algorithm of the KEY RR (8)
2298 * Cert: base64 enocded block
2301 u_int32_t cert_type, key_tag, alg;
2302 char *errtype = "CERT parse error";
2303 int certlen, i, n, success;
2307 cert_type = sym_ston(__p_cert_syms, buf, &success);
2309 cert_type = wordtouint32(buf);
2310 if (wordtouint32_error || cert_type > 0xFFFF)
2311 ERRTO("CERT type out of range");
2313 PUTSHORT((u_int16_t)cert_type, cp);
2316 if (!getmlword((char*)buf, buf_len, fp, 0))
2317 ERRTO("CERT doesn't specify type");
2319 key_tag = wordtouint32(buf);
2320 if (wordtouint32_error || key_tag > 0xFFFF)
2321 ERRTO("CERT KEY tag out of range");
2323 PUTSHORT((u_int16_t)key_tag, cp);
2326 if (!getmlword(buf, buf_len, fp, 0))
2327 ERRTO("CERT missing algorithm ID");
2329 alg = sym_ston(__p_key_syms, buf, &success);
2331 alg = wordtouint32(buf);
2332 if (wordtouint32_error || alg > 0xFF)
2333 ERRTO("CERT KEY alg out of range");
2336 data[i++] = (u_char)alg;
2338 if (!getallwords(buf, buf_len, fp, 0)) {
2343 certlen = b64_pton(buf, (u_char*)cp, sizeof(data) - i);
2345 ERRTO("CERT blob has encoding error");
2347 /* set total length */
2357 parse_key_rr(char *buf, int buf_len, u_char *data, int data_size,
2358 FILE *fp, struct zoneinfo *zp, char *domain, enum context context,
2359 enum transport transport, char **errmsg)
2361 /* The KEY record looks like this in the db file:
2362 * Name Cl KEY Flags Proto Algid PublicKeyData
2366 * Flags 4 digit hex value (unsigned_16)
2370 * a string of base64 digits,
2371 * skipping any embedded whitespace.
2376 char *errtype = "KEY error";
2377 u_char *cp, *expstart;
2378 u_int expbytes, modbytes;
2383 getmlword_nesting = 0; /* KLUDGE err recov. */
2385 /*>>> Flags (unsigned_16) */
2386 keyflags = wordtouint32(buf);
2387 if (wordtouint32_error || 0xFFFF < keyflags)
2388 ERRTO("KEY flags error");
2389 if (keyflags & NS_KEY_RESERVED_BITMASK)
2390 ERRTO("KEY Reserved Flag Bit");
2391 PUTSHORT(keyflags, cp);
2393 /*>>> Protocol (8-bit decimal) */
2394 if (!getmlword((char*)buf, buf_len, fp, 0))
2395 ERRTO("KEY Protocol Field");
2396 pr = wordtouint32(buf);
2397 if (wordtouint32_error || 255 < pr)
2398 ERRTO("KEY Protocol Field");
2399 *cp++ = (u_char) pr;
2401 /*>>> Algorithm id (8-bit decimal) */
2402 if (!getmlword((char*)buf, buf_len, fp, 0))
2403 ERRTO("KEY Algorithm ID");
2404 al = wordtouint32(buf);
2405 if (wordtouint32_error || 0 == al || 255 == al || 255 < al)
2406 ERRTO("KEY Algorithm ID");
2407 *cp++ = (u_char) al;
2409 /*>>> Extended KEY flag field in bytes 5 and 6 */
2410 if (NS_KEY_EXTENDED_FLAGS & keyflags) {
2411 u_int32_t keyflags2;
2413 if (!getmlword((char*)buf, buf_len, fp, 0))
2414 ERRTO("KEY Flags Field");
2415 keyflags2 = wordtouint32(buf);
2416 if (wordtouint32_error || 0xFFFF < keyflags2)
2417 ERRTO("Extended key flags error");
2418 if (keyflags2 & NS_KEY_RESERVED_BITMASK2)
2419 ERRTO("KEY Reserved Flag2 Bit");
2420 PUTSHORT(keyflags2, cp);
2423 /*>>> Public Key data is in BASE64.
2424 * We don't care what algorithm it uses or what
2425 * the internal structure of the BASE64 data is.
2427 if (!getallwords(buf, MAXDATA, fp, 0))
2430 /* Convert from BASE64 to binary. */
2431 klen = b64_pton(buf, (u_char*)cp,
2432 data_size - (cp - data));
2434 ERRTO("KEY Public Key");
2437 /* set total length */
2438 n = klen + (cp - data);
2441 * Now check for valid key flags & algs & etc, from the RFC.
2444 if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK))
2445 nk = 1; /* No-key */
2447 nk = 0; /* have a key */
2449 if ((keyflags & (NS_KEY_NAME_TYPE | NS_KEY_TYPEMASK)) ==
2450 (NS_KEY_NAME_ZONE | NS_KEY_TYPE_CONF_ONLY))
2451 /* Zone key must have Auth bit set. */
2452 ERRTO("KEY Zone Key Auth. bit");
2454 if (al == 0 && nk == 0)
2455 ERRTO("KEY Algorithm");
2456 if (al != 0 && pr == 0)
2457 ERRTO("KEY Protocols");
2459 if (nk == 1 && klen != 0)
2460 ERRTO("KEY No-Key Flags Set");
2462 if (nk == 0 && klen == 0)
2463 ERRTO("KEY Type Spec'd");
2466 * Check algorithm-ID and key structure, for the algorithm-ID's
2467 * that we know about.
2474 expbytes = *expstart++;
2476 GETSHORT(expbytes, expstart);
2479 ERRTO("Exponent too short");
2480 if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
2481 ERRTO("Exponent too long");
2483 ERRTO("Exponent w/ 0");
2485 modbytes = klen - (expbytes + (expstart - cp));
2486 if (modbytes < (NS_MD5RSA_MIN_BITS + 7) / 8)
2487 ERRTO("Modulus too short");
2488 if (modbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
2489 ERRTO("Modulus too long");
2490 if (*(expstart+expbytes) == 0)
2491 ERRTO("Modulus starts w/ 0");
2496 u_int16_t dh_len, plen, glen, ulen;
2498 dh_cp = (u_char *)cp;
2499 GETSHORT(plen, dh_cp);
2501 ERRTO("DH short plen");
2504 ERRTO("DH plen > klen");
2506 GETSHORT(glen, dh_cp);
2507 if(glen <= 0 || glen > plen)
2508 ERRTO("DH glen bad");
2511 ERRTO("DH glen > klen");
2513 GETSHORT(ulen, dh_cp);
2514 if(ulen <= 0 || ulen > plen)
2515 ERRTO("DH ulen bad");
2518 ERRTO("DH ulen > klen");
2519 else if (dh_len < klen)
2520 ERRTO("DH *len < klen");
2531 ERRTO("DSA T value");
2532 if (klen != (1 + 20 + 3 *(64+8*t)))
2533 ERRTO("DSA length");
2537 case NS_ALG_PRIVATE_OID:
2539 ERRTO("No ObjectID in key");
2542 ERRTO("Unknown Key algorithm");
2545 endline(fp); /* flush the rest of the line */
2553 * function to invoke DNSSEC specific parsing routines.
2554 * this is simpler than copying these complicated blocks into the
2555 * multiple souce files that read files (ixfr, nsupdate etc..).
2556 * this code should be in a library rather than in this file but
2557 * what the heck for now (ogud@tislabs.com)
2560 parse_sec_rdata(char *buf, int buf_len, int buf_full, u_char *data,
2561 int data_size, FILE *fp, struct zoneinfo *zp,
2562 char *domain, u_int32_t ttl, int type, enum context context,
2563 enum transport transport, char **errmsg)
2567 getmlword_nesting = 0; /* KLUDGE err recov. */
2568 if (!buf_full && buf && buf_len != 0) /* check if any data in buf */
2569 if (!getmlword(buf, buf_len, fp, 1)) {
2570 *errmsg = "unexpected end of input";
2576 ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp,
2577 domain, ttl, context, transport, errmsg);
2580 ret = parse_key_rr(buf, buf_len, data, data_size, fp, zp,
2581 domain, context, transport, errmsg);
2584 ret = parse_nxt_rr(buf, buf_len, data, data_size, fp, zp,
2585 domain, context, transport, errmsg);
2588 ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg);
2592 *errmsg = "parse_sec_rdata():Unsupported SEC type type";