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 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 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 */ 115 int writepid(struct nsd * ATTR_UNUSED(nsd)) 116 { 117 return 0; 118 } 119 void unlinkpid(const char * ATTR_UNUSED(file)) 120 { 121 } 122 void bind8_stats(struct nsd * ATTR_UNUSED(nsd)) 123 { 124 } 125 126 void sig_handler(int ATTR_UNUSED(sig)) 127 { 128 } 129 130 extern char *optarg; 131 extern int optind; 132 133 int 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