1 /*
2 * nsd-checkzone.c -- nsd-checkzone(8) checks zones for syntax errors
3 *
4 * Copyright (c) 2013, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 */
9
10 #include "config.h"
11
12 #include <assert.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 #include <unistd.h>
18 #include <errno.h>
19
20 #include "nsd.h"
21 #include "options.h"
22 #include "util.h"
23 #include "zonec.h"
24 #include "ixfr.h"
25 #include "ixfrcreate.h"
26 #include "difffile.h"
27
28 struct nsd nsd;
29
30 /*
31 * Print the help text.
32 *
33 */
34 static void
usage(void)35 usage (void)
36 {
37 fprintf(stderr, "Usage: nsd-checkzone [-p] <zone name> <zone file>\n");
38 fprintf(stderr, "\t-p\tprint the zone if the zone is ok\n");
39 fprintf(stderr, "\t-i <old zone file>\tcreate an IXFR from the differences between the\n\t\told zone file and the new zone file. Writes to \n\t\t<zonefile>.ixfr and renames other <zonefile>.ixfr files to\n\t\t<zonefile>.ixfr.num+1.\n");
40 fprintf(stderr, "\t-n <ixfr number>\tnumber of IXFR versions to store, at most.\n\t\tdefault %d.\n", (int)IXFR_NUMBER_DEFAULT);
41 fprintf(stderr, "\t-s <ixfr size>\tsize of IXFR to store, at most. default %d.\n", (int)IXFR_SIZE_DEFAULT);
42 fprintf(stderr, "Version %s. Report bugs to <%s>.\n",
43 PACKAGE_VERSION, PACKAGE_BUGREPORT);
44 }
45
46 static void
check_zone(struct nsd * nsd,const char * name,const char * fname,FILE * out,const char * oldzone,uint32_t ixfr_number,uint64_t ixfr_size)47 check_zone(struct nsd* nsd, const char* name, const char* fname, FILE *out,
48 const char* oldzone, uint32_t ixfr_number, uint64_t ixfr_size)
49 {
50 const dname_type* dname;
51 zone_options_type* zo;
52 zone_type* zone;
53 unsigned errors;
54 struct ixfr_create* ixfrcr = NULL;
55
56 /* init*/
57 nsd->db = namedb_open(nsd->options);
58 dname = dname_parse(nsd->options->region, name);
59 if(!dname) {
60 /* parse failure */
61 error("cannot parse zone name '%s'", name);
62 }
63 zo = zone_options_create(nsd->options->region);
64 memset(zo, 0, sizeof(*zo));
65 zo->node.key = dname;
66 zo->name = name;
67 zone = namedb_zone_create(nsd->db, dname, zo);
68
69 if(oldzone) {
70 errors = zonec_read(name, oldzone, zone);
71 if(errors > 0) {
72 printf("zone %s file %s has %u errors\n", name, oldzone, errors);
73 exit(1);
74 }
75 ixfrcr = ixfr_create_start(zone, fname, ixfr_size, 1);
76 if(!ixfrcr) {
77 error("out of memory");
78 }
79 delete_zone_rrs(nsd->db, zone);
80 }
81
82 /* read the zone */
83 errors = zonec_read(name, fname, zone);
84 if(errors > 0) {
85 printf("zone %s file %s has %u errors\n", name, fname, errors);
86 ixfr_create_cancel(ixfrcr);
87 #ifdef MEMCLEAN /* otherwise, the OS collects memory pages */
88 namedb_close(nsd->db);
89 region_destroy(nsd->options->region);
90 #endif
91 exit(1);
92 }
93 if(ixfrcr) {
94 if(!ixfr_create_perform(ixfrcr, zone, 0, nsd, fname,
95 ixfr_number)) {
96 #ifdef MEMCLEAN /* otherwise, the OS collects memory pages */
97 namedb_close(nsd->db);
98 region_destroy(nsd->options->region);
99 ixfr_create_free(ixfrcr);
100 #endif
101 error("could not create IXFR");
102 }
103 printf("zone %s created IXFR %s.ixfr\n", name, fname);
104 ixfr_create_free(ixfrcr);
105 }
106 if (out) {
107 print_rrs(out, zone);
108 printf("; ");
109 }
110 printf("zone %s is ok\n", name);
111 namedb_close(nsd->db);
112 }
113
114 /* dummy functions to link */
writepid(struct nsd * ATTR_UNUSED (nsd))115 int writepid(struct nsd * ATTR_UNUSED(nsd))
116 {
117 return 0;
118 }
unlinkpid(const char * ATTR_UNUSED (file))119 void unlinkpid(const char * ATTR_UNUSED(file))
120 {
121 }
bind8_stats(struct nsd * ATTR_UNUSED (nsd))122 void bind8_stats(struct nsd * ATTR_UNUSED(nsd))
123 {
124 }
125
sig_handler(int ATTR_UNUSED (sig))126 void sig_handler(int ATTR_UNUSED(sig))
127 {
128 }
129
130 extern char *optarg;
131 extern int optind;
132
133 int
main(int argc,char * argv[])134 main(int argc, char *argv[])
135 {
136 /* Scratch variables... */
137 int c;
138 int print_zone = 0;
139 uint32_t ixfr_number = IXFR_NUMBER_DEFAULT;
140 uint64_t ixfr_size = IXFR_SIZE_DEFAULT;
141 char* oldzone = NULL;
142 struct nsd nsd;
143 memset(&nsd, 0, sizeof(nsd));
144
145 log_init("nsd-checkzone");
146
147 /* Parse the command line... */
148 while ((c = getopt(argc, argv, "hi:n:ps:")) != -1) {
149 switch (c) {
150 case 'h':
151 usage();
152 exit(0);
153 case 'i':
154 oldzone = optarg;
155 break;
156 case 'n':
157 ixfr_number = (uint32_t)atoi(optarg);
158 break;
159 case 'p':
160 print_zone = 1;
161 break;
162 case 's':
163 ixfr_size = (uint64_t)atoi(optarg);
164 break;
165 case '?':
166 default:
167 usage();
168 exit(1);
169 }
170 }
171 argc -= optind;
172 argv += optind;
173
174 /* Commandline parse error */
175 if (argc != 2) {
176 fprintf(stderr, "wrong number of arguments.\n");
177 usage();
178 exit(1);
179 }
180
181 nsd.options = nsd_options_create(region_create_custom(xalloc, free,
182 DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE,
183 DEFAULT_INITIAL_CLEANUP_SIZE, 1));
184 if (verbosity == 0)
185 verbosity = nsd.options->verbosity;
186
187 check_zone(&nsd, argv[0], argv[1], print_zone ? stdout : NULL,
188 oldzone, ixfr_number, ixfr_size);
189 region_destroy(nsd.options->region);
190 /* yylex_destroy(); but, not available in all versions of flex */
191
192 exit(0);
193 }
194