]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind/bin/named/db_load.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / contrib / bind / bin / named / db_load.c
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 $";
4 #endif /* not lint */
5
6 /*
7  * Copyright (c) 1986, 1988, 1990
8  *    The Regents of the University of California.  All rights reserved.
9  * 
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
25  * 
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
36  * SUCH DAMAGE.
37  */
38
39 /*
40  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
41  * 
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.
48  * 
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
56  * SOFTWARE.
57  */
58
59 /*
60  * Portions Copyright (c) 1995 by International Business Machines, Inc.
61  *
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
68  * permission.
69  *
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.
75  *
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.
82  */
83
84 /*
85  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
86  *
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.
90  *
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
98  * SOFTWARE.
99  */
100
101 /*
102  * Load zone from ASCII file on local host.  Format similar to RFC 883.
103  */
104
105 /* Import. */
106
107 #include "port_before.h"
108
109 #include <sys/types.h>
110 #include <sys/param.h>
111 #include <sys/stat.h>
112 #include <sys/socket.h>
113 #include <sys/un.h>
114
115 #include <netinet/in.h>
116 #include <arpa/nameser.h>
117 #include <arpa/inet.h>
118
119 #include <ctype.h>
120 #include <errno.h>
121 #include <netdb.h>
122 #include <resolv.h>
123 #include <errno.h>
124 #include <stdio.h>
125 #include <stdlib.h>
126 #include <string.h>
127 #include <syslog.h>
128 #include <time.h>
129
130 #include <isc/eventlib.h>
131 #include <isc/logging.h>
132 #include <isc/memcluster.h>
133
134 #include "port_after.h"
135
136 #include "named.h"
137
138 /* Forward. */
139
140 static int              gettoken(FILE *, const char *);
141 static int              getcharstring(char *, char *, int, int, int, FILE *,
142                                       const char *);
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 *);
149
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 **);
156
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 **);
161
162
163 static int              wordtouint32_error = 0;
164 static int              empty_token = 0;
165 static int              getmlword_nesting = 0;
166
167 /* Global. */
168
169 static int clev;        /* a zone deeper in a hierarchy has more credibility */
170
171 /*
172  * Parser token values
173  */
174 #define CURRENT         1
175 #define DOT             2
176 #define AT              3
177 #define DNAME           4
178 #define INCLUDE         5
179 #define ORIGIN          6
180 #define GENERATE        7
181 #define DEFAULTTTL      8
182 #define ERRTOK          9
183
184 #define MAKENAME_OK(N) \
185         do { \
186                 if (!makename_ok(N, origin, class, zp, \
187                                  transport, context, \
188                                  domain, filename, lineno, \
189                                  data_size - ((u_char*)N - data))) { \
190                         errs++; \
191                         sprintf(buf, "bad name \"%s\"", N); \
192                         goto err; \
193                 } \
194         } while (0)
195
196 #define MAKENAME_OKZP(N, SI) \
197         do { \
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))) { \
202                         errs++; \
203                         sprintf(buf, "bad name \"%s\"", N); \
204                         goto err; \
205                 } \
206         } while (0)
207
208 #define RANGE(x, min, max) \
209         (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
210
211 /* Public. */
212
213 /* int
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.
218  * returns:
219  *      -1 = can't open file
220  *      0 = success
221  *      >0 = number of errors encountered
222  */
223 int
224 db_load(const char *filename, const char *in_origin,
225         struct zoneinfo *zp, const char *def_domain, int isixfr)
226 {
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;
231                 char             *name;
232         } *filenames, *fn;
233
234         const char *errtype = "Database";
235         char *cp;
236         char domain[MAXDNAME], origin[MAXDNAME], tmporigin[MAXDNAME];
237         char buf[MAXDATA];
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;
244         u_long tmplong;
245         struct databuf *dp;
246         FILE *fp;
247         struct stat sb;
248         struct in_addr ina;
249         enum transport transport;
250         enum context context;
251         struct sockaddr_in empty_from;
252         int genstart, genend, genstep;
253         char *thisfile;
254         void *state = NULL;
255
256         empty_from.sin_family = AF_INET;
257         empty_from.sin_addr.s_addr = htonl(INADDR_ANY);
258         empty_from.sin_port = htons(0);
259
260 /*
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'
263  * and complains.
264  */
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)
267
268         switch (zp->z_type) {
269         case Z_PRIMARY:
270         case Z_HINT:
271                 transport = primary_trans;
272                 break;
273         case Z_SECONDARY:
274         case Z_STUB:
275                 transport = secondary_trans;
276                 break;
277         case Z_CACHE:
278                 transport = response_trans;
279                 break;
280         default:
281                 transport = response_trans; /*guessing*/
282                 break;
283         }
284         errs = 0;
285         didinclude = 0;
286         ininclude = (def_domain != NULL);
287         if (!ininclude) {
288                 rrcount = 0;
289                 read_soa = 0;
290                 read_ns = 0;
291                 default_ttl = USE_MINIMUM;
292                 default_warn = 1;
293                 clev = nlabels(in_origin);
294                 filenames = NULL;
295         }
296         ttl = default_ttl;
297
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");
301
302         fn = (struct filenames *)memget(sizeof *filenames);
303         if (fn == NULL)
304                 ns_panic(ns_log_db, 0, "db_load: memget failed");
305         thisfile = fn->name = savestr(filename, 1);
306         fn->next = filenames;
307         filenames = fn;
308
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));
313                 zp->z_ftime = 0;
314                 return (-1);
315         }
316         if (zp->z_type == Z_HINT) {
317                 dbflags = DB_NODATA | DB_NOHINTS;
318                 dataflags = DB_F_HINT;
319 #ifdef STUBS
320         } else if (zp->z_type == Z_STUB && clev == 0) {
321                 dbflags = DB_NODATA | DB_NOHINTS;
322                 dataflags = DB_F_HINT;
323 #endif
324         } else {
325                 dbflags = DB_NODATA;
326                 dataflags = 0;
327         }
328         gettime(&tt);
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;
333         }
334         slineno = lineno;
335         lineno = 1;
336         if (def_domain)
337                 strcpy(domain, def_domain);
338         else
339                 domain[0] = '\0';
340         class = zp->z_class;
341         zp->z_flags &= ~(Z_INCLUDE|Z_DB_BAD);
342         while ((c = gettoken(fp, filename)) != EOF) {
343                 switch (c) {
344                 case INCLUDE:
345                         if (isixfr) {
346                                 c = ERRTOK;
347                                 break;
348                         }
349                         if (!getword(buf, sizeof buf, fp, 0))
350                                 /* file name*/
351                                 break;
352                         if (!getword(tmporigin, sizeof(tmporigin), fp, 1))
353                                 strcpy(tmporigin, origin);
354                         else {
355                                 if (makename(tmporigin, origin,
356                                              sizeof(tmporigin)) == -1)
357                                         ERRTO("$INCLUDE makename failed");
358                                 endline(fp);
359                         }
360                         didinclude = 1;
361                         errs += db_load(buf, tmporigin, zp, domain, ISNOTIXFR);
362                         continue;
363
364                 case ORIGIN:
365                         (void) strcpy(buf, origin);
366                         if (!getword(origin, sizeof(origin), fp, 1))
367                                 break;
368                         ns_debug(ns_log_load, 3, "db_load: origin %s, buf %s",
369                                  origin, buf);
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",
373                                  origin);
374                         continue;
375
376                 case GENERATE:
377                         if (!getword(buf, sizeof(buf), fp, 0))
378                                 ERRTOZ("$GENERATE missing RANGE");
379                         n = sscanf(buf, "%d-%d/%d", &genstart, &genend,
380                                                         &genstep);
381                         if (n != 2 && n != 3)
382                                 ERRTO("$GENERATE invalid range");
383                         if (n == 2)
384                                 genstep = 1;
385                         if ((genend < genstart) || (genstart < 0) ||
386                             (genstep < 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) {
394                                 ns_info(ns_log_load,
395                                         "%s: Line %d: $GENERATE unknown type: %s.",
396                                         filename, lineno, buf);
397                                 errs++;
398                                 endline(fp);
399                                 continue;
400                         }
401                         switch (type) {
402                         case ns_t_ns:
403                         case ns_t_ptr:
404                         case ns_t_cname:
405                         case ns_t_a:
406                         case ns_t_aaaa:
407                                 break;
408                         default:
409                                 ERRTO("$GENERATE unsupported type");
410                         }
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)) {
420                                         strcpy(buf, domain);
421                                         ERRTO("$GENERATE owner name error");
422                                 }
423                                 switch (type) {
424                                 case ns_t_ns:
425                                 case ns_t_ptr:
426                                 case ns_t_cname:
427                                         if (genname(genrhs, i, origin, (char *)data,
428                                                         sizeof data) == -1)
429                                                 ERRTOZ("$GENERATE genname RHS failed");
430                                         switch (type) {
431                                         case ns_t_ns:
432                                                 context = hostname_ctx;
433                                                 break;
434                                         case ns_t_ptr:
435                                                 context = ns_ptrcontext(domain);
436                                                 break;
437                                         case ns_t_cname:
438                                                 context = domain_ctx;
439                                                 break;
440                                         }
441                                         if (!ns_nameok(NULL, (char *)data, class, zp,
442                                                            transport, context,
443                                                            domain, inaddr_any)) {
444                                                 strncpy(buf, domain, sizeof(buf));
445                                                 buf[sizeof(buf)-1] = '\0';
446                                                 ERRTO("$GENERATE name error");
447                                         }
448                                         n = strlen((char *)data) + 1;
449                                         break;
450                                 case ns_t_a:
451                                 case ns_t_aaaa:
452                                         if (genname(genrhs, i, NULL, (char *)data,
453                                                         sizeof data) == -1)
454                                                 ERRTOZ("$GENERATE genname RHS failed");
455                                         strncpy(buf, (char*)data, sizeof(buf));
456                                         buf[sizeof(buf)-1] = '\0';
457                                         switch (type) {
458                                         case ns_t_a:
459                                                 if (!inet_aton(buf, &ina))
460                                                         ERRTO("IP Address");
461                                                 (void) ina_put(ina, data);
462                                                 n = NS_INT32SZ;
463                                                 break;
464                                         case ns_t_aaaa:
465                                                 if (inet_pton(AF_INET6, buf, data) <= 0)
466                                                         ERRTO("IPv6 Address");
467                                                 n = NS_IN6ADDRSZ;
468                                                 break;
469                                         }
470                                         break;
471                                 default:
472                                            ERRTOZ("$GENERATE unsupported context");
473                                 }
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;
479                                 dp->d_clev = clev;
480                                 c = db_set_update(domain, dp, &state, dbflags,
481                                                   (dataflags & DB_F_HINT) != 0 ?
482                                                   &fcachetab : &hashtab,
483                                                   empty_from, &rrcount, lineno,
484                                                   filename);
485                                 if (c != OK) {
486                                         if (c == CNAMEANDOTHER)
487                                                 errs++;
488                                 }
489                         }
490                         endline(fp);
491                         continue;
492
493                 case DNAME:
494                         if (!getword(domain, sizeof(domain), fp, 1))
495                                 break;
496                         if (makename(domain, origin, sizeof(domain)) == -1)
497                                 ERRTO("ownername makename failed");
498                         goto gotdomain;
499
500                 case DEFAULTTTL:
501                         if (getttl(fp, filename, lineno, &n,
502                                    &multiline) <= 0 || n > MAXIMUM_TTL) {
503                                 ERRTO("$TTL bad TTL value");
504                         }
505                         ttl = default_ttl = n;
506                         continue;
507
508                 case AT:
509                         (void) strcpy(domain, origin);
510                         goto gotdomain;
511
512                 case DOT:
513                         domain[0] = '\0';
514                         /* FALLTHROUGH */
515                 case CURRENT:
516                 gotdomain:
517                         if (!getword(buf, sizeof buf, fp, 0)) {
518                                 if (c == CURRENT)
519                                         continue;
520                                 break;
521                         }
522                         if (ns_parse_ttl(buf, &tmplong) < 0) {
523                                 if (zp->z_type == z_master &&
524                                     default_warn &&
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");
530                                         default_warn = 0;
531                                 }
532                                 ttl = (u_int32_t)default_ttl;
533                         } else {
534                                 ttl = tmplong;
535                                 if (ttl > MAXIMUM_TTL) {
536                                         ns_info(ns_log_load,
537                                       "%s: Line %d: TTL > %u; converted to 0",
538                                                 filename, lineno, MAXIMUM_TTL);
539                                         ttl = 0;
540                                 }
541                                 if (zp->z_type == Z_CACHE) {
542                                         /*
543                                          * This allows the cache entry to age
544                                          * while sitting on disk (powered off).
545                                          */
546                                         if (ttl > max_cache_ttl)
547                                                 ttl = max_cache_ttl;
548                                         ttl += sb.st_mtime;
549                                 }
550                                 if (!getword(buf, sizeof buf, fp, 0))
551                                         break;
552                         }
553
554                         /* Parse class (IN, etc) */
555                         someclass = sym_ston(__p_class_syms, buf, &success);
556                         if (success && someclass != zp->z_class) {
557                                 ns_info(ns_log_load,
558                                         "%s: Line %d: wrong class: %s.",
559                                         filename, lineno,
560                                         p_class(someclass));
561                                 errs++;
562                                 break;
563                         }
564                         if (success && someclass != C_ANY) {
565                                 class = someclass;
566                                 (void) getword(buf, sizeof buf, fp, 0);
567                         }
568
569                         /* Parse RR type (A, MX, etc) */
570                         type = sym_ston(__p_type_syms, buf, &success);
571                         if (success == 0 || type == ns_t_any) {
572                                 ns_info(ns_log_load,
573                                         "%s: Line %d: Unknown type: %s.",
574                                         filename, lineno, buf);
575                                 errs++;
576                                 break;
577                         }
578                         if (ttl == USE_MINIMUM) 
579                                 ttl = zp->z_minimum;
580                         context = ns_ownercontext(type, transport);
581                         if (!ns_nameok(NULL, domain, class, zp, transport, context,
582                                        domain, inaddr_any)) {
583                                 errs++;
584                                 ns_notice(ns_log_load,
585                                           "%s:%d: owner name error",
586                                           filename, lineno);
587                                 break;
588                         }
589                         context = domain_ctx;
590                         switch (type) {
591                         case ns_t_key:
592                         case ns_t_sig:
593                         case ns_t_nxt:
594                         case ns_t_cert:
595                                 /*
596                                  * Don't do anything here for these types --
597                                  * they read their own input separately later.
598                                  */
599                                 goto dont_get_word;
600
601                         case ns_t_soa:
602                         case ns_t_minfo:
603                         case ns_t_rp:
604                         case ns_t_ns:
605                         case ns_t_cname:
606                         case ns_t_mb:
607                         case ns_t_mg:
608                         case ns_t_mr:
609                         case ns_t_ptr:
610                                 escape = 1;
611                                 break;
612                         default:
613                                 escape = 0;
614                         }
615                         if (!getword(buf, sizeof buf, fp, escape))
616                                 break;
617                         ns_debug(ns_log_load, 3,
618                                  "d='%s', c=%d, t=%d, ttl=%u, data='%s'",
619                                  domain, class, type, ttl, buf);
620                         /*
621                          * Convert the ascii data 'buf' to the proper format
622                          * based on the type and pack into 'data'.
623                          */
624                 dont_get_word:
625                         switch (type) {
626                         case ns_t_a:
627                                 if (!inet_aton(buf, &ina))
628                                         ERRTO("IP Address");
629                                 (void) ina_put(ina, data);
630                                 n = NS_INT32SZ;
631                                 break;
632
633                         case ns_t_soa:
634                                 context = hostname_ctx;
635                                 goto soa_rp_minfo;
636                         case ns_t_rp:
637                         case ns_t_minfo:
638                                 context = mailname_ctx;
639                                 /* FALLTHROUGH */
640                         soa_rp_minfo:
641                                 (void) strcpy((char *)data, buf);
642                                
643                                 MAKENAME_OK((char *)data);
644                                 cp = (char *)(data + strlen((char *)data) + 1);
645                                 if (!getword(cp,
646                                              (sizeof data) -
647                                              (cp - (char*)data),
648                                              fp, 1))
649                                         ERRTO("Domain Name");
650                                 if (type == ns_t_rp)
651                                         context = domain_ctx;
652                                 else
653                                         context = mailname_ctx;
654                                 MAKENAME_OK(cp);
655                                 cp += strlen((char *)cp) + 1;
656                                 if (type != ns_t_soa) {
657                                         n = cp - (char *)data;
658                                         break;
659                                 }
660                                 if (ns_samename(zp->z_origin, domain) != 1) {
661                                         errs++;
662                                         ns_error(ns_log_load,
663                                 "%s:%d: SOA for \"%s\" not at zone top \"%s\"",
664                                                  filename, lineno, domain,
665                                                  zp->z_origin);
666                                 }
667                                 c = getnonblank(fp, filename);
668                                 if (c == '(') {
669                                         multiline = 1;
670                                 } else {
671                                         multiline = 0;
672                                         ungetc(c, fp);
673                                 }
674                                 serial = zp->z_serial;
675                                 zp->z_serial = getnum(fp, filename,
676                                                       GETNUM_SERIAL);
677                                 if (getnum_error)
678                                         errs++;
679                                 n = (u_int32_t) zp->z_serial;
680                                 PUTLONG(n, cp);
681                                 if (serial != 0 &&
682                                     SEQ_GT(serial, zp->z_serial)) {
683                                         ns_notice(ns_log_load,
684                          "%s:%d: WARNING: new serial number < old (%lu < %lu)",
685                                                   filename , lineno,
686                                                   zp->z_serial, serial);
687                                 }
688                                 if (getttl(fp, filename, lineno, &n,
689                                            &multiline) <= 0) {
690                                         errs++;
691                                         n = INIT_REFRESH;
692                                 }
693                                 PUTLONG(n, cp);
694                                 zp->z_refresh = RANGE(n, MIN_REFRESH,
695                                                       MAX_REFRESH);
696                                 if (zp->z_type == Z_SECONDARY
697 #if defined(STUBS)
698                                     || zp->z_type == Z_STUB
699 #endif
700                                     ) {
701                                         ns_refreshtime(zp, MIN(sb.st_mtime,
702                                                                tt.tv_sec));
703                                         sched_zone_maint(zp);
704                                 }
705 #ifdef BIND_UPDATE
706                                 if ((zp->z_type == Z_PRIMARY) &&
707                                     (zp->z_flags & Z_DYNAMIC))
708                                         if ((u_int32_t)zp->z_soaincrintvl >
709                                             zp->z_refresh/3) {
710                                                 ns_info(ns_log_load,
711                     "zone soa update time truncated to 1/3rd of refresh time");
712                                                 zp->z_soaincrintvl =
713                                                         zp->z_refresh / 3;
714                                         }
715 #endif
716
717                                 if (getttl(fp, filename, lineno, &n,
718                                            &multiline) <= 0) {
719                                         errs++;
720                                         n = INIT_REFRESH;
721                                 }
722                                 PUTLONG(n, cp);
723                                 zp->z_retry = RANGE(n, MIN_RETRY, MAX_RETRY);
724                                 if (getttl(fp, filename, lineno,
725                                            &n, &multiline) <= 0) {
726                                         errs++;
727                                         n = INIT_REFRESH;
728                                 }
729                                 PUTLONG(n, cp);
730                                 zp->z_expire = RANGE(n, zp->z_refresh,
731                                                      MAX_EXPIRE);
732                                 if (getttl(fp, filename, lineno, &n,
733                                            &multiline) <= 0) {
734                                         errs++;
735                                         n = 120;
736                                 }
737                                 PUTLONG(n, cp);
738                                 if (n > MAXIMUM_TTL) {
739                                         ns_info(ns_log_load,
740                            "%s: Line %d: SOA minimum TTL > %u; converted to 0",
741                                                 filename, lineno, MAXIMUM_TTL);
742                                         zp->z_minimum = 0;
743                                 } else
744                                         zp->z_minimum = n;
745                                 if (default_ttl == USE_MINIMUM)
746                                         ttl = n;
747                                 n = cp - (char *)data;
748                                 if (multiline) {
749                                         buf[0] = getnonblank(fp, filename);
750                                         buf[1] = '\0';
751                                         if (buf[0] != ')')
752                                                 ERRTO("SOA \")\"");
753                                         endline(fp);
754                                 }
755                                 read_soa++;
756                                 if (zp->z_type == Z_PRIMARY)
757                                         fixup_soa(filename, zp);
758                                 break;
759
760                         case ns_t_wks:
761                                 /* Address */
762                                 if (!inet_aton(buf, &ina))
763                                         ERRTO("WKS IP Address");
764                                 (void) ina_put(ina, data);
765                                 /* Protocol */
766                                 data[INADDRSZ] = getprotocol(fp, filename);
767                                 /* Services */
768                                 n = getservices(NS_INT32SZ + sizeof(char),
769                                                 (char *)data, fp, filename);
770                                 break;
771
772                         case ns_t_ns:
773                                 if (ns_samename(zp->z_origin, domain) == 1)
774                                         read_ns++;
775                                 context = hostname_ctx;
776                                 goto cname_etc;
777                         case ns_t_cname:
778                         case ns_t_mb:
779                         case ns_t_mg:
780                         case ns_t_mr:
781                                 context = domain_ctx;
782                                 goto cname_etc;
783                         case ns_t_ptr:
784                                 context = ns_ptrcontext(domain);
785                         cname_etc:
786                                 (void) strcpy((char *)data, buf);
787                                 MAKENAME_OK((char *)data);
788                                 n = strlen((char *)data) + 1;
789                                 break;
790
791                         case ns_t_naptr:
792                         /* Order Preference Flags Service Replacement Regexp */
793                                 n = 0;
794                                 cp = buf;
795                                 /* Order */
796                                 while (isdigit(*cp))
797                                         n = n * 10 + (*cp++ - '0');
798                                 /* catch bad values */
799                                 if (cp == buf || n > 65535)
800                                         ERRTO("NAPTR Order");
801                                 cp = (char *)data;
802                                 PUTSHORT((u_int16_t)n, cp);
803
804                                 /* Preference */
805                                 n = getnum(fp, filename, GETNUM_NONE);
806                                 if (getnum_error || n > 65536)
807                                         ERRTO("NAPTR Preference");
808                                 PUTSHORT((u_int16_t)n, cp);
809
810                                 /* Flags */
811                                 if (!getword(buf, sizeof buf, fp, 0))
812                                         ERRTO("NAPTR Flags");
813                                 n = strlen(buf);
814                                 if (n > 255)
815                                         ERRTO("NAPTR Flags too big");
816                                 *cp++ = n;
817                                 memcpy(cp, buf, (int)n);
818                                 cp += n;
819
820                                 /* Service Classes */
821                                 if (!getword(buf, sizeof buf, fp, 0))
822                                         ERRTO("NAPTR Service Classes");
823                                 n = strlen(buf);
824                                 if (n > 255)
825                                         ERRTO("NAPTR Service Classes too big");
826                                 *cp++ = n;
827                                 memcpy(cp, buf, (int)n);
828                                 cp += n;
829
830                                 /* Pattern */
831                                 if (!getword(buf, sizeof buf, fp, 0))
832                                         ERRTO("NAPTR Pattern");
833                                 n = strlen(buf);
834                                 if (n > 255)
835                                         ERRTO("NAPTR Pattern too big");
836                                 *cp++ = n;
837                                 memcpy(cp, buf, (int)n);
838                                 cp += n;
839
840                                 /* Replacement */
841                                 if (!getword(buf, sizeof buf, fp, 1))
842                                         ERRTO("NAPTR Replacement");
843                                 n = strlen(buf);
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;
848                                 MAKENAME_OK(cp);
849                                 /* advance pointer to end of data */
850                                 cp += strlen((char *)cp) +1;
851
852                                 /* now save length */
853                                 n = (cp - (char *)data);
854                                 break;
855
856
857                         case ns_t_mx:
858                         case ns_t_afsdb:
859                         case ns_t_rt:
860                         case ns_t_srv:
861                                 n = 0;
862                                 cp = buf;
863                                 while (isdigit(*cp))
864                                         n = n * 10 + (*cp++ - '0');
865                                 /* catch bad values */
866                                 if ((cp == buf) || (n > 65535))
867                                         ERRTO("Priority");
868                                 cp = (char *)data;
869                                 PUTSHORT((u_int16_t)n, cp);
870
871                                 if (type == ns_t_srv) {
872                                         n = getnum(fp, filename, GETNUM_NONE);
873                                         if (getnum_error || n > 65536)
874                                                 ERRTO("SRV RR");
875                                         PUTSHORT((u_int16_t)n, cp);
876
877                                         n = getnum(fp, filename, GETNUM_NONE);
878                                         if (getnum_error || n > 65536)
879                                                 ERRTO("SRV RR");
880                                         PUTSHORT((u_int16_t)n, cp);
881                                 }
882
883                                 if (!getword(buf, sizeof buf, fp, 1))
884                                         ERRTO("Domain Name");
885                                 (void) strcpy((char *)cp, buf);
886                                 context = hostname_ctx;
887                                 MAKENAME_OK(cp);
888                                 /* advance pointer to end of data */
889                                 cp += strlen((char *)cp) +1;
890
891                                 /* now save length */
892                                 n = (cp - (char *)data);
893                                 break;
894
895                         case ns_t_px:
896                                 context = domain_ctx;
897                                 n = 0;
898                                 data[0] = '\0';
899                                 cp = buf;
900                                 while (isdigit(*cp))
901                                         n = n * 10 + (*cp++ - '0');
902                                 /* catch bad values */
903                                 if ((cp == buf) || (n > 65535))
904                                         ERRTO("PX Priority");
905                                 cp = (char *)data;
906                                 PUTSHORT((u_int16_t)n, cp);
907
908                                 if (!getword(buf, sizeof buf, fp, 0))
909                                         ERRTO("PX Domain1");
910                                 (void) strcpy((char *)cp, buf);
911                                 MAKENAME_OK(cp);
912                                 /* advance pointer to next field */
913                                 cp += strlen((char *)cp) + 1;
914                                 if (!getword(buf, sizeof buf, fp, 0))
915                                         ERRTO("PX Domain2");
916                                 (void) strcpy((char *)cp, buf);
917                                 MAKENAME_OK(cp);
918                                 /* advance pointer to end of data */
919                                 cp += strlen((char *)cp) + 1;
920
921                                 /* now save length */
922                                 n = (cp - (char *)data);
923                                 break;
924
925                         case ns_t_hinfo:
926                                 n = getcharstring(buf, (char *)data, type,
927                                                   2, 2, fp, filename);
928                                 if (n == 0)
929                                         ERRTO("HINFO RR");
930                                 break;
931
932                         case ns_t_isdn:
933                                 n = getcharstring(buf, (char *)data, type,
934                                                   1, 2, fp, filename);
935                                 if (n == 0)
936                                         ERRTO("ISDN RR");
937                                 break;
938
939                         case ns_t_txt:
940                                 n = getcharstring(buf, (char *)data, type,
941                                                   1, 0, fp, filename);
942                                 if (n == 0)
943                                         ERRTO("TXT RR");
944                                 break;
945
946
947                         case ns_t_x25:
948                                 n = getcharstring(buf, (char *)data, type,
949                                                   1, 1, fp, filename);
950                                 if (n == 0)
951                                         ERRTO("X25 RR");
952                                 break;
953
954                         case ns_t_nsap:
955                                 n = inet_nsap_addr(buf, (u_char *)data,
956                                                    sizeof data);
957                                 if (n == 0)
958                                         ERRTO("NSAP RR");
959                                 endline(fp);
960                                 break;
961
962                         case ns_t_aaaa:
963                                 if (inet_pton(AF_INET6, buf, data) <= 0)
964                                         ERRTO("IPv4 Address");
965                                 n = NS_IN6ADDRSZ;
966                                 endline(fp);
967                                 break;
968
969                         case ns_t_nxt:
970                         case ns_t_key: 
971                         case ns_t_cert:
972                         case ns_t_sig: {
973                                 char *errmsg = NULL;
974                                 int ret = parse_sec_rdata(buf, sizeof(buf), 0,
975                                                           data, sizeof(data),
976                                                           fp, zp, domain, ttl,
977                                                           type, domain_ctx,
978                                                           transport, &errmsg);
979                                 if (ret < 0) {
980                                         errtype = errmsg;
981                                         goto err;
982                                 }
983                                 else
984                                         n = ret;
985                                 break;
986                         }
987
988
989                         case ns_t_loc:
990                                 cp = buf + (n = strlen(buf));
991                                 *cp = ' ';
992                                 cp++;
993                                 n++;
994                                 while ((i = getc(fp), *cp = i, i != EOF)
995                                        && *cp != '\n'
996                                        && (n < MAXDATA)) {
997                                         cp++; n++;
998                                 }
999                                 if (*cp == '\n') /* leave \n for getword */
1000                                         ungetc(*cp, fp);
1001                                 *cp = '\0';
1002                                 /* now process the whole line */
1003                                 n = loc_aton(buf, (u_char *)data);
1004                                 if (n == 0)
1005                                         goto err;
1006                                 endline(fp);
1007                                 break;
1008
1009
1010                         default:
1011                                 goto err;
1012                         }
1013                         /*
1014                          * Ignore data outside the zone.
1015                          */
1016                         if (zp->z_type != Z_CACHE &&
1017                             !ns_samedomain(domain, zp->z_origin))
1018                         {
1019                                 ns_info(ns_log_load,
1020                             "%s:%d: data \"%s\" outside zone \"%s\" (ignored)",
1021                                         filename, lineno, domain,
1022                                         zp->z_origin);
1023                                 continue;
1024                         }
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;
1030                         dp->d_clev = clev;
1031                         c = db_set_update(domain, dp, &state, dbflags,
1032                                           (dataflags & DB_F_HINT) != 0 ?
1033                                           &fcachetab : &hashtab, 
1034                                           empty_from, &rrcount, lineno,
1035                                           filename);
1036                         if (c == CNAMEANDOTHER)
1037                                 errs++;
1038                         continue;
1039
1040                 case ERRTOK:
1041                         break;
1042                 }
1043  err:
1044                 errs++;
1045                 ns_notice(ns_log_load, "%s:%d: %s error near (%s)",
1046                           filename, empty_token ? (lineno - 1) : lineno,
1047                           errtype, buf);
1048                 if (!empty_token)
1049                         endline(fp);
1050         }
1051         c = db_set_update(NULL, NULL, &state, dbflags,
1052                           (dataflags & DB_F_HINT) ? &fcachetab : &hashtab,
1053                           empty_from, &rrcount, lineno, filename);
1054         if (c != OK) {
1055                 if (c == CNAMEANDOTHER)
1056                         errs++;
1057         }
1058
1059         (void) my_fclose(fp);
1060         lineno = slineno;
1061         if (!ininclude) {
1062                 if (didinclude) {
1063                         zp->z_flags |= Z_INCLUDE;
1064                         zp->z_ftime = 0;
1065                 } else
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;
1070
1071                         if (read_soa == 0)
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";
1077                         else if (!rrcount)
1078                                 msg = "no relevant RRs found";
1079                         if (msg != NULL) {
1080                                 errs++;
1081                                 ns_warning(ns_log_load,
1082                                            "Zone \"%s\" (file %s): %s",
1083                                            zp->z_origin, filename, msg);
1084                         }
1085                 }
1086                 while (filenames) {
1087                         fn = filenames;
1088                         filenames = filenames->next;
1089                         freestr(fn->name);
1090                         memput(fn, sizeof *fn);
1091                 }
1092                 if (errs != 0)
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);
1097                 else
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);
1102         }
1103         if (errs != 0) {
1104                 zp->z_flags |= Z_DB_BAD;
1105                 zp->z_ftime = 0;
1106         }
1107 #ifdef BIND_NOTIFY
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);
1111 #endif
1112         return (errs);
1113 }
1114
1115 void
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", 
1122                          domain, type);
1123 }
1124
1125 static int
1126 gettoken(FILE *fp, const char *src) {
1127         int c;
1128         char op[32];
1129
1130         for (;;) {
1131                 c = getc(fp);
1132  top:
1133                 switch (c) {
1134                 case EOF:
1135                         return (EOF);
1136
1137                 case '$':
1138                         if (getword(op, sizeof op, fp, 0)) {
1139                                 if (!strcasecmp("include", op))
1140                                         return (INCLUDE);
1141                                 if (!strcasecmp("origin", op))
1142                                         return (ORIGIN);
1143                                 if (!strcasecmp("generate", op))
1144                                         return (GENERATE);
1145                                 if (!strcasecmp("ttl", op))
1146                                         return (DEFAULTTTL);
1147                         }
1148                         ns_notice(ns_log_db,
1149                                   "%s:%d: Unknown $ option: $%s", 
1150                                   src, lineno, op);
1151                         return (ERRTOK);
1152
1153                 case ';':
1154                         while ((c = getc(fp)) != EOF && c != '\n')
1155                                 ;
1156                         goto top;
1157
1158                 case ' ':
1159                 case '\t':
1160                         return (CURRENT);
1161
1162                 case '.':
1163                         return (DOT);
1164
1165                 case '@':
1166                         return (AT);
1167
1168                 case '\n':
1169                         lineno++;
1170                         continue;
1171
1172                 case '\r':
1173                         if (NS_OPTION_P(OPTION_TREAT_CR_AS_SPACE) != 0)
1174                                 return (CURRENT);
1175
1176                 default:
1177                         (void) ungetc(c, fp);
1178                         return (DNAME);
1179                 }
1180         }
1181 }
1182
1183 /* int
1184  * getword(buf, size, fp, preserve)
1185  *      get next word, skipping blanks & comments.
1186  *      '\' '\n' outside of "quotes" is considered a blank.
1187  * parameters:
1188  *      buf - destination
1189  *      size - of destination
1190  *      fp - file to read from
1191  *      preserve - should we preserve \ before \\ and \.?
1192  *   if preserve == 2, then keep all \
1193  * return value:
1194  *      0 = no word; perhaps EOL or EOF; lineno was incremented.
1195  *      1 = word was read
1196  */
1197 int
1198 getword(char *buf, size_t size, FILE *fp, int preserve) {
1199         char *cp = buf;
1200         int c, spaceok, once;
1201
1202         empty_token = 0;        /* XXX global side effect. */
1203         once = 0;
1204         while ((c = getc(fp)) != EOF) {
1205                 once++;
1206                 if (c == ';') {
1207                         /* Comment.  Skip to end of line. */
1208                         while ((c = getc(fp)) != EOF && c != '\n')
1209                                 (void)NULL;
1210                         c = '\n';
1211                 }
1212                 if (c == '\n') {
1213                         /*
1214                          * Unescaped newline.  It's a terminator unless we're
1215                          * already midway into a token.
1216                          */
1217                         if (cp != buf)
1218                                 ungetc(c, fp);
1219                         else
1220                                 lineno++;
1221                         break;
1222                 }
1223                 if (c == '"') {
1224                         /* "Quoted string."  Gather the whole string here. */
1225                         while ((c = getc(fp)) != EOF && c!='"' && c!='\n') {
1226                                 if (c == '\\') {
1227                                         if ((c = getc(fp)) == EOF)
1228                                                 c = '\\';
1229                                         if (preserve)
1230                                                 switch (c) {
1231                                                 default:
1232                                                         if (preserve == 1)
1233                                                                 break;
1234                                                 case '\\':
1235                                                 case '.':
1236                                                 case '0':
1237                                                 case '1':
1238                                                 case '2':
1239                                                 case '3':
1240                                                 case '4':
1241                                                 case '5':
1242                                                 case '6':
1243                                                 case '7':
1244                                                 case '8':
1245                                                 case '9':
1246                                                         if (cp >= buf+size-1)
1247                                                                 break;
1248                                                         *cp++ = '\\';
1249                                                 }
1250                                         if (c == '\n')
1251                                                 lineno++;
1252                                 }
1253                                 if (cp >= buf+size-1)
1254                                         break;
1255                                 *cp++ = c;
1256                         }
1257                         /*
1258                          * Newline string terminators are
1259                          * not token terminators.
1260                          */
1261                         if (c == '\n') {
1262                                 lineno++;
1263                                 break;
1264                         }
1265                         /* Sample following character, check for terminator. */
1266                         if ((c = getc(fp)) != EOF)
1267                                 ungetc(c, fp);
1268                         if (c == EOF || isspace(c)) {
1269                                 *cp = '\0';
1270                                 return (1);
1271                         }
1272                         continue;
1273                 }
1274                 spaceok = 0;
1275                 if (c == '\\') {
1276                         /* Do escape processing. */
1277                         if ((c = getc(fp)) == EOF)
1278                                 c = '\\';
1279                         if (preserve)
1280                                 switch (c) {
1281                                 default:
1282                                         if (preserve == 1)
1283                                                 break;
1284                                 case '\\':
1285                                 case '.':
1286                                 case '0':
1287                                 case '1':
1288                                 case '2':
1289                                 case '3':
1290                                 case '4':
1291                                 case '5':
1292                                 case '6':
1293                                 case '7':
1294                                 case '8':
1295                                 case '9':
1296                                         if (cp >= buf+size-1)
1297                                                 break;
1298                                         *cp++ = '\\';
1299                                 }
1300                         if (c == ' ' || c == '\t')
1301                                 spaceok++;
1302                 }
1303                 if (isspace(c) && !spaceok) {
1304                         /* Blank of some kind.  Skip run. */
1305                         while (isspace(c = getc(fp)) && c != '\n')
1306                                 (void)NULL;
1307                         ungetc(c, fp);
1308                         /* Blank means terminator if the token is nonempty. */
1309                         if (cp != buf)          /* Trailing whitespace */
1310                                 break;
1311                         continue;               /* Leading whitespace */
1312                 }
1313                 if (cp >= buf + size - 1)
1314                         break;
1315                 *cp++ = (char)c;
1316         }
1317         *cp = '\0';
1318         if (cp == buf)
1319                 empty_token = 1;
1320         if (!once)
1321                 lineno++;
1322         return (cp != buf);
1323 }
1324
1325 /*
1326  * int
1327  * getttl(fp, fn, ln, ttl, multiline)
1328  *      read a word from the file and parse it as a TTL.
1329  * return:
1330  *      1 ttl found
1331  *      0 word not read (EOF or EOL?)
1332  *      -1 word read but it wasn't a ttl
1333  * side effects:
1334  *      *ttl is written if the return value is to be 1.
1335  */
1336 int
1337 getttl(FILE *fp, const char *fn, int lineno, u_int32_t *ttl, int *multiline) {
1338         char buf[MAXDATA];
1339         u_long tmp;
1340         int ch;
1341         int len;
1342
1343         while (!feof(fp) && !getword(buf, sizeof buf, fp, 0) && *multiline)
1344                 (void)NULL;
1345         len = strlen(buf);
1346         if (*multiline && len && buf[len-1] == ')') {
1347                 buf[len-1] = '\0';
1348                 *multiline = 0;
1349         }
1350         if (ns_parse_ttl(buf, &tmp) < 0) {
1351                 ns_notice(ns_log_db, "%s:%d: expected a TTL, got \"%s\"",
1352                           fn, lineno, buf);
1353                 return (-1);
1354         }
1355         if (*multiline) {
1356                 ch = getnonblank(fp, fn);
1357                 if (ch == EOF)
1358                         return (-1);
1359                 if (ch == ';')
1360                         endline(fp);
1361                 else
1362                         ungetc(ch, fp);
1363         }
1364         *ttl = (u_int32_t)tmp;
1365         return (1);
1366 }
1367
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)
1374 */
1375 static int
1376 getmlword(char *buf, size_t size, FILE *fp, int preserve) {
1377         char *p;
1378         
1379         do {
1380                 while (!getword (buf, size, fp, preserve)) {
1381                         /* No more words on this line.  See if doing the
1382                            multiline thing. */
1383                         if (!getmlword_nesting) {       /* Nope... */
1384                                 ungetc('\n', fp);       /* Push back newline */
1385                                 lineno--;               /* Unbump the lineno */
1386                                 empty_token = 0;        /* Undo this botch */
1387                                 return 0;
1388                         }
1389                         if (feof(fp) || ferror(fp))
1390                                 return 0;       /* Error, no terminating ')' */
1391                         /* Continue reading til we get a word... */
1392                 }
1393                 while ('(' == *buf) {
1394                         /* Word starts with paren.  Multiline mode.
1395                            Move the rest of the word down over the paren.  */
1396                         getmlword_nesting++;
1397                         p = buf;
1398                         while (0 != (p[0]=p[1]))  p++;
1399                 }
1400                 while (')' == *buf) {
1401                         getmlword_nesting--;
1402                         p = buf;
1403                         while (0 != (p[0]=p[1]))  p++;
1404                 }
1405         } while (buf[0] == 0);  /* loop til we get a non-( non-) word */
1406
1407         return 1;               /* Got a word... */
1408 }
1409
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
1418 */
1419 static int
1420 getallwords(char *buf, size_t size, FILE *fp, int preserve) {
1421         char *runningbuf  = buf;
1422         int runningsize = size;
1423         int len;
1424
1425         while (runningsize > 0) {
1426                 if (!getmlword (runningbuf, runningsize, fp, preserve)) {
1427                         return runningbuf!=buf;         /* 1 or 0 */
1428                 }
1429                 len = strlen(runningbuf);
1430                 runningbuf += len;
1431                 runningsize -= len;
1432         }
1433         return -1;                      /* Error, String too long */
1434 }
1435
1436 int
1437 getnum(FILE *fp, const char *src, int opt) {
1438         int c, n;
1439         int seendigit = 0;
1440         int seendecimal = 0;
1441         int m = 0;
1442         int allow_dots = 0;
1443
1444         getnum_error = 0;
1445 #ifdef DOTTED_SERIAL
1446         if (opt & GETNUM_SERIAL)
1447                 allow_dots++;
1448 #endif
1449         for (n = 0; (c = getc(fp)) != EOF; ) {
1450                 if (isspace(c)) {
1451                         if (c == '\n')
1452                                 lineno++;
1453                         if (seendigit)
1454                                 break;
1455                         continue;
1456                 }
1457                 if (c == ';') {
1458                         while ((c = getc(fp)) != EOF && c != '\n')
1459                                 ;
1460                         if (c == '\n')
1461                                 lineno++;
1462                         if (seendigit)
1463                                 break;
1464                         continue;
1465                 }
1466                 if (getnum_error)
1467                         continue;
1468                 if (!isdigit(c)) {
1469                         if (c == ')' && seendigit) {
1470                                 (void) ungetc(c, fp);
1471                                 break;
1472                         }
1473                         if (seendigit && (opt & GETNUM_SCALED) &&
1474                             strchr("KkMmGg", c) != NULL) {
1475                                 switch (c) {
1476                                 case 'K': case 'k':
1477                                         n *= 1024;
1478                                         break;
1479                                 case 'M': case 'm':
1480                                         n *= (1024 * 1024);
1481                                         break;
1482                                 case 'G': case 'g':
1483                                         n *= (1024 * 1024 * 1024);
1484                                         break;
1485                                 }
1486                                 break;
1487                         }
1488                         if (seendecimal || c != '.' || !allow_dots) {
1489                                 ns_notice(ns_log_db,
1490                                           "%s:%d: expected a number",
1491                                           src, lineno);
1492                                 getnum_error = 1;
1493                         } else {
1494                                 if (!seendigit)
1495                                         n = 1;
1496 #ifdef SENSIBLE_DOTS
1497                                 n *= 10000;
1498 #else
1499                                 n *= 1000;
1500 #endif
1501                                 seendigit = 1;
1502                                 seendecimal = 1;
1503                         }
1504                         continue;
1505                 }
1506 #ifdef SENSIBLE_DOTS
1507                 if (seendecimal)
1508                         m = m * 10 + (c - '0');
1509                 else
1510                         n = n * 10 + (c - '0');
1511 #else
1512                 n = n * 10 + (c - '0');
1513 #endif
1514                 seendigit = 1;
1515         }
1516         if (getnum_error)
1517                 return (0);
1518         if (m > 9999) {
1519                 ns_info(ns_log_db, 
1520                         "%s:%d: number after the decimal point exceeds 9999", 
1521                         src, lineno);
1522                 getnum_error = 1;
1523                 return (0);
1524         }
1525         if (seendecimal) {
1526                 ns_info(ns_log_db,
1527                         "%s:%d: decimal serial number interpreted as %d",
1528                         src, lineno, n+m);
1529         }
1530         return (n + m);
1531 }
1532
1533 #ifndef BIND_UPDATE
1534 static
1535 #endif
1536 int
1537 getnonblank(FILE *fp, const char *src) {
1538         int c;
1539
1540         while ((c = getc(fp)) != EOF) {
1541                 if (isspace(c)) {
1542                         if (c == '\n')
1543                                 lineno++;
1544                         continue;
1545                 }
1546                 if (c == ';') {
1547                         while ((c = getc(fp)) != EOF && c != '\n')
1548                                 ;
1549                         if (c == '\n')
1550                                 lineno++;
1551                         continue;
1552                 }
1553                 return (c);
1554         }
1555         ns_info(ns_log_db, "%s:%d: unexpected EOF", src, lineno);
1556         return (EOF);
1557 }
1558
1559 /*
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".
1569  */
1570
1571 static int
1572 genname(char *name, int it, const char *origin, char *buf, int size) {
1573         char *bp = buf;
1574         char *eom = buf + size;
1575         char *cp;
1576         char numbuf[32];
1577         char fmt[32];
1578         int delta = 0;
1579         int width;
1580
1581         while (*name) {
1582                 if (*name == '$') {
1583                         if (*(++name) == '$') {
1584                                 /* should be deprecated.  how? */
1585                                 if (bp >= eom)
1586                                         return (-1);
1587                                 *bp++ = *name++;
1588                         } else {
1589                                 strcpy(fmt, "%d");
1590                                 if (*name == '{') {
1591                                         switch (sscanf(name, "{%d,%d,%1[doxX]}", &delta, &width, numbuf)) {
1592                                         case 1:
1593                                                 break;
1594                                         case 2:
1595                                                 sprintf(fmt, "%%0%dd", width);
1596                                                 break;
1597                                         case 3:
1598                                                 sprintf(fmt, "%%0%d%c", width, numbuf[0]);
1599                                                 break;
1600                                         default:
1601                                                 return (-1);
1602                                         }
1603                                         while (*name && *name++ != '}') {
1604                                                 continue;
1605                                         }
1606                                 }
1607                                 sprintf(numbuf, fmt, it + delta);
1608                                 cp = numbuf;
1609                                 while (*cp) {
1610                                         if (bp >= eom)
1611                                                 return (-1);
1612                                         *bp++ = *cp++;
1613                                 }
1614                         }
1615                 } else if (*name == '\\') {
1616                         if (*(++name) == '\0') {
1617                                 if (bp >= eom)
1618                                         return (-1);
1619                                 *bp++ = '\\';
1620                         } else {
1621                                 switch (*name) {
1622                                 case '\\':
1623                                 case '.':
1624                                 case '0':
1625                                 case '1':
1626                                 case '2':
1627                                 case '3':
1628                                 case '4':
1629                                 case '5':
1630                                 case '6':
1631                                 case '7':
1632                                 case '8':
1633                                 case '9':
1634                                         if (bp >= eom)
1635                                                 return (-1);
1636                                         *bp++ = '\\';
1637                                 default:
1638                                         if (bp >= eom)
1639                                                 return (-1);
1640                                         *bp++ = *name++;
1641                                 }
1642                         }
1643                 } else {
1644                         if (bp >= eom)
1645                                 return (-1);
1646                         *bp++ = *name++;
1647                 }
1648         }
1649         if (bp >= eom)
1650                 return (-1);
1651         *bp = '\0';
1652         return (origin == NULL ? 0 : makename(buf, origin, size));
1653 }
1654
1655
1656 /*
1657  * Take name and fix it according to following rules:
1658  * "." means root.
1659  * "@" means current origin.
1660  * "name." means no changes.
1661  * "name" means append origin.
1662  */
1663 int
1664 makename(char *name, const char *origin, int size) {
1665         int n;
1666         u_char domain[MAXCDNAME];
1667
1668         switch (ns_name_pton(name, domain, sizeof(domain))) {
1669         case -1:
1670                 return (-1);
1671         case 1:         /* FULLY QUALIFIED */
1672                 break;
1673         case 0:         /* UNQUALIFIED */
1674                 if (strcmp(name, "@") == 0) /* must test raw name */
1675                         domain[0] = 0;
1676                 if ((n = dn_skipname(domain, domain+sizeof(domain))) == -1)
1677                         return (-1);
1678                 /* step back over root, append origin */
1679                 switch (ns_name_pton(origin, domain+n-1, sizeof(domain)-n+1)) {
1680                 case -1:
1681                         return (-1);
1682                 case 0:
1683                 case 1:
1684                         break;
1685                 }
1686                 break;
1687         }
1688         if (ns_name_ntop(domain, name, size) == -1)
1689                 return (-1);
1690         if (name[0] == '.')     /* root */
1691                 name[0] = '\0';
1692         return (0);
1693 }
1694
1695 int
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)
1699 {
1700         int ret = 1;
1701
1702         if (makename(name, origin, size) == -1) {
1703                 ns_info(ns_log_db, "%s:%d: makename failed",
1704                         filename, lineno);
1705                 return (0);
1706         }
1707         if (!ns_nameok(NULL, name, class, zp, transport, context, owner,
1708                        inaddr_any)) {
1709                 ns_info(ns_log_db, "%s:%d: database naming error",
1710                         filename, lineno);
1711                 ret = 0;
1712         }
1713         return (ret);
1714 }
1715
1716 void
1717 endline(FILE *fp) {
1718         int c;
1719
1720         while ((c = getc(fp)) != '\0') {
1721                 if (c == '\n') {
1722                         (void) ungetc(c,fp);
1723                         break;
1724                 } else if (c == EOF) {
1725                         break;
1726                 }
1727         }
1728 }
1729
1730 #define MAXPORT 1024
1731 #define MAXLEN 24
1732
1733 #ifndef BIND_UPDATE
1734 static
1735 #endif
1736 char
1737 getprotocol(FILE *fp, const char *src) {
1738         int k;
1739         char b[MAXLEN];
1740
1741         (void) getword(b, sizeof(b), fp, 0);
1742                 
1743         k = protocolnumber(b);
1744         if (k == -1)
1745                 ns_info(ns_log_db, "%s:%d: unknown protocol: %s.",
1746                         src, lineno, b);
1747         return ((char) k);
1748 }
1749
1750 #ifndef BIND_UPDATE
1751 static
1752 #endif
1753 int
1754 getservices(int offset, char *data, FILE *fp, const char *src) {
1755         int j, ch, k, maxl, bracket;
1756         char bm[MAXPORT/8];
1757         char b[MAXLEN];
1758
1759         for (j = 0; j < MAXPORT/8; j++)
1760                 bm[j] = 0;
1761         maxl = 0;
1762         bracket = 0;
1763         while (getword(b, sizeof(b), fp, 0) || bracket) {
1764                 if (feof(fp) || ferror(fp))
1765                         break;
1766                 if (strlen(b) == 0)
1767                         continue;
1768                 if (b[0] == '(') {
1769                         bracket++;
1770                         continue;
1771                 }
1772                 if (b[0] == ')') {
1773                         bracket = 0;
1774                         while ((ch = getc(fp)) != EOF && ch != '\n')
1775                                 (void)NULL;
1776                         if (ch == '\n')
1777                                 lineno++;
1778                         break;
1779                 }
1780                 k = servicenumber(b);
1781                 if (k == -1) {
1782                         ns_info(ns_log_db,
1783                                 "%s:%d: Unknown service '%s'",
1784                                 src, lineno, b);
1785                         continue;
1786                 }
1787                 if ((k < MAXPORT) && (k)) {
1788                         bm[k/8] |= (0x80>>(k%8));
1789                         if (k > maxl)
1790                                 maxl = k;
1791                 } else {
1792                         ns_info(ns_log_db,
1793                                 "%s:%d: port no. (%d) too big",
1794                                 src, lineno, k);
1795                 }
1796         }
1797         if (bracket)
1798                 ns_info(ns_log_db, "%s:%d: missing close paren",
1799                         src, lineno);
1800         maxl = maxl/8+1;
1801         memcpy(data+offset, bm, maxl);
1802         return (maxl+offset);
1803 }
1804
1805 /*
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.
1808  */
1809 static u_int32_t
1810 wordtouint32(buf)
1811         char *buf;
1812 {
1813         u_long result;
1814         u_int32_t res2;
1815         char *bufend;
1816
1817         wordtouint32_error = 0;
1818         result = strtoul(buf, &bufend, 0);
1819         if (bufend == buf)
1820                 wordtouint32_error = 1;
1821         else
1822                 while ('\0' != *bufend) {
1823                         if (isspace(*bufend))
1824                                 bufend++;
1825                         else {
1826                                 wordtouint32_error = 1;
1827                                 break;
1828                         }
1829                 }
1830         /* Check for truncation between u_long and u_int32_t */
1831         res2 = result;
1832         if (res2 != result)             
1833                 wordtouint32_error = 1;
1834         return (res2);
1835 }
1836
1837 static int
1838 getcharstring(char *buf, char *data, int type,
1839               int minfields, int maxfields,
1840               FILE *fp, const char *src)
1841 {
1842         int nfield = 0, done = 0, n = 0, i;
1843         char *b = buf;
1844
1845         do {
1846                 nfield++;
1847                 i = strlen(buf);
1848 #ifdef ALLOW_LONG_TXT_RDATA
1849                 b = buf;
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;
1856                                 b += MAXCHARSTRING;
1857                                 i -= MAXCHARSTRING;
1858                         }
1859                 }
1860 #endif /* ALLOW_LONG_TXT_RDATA */
1861                 if (i > MAXCHARSTRING) {
1862                         ns_info(ns_log_db,
1863                                 "%s:%d: RDATA field %d too long",
1864                                 src, lineno -1, nfield);
1865                         return (0);
1866                 }
1867                 if (n + i + 1 > MAXDATA) {
1868                         ns_info(ns_log_db,
1869                                 "%s:%d: total RDATA too long",
1870                                 src, lineno -1);
1871                         return (0);
1872                 }
1873                 data[n] = i;
1874                 memmove(data + n + 1, b, (int)i);
1875                 n += i + 1;
1876                 done = (maxfields && nfield >= maxfields);
1877         } while (!done && getword(buf, MAXDATA, fp, 0));
1878
1879         if (nfield < minfields) {
1880                 ns_info(ns_log_db,
1881                         "%s:%d: expected %d RDATA fields, only saw %d",
1882                         src, lineno -1, minfields, nfield);
1883                 return (0);
1884         }
1885
1886         if (done)
1887                 endline(fp);
1888
1889         return (n);
1890 }
1891
1892
1893 /* 
1894  * get_nxt_types(): Read the list of types in the NXT record.
1895  *
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 
1900  *
1901  * The result is how many bytes are significant in the result.
1902  * ogud@tis.com 1995
1903  */
1904 static int
1905 get_nxt_types(u_char *data, FILE *fp, const char *filename) {
1906         char b[MAXLABEL];       /* Not quite the right size, but good enough */
1907         int maxtype=0;
1908         int success;
1909         int type;
1910         int errs = 0;
1911
1912         memset(data, 0, NS_NXT_MAX/NS_NXT_BITS+1);
1913
1914         while (getmlword(b, sizeof(b), fp, 0)) {
1915                 if (feof(fp) || ferror(fp))
1916                         break;
1917                 if (strlen(b) == 0 || b[0] == '\n')
1918                         continue;
1919
1920                 /* Parse RR type (A, MX, etc) */
1921                 type = sym_ston(__p_type_syms, (char *)b, &success);
1922                 if ((!success) || type == ns_t_any) {
1923                         errs++;
1924                         ns_info(ns_log_db,
1925                                 "%s: Line %d: Unknown type: %s in NXT record.",
1926                                 filename, lineno, b);
1927                         continue;
1928                 }
1929                 NS_NXT_BIT_SET(type, data);
1930                 if (type > maxtype)
1931                         maxtype = type;
1932         }
1933         if (errs)
1934                 return (0);
1935         else
1936                 return (maxtype/NS_NXT_BITS+1);
1937 }
1938
1939 /* sanity checks PRIMARY ONLY */
1940 static void
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);
1947
1948         /* Sanity. */
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);
1954
1955         /*
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)
1959          */
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)",
1963                            fn, zp->z_expire);
1964
1965         /*
1966          * Sanity: maximum down time if we havn't talked for six months 
1967          * war must have broken out.
1968          */
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)",
1972                            fn, zp->z_expire);
1973
1974         /* Sanity. */
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);
1979 }
1980
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
1985  *
1986  */
1987
1988 static int
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)
1992 {
1993 /* The SIG record looks like this in the db file:
1994    Name Cl SIG RRtype Algid [OTTL] Texp Tsig Kfoot Signer Sig
1995   
1996    where:  Name and Cl are as usual
1997    SIG     is a keyword
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
2010    text RR.
2011   
2012    It's too crazy to run these pages of SIG code at the right
2013    margin.  I'm exdenting them for readability.
2014 */
2015         u_int32_t sig_type;
2016         int dateerror;
2017         int siglen, success;
2018         u_char *cp;
2019         u_int32_t al, la, n;
2020         u_int32_t signtime, exptime, timetilexp;
2021         u_int32_t origTTL;
2022         enum context context;
2023         time_t now;
2024         char *errtype = "SIG error";
2025         int i, my_buf_size = MAXDATA, errs = 0;
2026
2027         
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;
2036
2037         i = 0;
2038         data[i] = '\0';
2039         
2040         getmlword_nesting = 0; /* KLUDGE err recovery */
2041         
2042         /* RRtype (char *)
2043          * if old style inp will contain the next token
2044          *copy that into buffer, otherwise read from file
2045          */
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) {
2051                 /*
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".
2057                  */
2058                 sig_type = wordtouint32 (buf);
2059                 if (wordtouint32_error || sig_type > 0xFFFF)
2060                         ERRTO("Unknown RR type in SIG record");
2061         }
2062         cp = &data[i];
2063         PUTSHORT((u_int16_t)sig_type, cp);
2064         i += 2;
2065         
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;
2073         i++;
2074         
2075         /*
2076          * Labels (8-bit decimal)
2077          */
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;
2084         i++;
2085         
2086         /*
2087          * OTTL (optional u_int32_t) and
2088          * Texp (u_int32_t date)
2089          */
2090         if (!getmlword(buf, my_buf_size, fp, 0))
2091                 ERRTO("OTTL and expiration time missing");
2092         /*
2093          * See if OTTL is missing and this is a date.
2094          * This relies on good, silent error checking
2095          * in ns_datetosecs.
2096          */
2097         exptime = ns_datetosecs(buf, &dateerror);
2098         if (!dateerror) {
2099                 /* Output TTL as OTTL */
2100                 origTTL = ttl;
2101                 cp = &data[i];
2102                 PUTLONG (origTTL, cp);
2103                 i += 4;
2104         } else {
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");
2110                 cp = &data[i];
2111                 PUTLONG(origTTL, cp);
2112                 i += 4;
2113                 if (!getmlword(buf, my_buf_size, fp, 0))
2114                         ERRTO("Expiration time missing");
2115                 exptime = ns_datetosecs(buf, &dateerror);
2116         }
2117         if (dateerror || exptime > 0x7fffffff || exptime <= 0)
2118                 ERRTO("Invalid expiration time");
2119         cp = &data[i];
2120         PUTLONG(exptime, cp);
2121         i += 4;
2122         
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");
2129         cp = &data[i];
2130         PUTLONG(signtime, cp);
2131         i += 4;
2132         
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");
2139         cp = &data[i];
2140         PUTSHORT((u_int16_t)n, cp);
2141         i += 2;
2142
2143         /* Signer's Name */
2144         if (!getmlword((char*)buf, my_buf_size, fp, 0))
2145                 ERRTO("Missing signer's name");
2146         cp = &data[i];
2147         strcpy((char *)cp, buf);
2148         context = domain_ctx;
2149         MAKENAME_OKZP((char *)cp, data_size);
2150         i += strlen((char *)cp) + 1;
2151
2152         /*
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.
2156          */
2157         if (!getallwords(buf, my_buf_size, fp, 0)) {
2158                 siglen = 0;
2159         } else {
2160                 cp = &data[i];
2161                 siglen = b64_pton(buf, (u_char*)cp, data_size - i);
2162                 if (siglen < 0)
2163                         ERRTO("Signature block bad");
2164         }
2165         
2166         /* set total length and we're done! */
2167         n = i + siglen;
2168         
2169         /*
2170          * Check signature time, expiration, and adjust TTL.  Note
2171          * that all time values are in GMT (UTC), *not* local time.
2172          */
2173         
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 */
2176         if (ttl > origTTL)
2177                 ERRTO("TTL is greater than signed original TTL");
2178         
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");
2182         
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");
2186         
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);
2193                 ttl = timetilexp;
2194         }
2195
2196         /*
2197          * Check algorithm-ID and key structure, for
2198          * the algorithm-ID's that we know about.
2199          */
2200         switch (al) {
2201         case NS_ALG_MD5RSA:
2202                 if (siglen == 0)
2203                         ERRTO("No key for RSA algorithm");
2204                 if (siglen < 1)
2205                         ERRTO("Signature too short");
2206                 if (siglen > (NS_MD5RSA_MAX_BITS + 7) / 8)
2207                         ERRTO("Signature too long");
2208                 break;
2209                 
2210         case NS_ALG_DH:
2211                 if (siglen < 1)
2212                         ERRTO("DH Signature too short");
2213                 break; /* need more tests here */
2214                 
2215         case NS_ALG_DSA:
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 */
2221                 
2222         case NS_ALG_EXPIRE_ONLY:
2223                 if (siglen != 0)
2224                         ERRTO(
2225                                 "Signature supplied to expire-only algorithm");
2226                 break;
2227         case NS_ALG_PRIVATE_OID:
2228                 if (siglen == 0)
2229                         ERRTO("No ObjectID in key");
2230                 break;
2231         default:
2232                 ERRTO("UNKOWN SIG algorithm");
2233         }
2234
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.  */
2241         
2242         endline(fp);  /* flush the rest of the line */
2243         
2244         return (n);
2245  err:
2246         *errmsg = errtype;
2247         return (-1);
2248 }
2249
2250 static int
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)
2254 {
2255         
2256         /* The NXT record looks like:
2257            Name Cl NXT nextname RRT1 RRT2 MX A SOA ...
2258           
2259            where:  Name and Cl are as usual
2260            NXT     is a keyword
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".
2266
2267            When a NXT record is cryptographically signed, it proves the
2268            nonexistence of an RR (actually a whole set of RR's). 
2269         */
2270         int n, errs = 0, i;
2271         u_char *cp;
2272 /*      char *origin = zp->z_origin;
2273         int class    = zp->z_class; */
2274         *errmsg = "NXT name error";
2275
2276         (void) strcpy((char *)data, buf);
2277         MAKENAME_OKZP((char *)data, data_size);
2278         n = strlen((char *)data) + 1;
2279         cp = n + data;
2280         i = get_nxt_types(cp, fp, zp->z_source);
2281         if( i > 0)
2282                 return (n + i);
2283         *errmsg = "NXT type error";
2284  err:
2285         return (-1);
2286 }
2287
2288
2289 static int
2290 parse_cert_rr(char *buf, int buf_len, u_char *data, int data_size, 
2291               FILE *fp, char **errmsg)
2292 {
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
2299          */
2300         u_char *cp;
2301         u_int32_t cert_type, key_tag, alg;
2302         char *errtype = "CERT parse error";
2303         int certlen, i, n, success;
2304         
2305         i = 0;
2306         cp = &data[i];
2307         cert_type = sym_ston(__p_cert_syms, buf, &success);
2308         if (!success) {
2309                 cert_type = wordtouint32(buf);
2310                 if (wordtouint32_error || cert_type > 0xFFFF)
2311                         ERRTO("CERT type out of range");
2312         }
2313         PUTSHORT((u_int16_t)cert_type, cp);
2314         i += INT16SZ;
2315         
2316         if (!getmlword((char*)buf, buf_len, fp, 0))
2317                 ERRTO("CERT doesn't specify type");
2318         
2319         key_tag = wordtouint32(buf);
2320         if (wordtouint32_error || key_tag > 0xFFFF)
2321                 ERRTO("CERT KEY tag out of range");
2322         
2323         PUTSHORT((u_int16_t)key_tag, cp);
2324         i += INT16SZ;
2325         
2326         if (!getmlword(buf, buf_len, fp, 0))
2327                 ERRTO("CERT missing algorithm ID");
2328         
2329         alg = sym_ston(__p_key_syms, buf, &success);
2330         if (!success) {
2331                 alg = wordtouint32(buf);
2332                 if (wordtouint32_error || alg > 0xFF)
2333                         ERRTO("CERT KEY alg out of range");
2334         }
2335         
2336         data[i++] = (u_char)alg;
2337         
2338         if (!getallwords(buf, buf_len, fp, 0)) {
2339                 certlen = 0;
2340         }
2341         else {
2342                 cp = &data[i];
2343                 certlen = b64_pton(buf, (u_char*)cp, sizeof(data) - i);
2344                 if (certlen < 0)
2345                         ERRTO("CERT blob has encoding error");
2346         }
2347                                 /* set total length */
2348         n = i + certlen;
2349         return (n);
2350  err:
2351         *errmsg = errtype;
2352         return (-1);
2353         
2354 }
2355
2356 static int
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)
2360 {
2361         /* The KEY record looks like this in the db file:
2362          *      Name  Cl KEY Flags  Proto  Algid  PublicKeyData
2363          * where:
2364          *      Name,Cl per usual
2365          *      KEY     RR type
2366          *      Flags   4 digit hex value (unsigned_16)
2367          *      Proto   8 bit u_int
2368          *      Algid   8 bit u_int
2369          *      PublicKeyData
2370          *              a string of base64 digits,
2371          *              skipping any embedded whitespace.
2372          */
2373         u_int32_t al, pr;
2374         int nk, klen,i, n;
2375         u_int32_t keyflags;
2376         char *errtype = "KEY error";
2377         u_char *cp, *expstart;
2378         u_int expbytes, modbytes;
2379
2380         i = n = 0;
2381         data[i] = '\0';
2382         cp = data;
2383         getmlword_nesting = 0; /* KLUDGE err recov. */
2384
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);
2392         
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;
2400         
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;
2408         
2409         /*>>> Extended KEY flag field in bytes 5 and 6 */
2410         if (NS_KEY_EXTENDED_FLAGS & keyflags) {
2411                 u_int32_t keyflags2;
2412                 
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);
2421         }
2422         
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.
2426          */
2427         if (!getallwords(buf, MAXDATA, fp, 0))
2428                 klen = 0;
2429         else {
2430                 /* Convert from BASE64 to binary. */
2431                 klen = b64_pton(buf, (u_char*)cp, 
2432                                 data_size - (cp - data));
2433                 if (klen < 0)
2434                         ERRTO("KEY Public Key");
2435         }
2436         
2437                                 /* set total length */
2438         n = klen + (cp - data);
2439         
2440         /*
2441          * Now check for valid key flags & algs & etc, from the RFC.
2442          */
2443         
2444         if (NS_KEY_TYPE_NO_KEY == (keyflags & NS_KEY_TYPEMASK))
2445                 nk = 1;         /* No-key */
2446         else
2447                 nk = 0;         /* have a key */
2448         
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");
2453         
2454         if (al == 0 && nk == 0)
2455                 ERRTO("KEY Algorithm");
2456         if (al != 0 && pr == 0)
2457                 ERRTO("KEY Protocols");
2458
2459         if (nk == 1 && klen != 0)
2460                 ERRTO("KEY No-Key Flags Set");
2461         
2462         if (nk == 0 && klen == 0)
2463                 ERRTO("KEY Type Spec'd");
2464         
2465         /* 
2466          *  Check algorithm-ID and key structure, for the algorithm-ID's 
2467          * that we know about. 
2468          */
2469         switch (al) {
2470         case NS_ALG_MD5RSA:
2471                 if (klen == 0)
2472                         break;
2473                 expstart = cp;
2474                 expbytes = *expstart++;
2475                 if (expbytes == 0)
2476                         GETSHORT(expbytes, expstart);
2477                 
2478                 if (expbytes < 1)
2479                         ERRTO("Exponent too short");
2480                 if (expbytes > (NS_MD5RSA_MAX_BITS + 7) / 8)
2481                         ERRTO("Exponent too long");
2482                 if (*expstart == 0)
2483                         ERRTO("Exponent w/ 0");
2484                 
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");
2492                 break;
2493                 
2494         case NS_ALG_DH: {
2495                 u_char *dh_cp;
2496                 u_int16_t dh_len, plen, glen, ulen;
2497                 
2498                 dh_cp = (u_char *)cp;
2499                 GETSHORT(plen, dh_cp);
2500                 if(plen < 16)
2501                         ERRTO("DH short plen");
2502                 dh_len = 2 + plen;
2503                 if(dh_len > klen)
2504                         ERRTO("DH plen > klen");
2505                 
2506                 GETSHORT(glen, dh_cp);
2507                 if(glen <= 0 || glen > plen)
2508                         ERRTO("DH glen bad");
2509                 dh_len = 2 + glen;
2510                 if(dh_len > klen)
2511                         ERRTO("DH glen > klen");
2512                 
2513                 GETSHORT(ulen, dh_cp);
2514                 if(ulen <= 0 || ulen > plen)
2515                         ERRTO("DH ulen bad");
2516                 dh_len = 2 + ulen;
2517                 if(dh_len > klen)
2518                         ERRTO("DH ulen > klen");
2519                 else if (dh_len < klen)
2520                         ERRTO("DH *len < klen");
2521                 break;
2522         }
2523         
2524         case NS_ALG_DSA: {
2525                 u_int8_t t;
2526                 
2527                 if ( klen == 0)
2528                         break;
2529                 t = *cp;
2530                 if (t > 8)
2531                         ERRTO("DSA T value");
2532                 if (klen != (1 + 20 + 3 *(64+8*t)))
2533                         ERRTO("DSA length");
2534                 break;
2535         }
2536         
2537         case NS_ALG_PRIVATE_OID:
2538                 if (klen == 0)
2539                         ERRTO("No ObjectID in key");
2540                 break;
2541         default:
2542                 ERRTO("Unknown Key algorithm");
2543         }
2544         
2545         endline(fp);  /* flush the rest of the line */
2546         return (n);
2547  err:
2548         *errmsg = errtype;
2549         return (-1);
2550 } /*T_KEY*/
2551                  
2552 /*
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)
2558  */
2559 int
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)
2564 {
2565         int ret = -1;
2566
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";
2571                         goto err;
2572                 }
2573
2574         switch (type) {
2575         case ns_t_sig:
2576                 ret = parse_sig_rr(buf, buf_len, data, data_size, fp, zp, 
2577                                    domain, ttl, context, transport, errmsg);
2578                 break;
2579         case ns_t_key:
2580                 ret = parse_key_rr(buf, buf_len, data, data_size, fp, zp,
2581                                    domain, context, transport, errmsg);
2582                 break;
2583         case ns_t_nxt:
2584                 ret = parse_nxt_rr(buf, buf_len, data, data_size, fp, zp,
2585                                    domain, context, transport, errmsg);
2586                 break;
2587         case ns_t_cert:
2588                 ret = parse_cert_rr(buf, buf_len, data, data_size, fp, errmsg);
2589                 break;
2590         default:
2591                 ret = -1;
2592                 *errmsg = "parse_sec_rdata():Unsupported SEC type type";
2593                 goto err;
2594         }
2595         return (ret);
2596  err:
2597         endline(fp);
2598         return (ret);
2599 }
2600