named-checkzone.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: named-checkzone.c,v 1.65.32.2 2012/02/07 02:45:21 each Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <stdlib.h>
00025 
00026 #include <isc/app.h>
00027 #include <isc/commandline.h>
00028 #include <isc/dir.h>
00029 #include <isc/entropy.h>
00030 #include <isc/hash.h>
00031 #include <isc/log.h>
00032 #include <isc/mem.h>
00033 #include <isc/socket.h>
00034 #include <isc/string.h>
00035 #include <isc/task.h>
00036 #include <isc/timer.h>
00037 #include <isc/util.h>
00038 
00039 #include <dns/db.h>
00040 #include <dns/fixedname.h>
00041 #include <dns/log.h>
00042 #include <dns/master.h>
00043 #include <dns/masterdump.h>
00044 #include <dns/name.h>
00045 #include <dns/rdataclass.h>
00046 #include <dns/rdataset.h>
00047 #include <dns/result.h>
00048 #include <dns/types.h>
00049 #include <dns/zone.h>
00050 
00051 #include "check-tool.h"
00052 
00053 static int quiet = 0;
00054 static isc_mem_t *mctx = NULL;
00055 static isc_entropy_t *ectx = NULL;
00056 dns_zone_t *zone = NULL;
00057 dns_zonetype_t zonetype = dns_zone_master;
00058 static int dumpzone = 0;
00059 static const char *output_filename;
00060 static char *prog_name = NULL;
00061 static const dns_master_style_t *outputstyle = NULL;
00062 static enum { progmode_check, progmode_compile } progmode;
00063 
00064 #define ERRRET(result, function) \
00065         do { \
00066                 if (result != ISC_R_SUCCESS) { \
00067                         if (!quiet) \
00068                                 fprintf(stderr, "%s() returned %s\n", \
00069                                         function, dns_result_totext(result)); \
00070                         return (result); \
00071                 } \
00072         } while (0)
00073 
00074 ISC_PLATFORM_NORETURN_PRE static void
00075 usage(void) ISC_PLATFORM_NORETURN_POST;
00076 
00077 static void
00078 usage(void) {
00079         fprintf(stderr,
00080                 "usage: %s [-djqvD] [-c class] "
00081                 "[-f inputformat] [-F outputformat] [-J filename] "
00082                 "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
00083                 "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
00084                 "[-r (ignore|warn|fail)] "
00085                 "[-i (full|full-sibling|local|local-sibling|none)] "
00086                 "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
00087                 "[-W (ignore|warn)] "
00088                 "%s zonename filename\n",
00089                 prog_name,
00090                 progmode == progmode_check ? "[-o filename]" : "-o filename");
00091         exit(1);
00092 }
00093 
00094 static void
00095 destroy(void) {
00096         if (zone != NULL)
00097                 dns_zone_detach(&zone);
00098         dns_name_destroy();
00099 }
00100 
00101 /*% main processing routine */
00102 int
00103 main(int argc, char **argv) {
00104         int c;
00105         char *origin = NULL;
00106         char *filename = NULL;
00107         isc_log_t *lctx = NULL;
00108         isc_result_t result;
00109         char classname_in[] = "IN";
00110         char *classname = classname_in;
00111         const char *workdir = NULL;
00112         const char *inputformatstr = NULL;
00113         const char *outputformatstr = NULL;
00114         dns_masterformat_t inputformat = dns_masterformat_text;
00115         dns_masterformat_t outputformat = dns_masterformat_text;
00116         dns_masterrawheader_t header;
00117         isc_uint32_t rawversion = 1, serialnum = 0;
00118         dns_ttl_t maxttl = 0;
00119         isc_boolean_t snset = ISC_FALSE;
00120         isc_boolean_t logdump = ISC_FALSE;
00121         FILE *errout = stdout;
00122         char *endp;
00123 
00124         /*
00125          * Uncomment the following line if memory debugging is needed:
00126          * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
00127          */
00128 
00129         outputstyle = &dns_master_style_full;
00130 
00131         prog_name = strrchr(argv[0], '/');
00132         if (prog_name == NULL)
00133                 prog_name = strrchr(argv[0], '\\');
00134         if (prog_name != NULL)
00135                 prog_name++;
00136         else
00137                 prog_name = argv[0];
00138         /*
00139          * Libtool doesn't preserve the program name prior to final
00140          * installation.  Remove the libtool prefix ("lt-").
00141          */
00142         if (strncmp(prog_name, "lt-", 3) == 0)
00143                 prog_name += 3;
00144 
00145 #define PROGCMP(X) \
00146         (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
00147 
00148         if (PROGCMP("named-checkzone"))
00149                 progmode = progmode_check;
00150         else if (PROGCMP("named-compilezone"))
00151                 progmode = progmode_compile;
00152         else
00153                 INSIST(0);
00154 
00155         /* Compilation specific defaults */
00156         if (progmode == progmode_compile) {
00157                 zone_options |= (DNS_ZONEOPT_CHECKNS |
00158                                  DNS_ZONEOPT_FATALNS |
00159                                  DNS_ZONEOPT_CHECKSPF |
00160                                  DNS_ZONEOPT_CHECKDUPRR |
00161                                  DNS_ZONEOPT_CHECKNAMES |
00162                                  DNS_ZONEOPT_CHECKNAMESFAIL |
00163                                  DNS_ZONEOPT_CHECKWILDCARD);
00164         } else
00165                 zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
00166                                  DNS_ZONEOPT_CHECKSPF);
00167 
00168 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
00169 
00170         isc_commandline_errprint = ISC_FALSE;
00171 
00172         while ((c = isc_commandline_parse(argc, argv,
00173                                "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
00174                != EOF) {
00175                 switch (c) {
00176                 case 'c':
00177                         classname = isc_commandline_argument;
00178                         break;
00179 
00180                 case 'd':
00181                         debug++;
00182                         break;
00183 
00184                 case 'i':
00185                         if (ARGCMP("full")) {
00186                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
00187                                                 DNS_ZONEOPT_CHECKSIBLING;
00188                                 docheckmx = ISC_TRUE;
00189                                 docheckns = ISC_TRUE;
00190                                 dochecksrv = ISC_TRUE;
00191                         } else if (ARGCMP("full-sibling")) {
00192                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
00193                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
00194                                 docheckmx = ISC_TRUE;
00195                                 docheckns = ISC_TRUE;
00196                                 dochecksrv = ISC_TRUE;
00197                         } else if (ARGCMP("local")) {
00198                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
00199                                 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
00200                                 docheckmx = ISC_FALSE;
00201                                 docheckns = ISC_FALSE;
00202                                 dochecksrv = ISC_FALSE;
00203                         } else if (ARGCMP("local-sibling")) {
00204                                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
00205                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
00206                                 docheckmx = ISC_FALSE;
00207                                 docheckns = ISC_FALSE;
00208                                 dochecksrv = ISC_FALSE;
00209                         } else if (ARGCMP("none")) {
00210                                 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
00211                                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
00212                                 docheckmx = ISC_FALSE;
00213                                 docheckns = ISC_FALSE;
00214                                 dochecksrv = ISC_FALSE;
00215                         } else {
00216                                 fprintf(stderr, "invalid argument to -i: %s\n",
00217                                         isc_commandline_argument);
00218                                 exit(1);
00219                         }
00220                         break;
00221 
00222                 case 'f':
00223                         inputformatstr = isc_commandline_argument;
00224                         break;
00225 
00226                 case 'F':
00227                         outputformatstr = isc_commandline_argument;
00228                         break;
00229 
00230                 case 'j':
00231                         nomerge = ISC_FALSE;
00232                         break;
00233 
00234                 case 'J':
00235                         journal = isc_commandline_argument;
00236                         nomerge = ISC_FALSE;
00237                         break;
00238 
00239                 case 'k':
00240                         if (ARGCMP("warn")) {
00241                                 zone_options |= DNS_ZONEOPT_CHECKNAMES;
00242                                 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
00243                         } else if (ARGCMP("fail")) {
00244                                 zone_options |= DNS_ZONEOPT_CHECKNAMES |
00245                                                 DNS_ZONEOPT_CHECKNAMESFAIL;
00246                         } else if (ARGCMP("ignore")) {
00247                                 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
00248                                                   DNS_ZONEOPT_CHECKNAMESFAIL);
00249                         } else {
00250                                 fprintf(stderr, "invalid argument to -k: %s\n",
00251                                         isc_commandline_argument);
00252                                 exit(1);
00253                         }
00254                         break;
00255 
00256                 case 'L':
00257                         snset = ISC_TRUE;
00258                         endp = NULL;
00259                         serialnum = strtol(isc_commandline_argument, &endp, 0);
00260                         if (*endp != '\0') {
00261                                 fprintf(stderr, "source serial number "
00262                                                 "must be numeric");
00263                                 exit(1);
00264                         }
00265                         break;
00266 
00267                 case 'l':
00268                         zone_options2 |= DNS_ZONEOPT2_CHECKTTL;
00269                         endp = NULL;
00270                         maxttl = strtol(isc_commandline_argument, &endp, 0);
00271                         if (*endp != '\0') {
00272                                 fprintf(stderr, "maximum TTL "
00273                                                 "must be numeric");
00274                                 exit(1);
00275                         }
00276                         break;
00277 
00278 
00279                 case 'n':
00280                         if (ARGCMP("ignore")) {
00281                                 zone_options &= ~(DNS_ZONEOPT_CHECKNS|
00282                                                   DNS_ZONEOPT_FATALNS);
00283                         } else if (ARGCMP("warn")) {
00284                                 zone_options |= DNS_ZONEOPT_CHECKNS;
00285                                 zone_options &= ~DNS_ZONEOPT_FATALNS;
00286                         } else if (ARGCMP("fail")) {
00287                                 zone_options |= DNS_ZONEOPT_CHECKNS|
00288                                                 DNS_ZONEOPT_FATALNS;
00289                         } else {
00290                                 fprintf(stderr, "invalid argument to -n: %s\n",
00291                                         isc_commandline_argument);
00292                                 exit(1);
00293                         }
00294                         break;
00295 
00296                 case 'm':
00297                         if (ARGCMP("warn")) {
00298                                 zone_options |= DNS_ZONEOPT_CHECKMX;
00299                                 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
00300                         } else if (ARGCMP("fail")) {
00301                                 zone_options |= DNS_ZONEOPT_CHECKMX |
00302                                                 DNS_ZONEOPT_CHECKMXFAIL;
00303                         } else if (ARGCMP("ignore")) {
00304                                 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
00305                                                   DNS_ZONEOPT_CHECKMXFAIL);
00306                         } else {
00307                                 fprintf(stderr, "invalid argument to -m: %s\n",
00308                                         isc_commandline_argument);
00309                                 exit(1);
00310                         }
00311                         break;
00312 
00313                 case 'o':
00314                         output_filename = isc_commandline_argument;
00315                         break;
00316 
00317                 case 'q':
00318                         quiet++;
00319                         break;
00320 
00321                 case 'r':
00322                         if (ARGCMP("warn")) {
00323                                 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
00324                                 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
00325                         } else if (ARGCMP("fail")) {
00326                                 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
00327                                                 DNS_ZONEOPT_CHECKDUPRRFAIL;
00328                         } else if (ARGCMP("ignore")) {
00329                                 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
00330                                                   DNS_ZONEOPT_CHECKDUPRRFAIL);
00331                         } else {
00332                                 fprintf(stderr, "invalid argument to -r: %s\n",
00333                                         isc_commandline_argument);
00334                                 exit(1);
00335                         }
00336                         break;
00337 
00338                 case 's':
00339                         if (ARGCMP("full"))
00340                                 outputstyle = &dns_master_style_full;
00341                         else if (ARGCMP("relative")) {
00342                                 outputstyle = &dns_master_style_default;
00343                         } else {
00344                                 fprintf(stderr,
00345                                         "unknown or unsupported style: %s\n",
00346                                         isc_commandline_argument);
00347                                 exit(1);
00348                         }
00349                         break;
00350 
00351                 case 't':
00352                         result = isc_dir_chroot(isc_commandline_argument);
00353                         if (result != ISC_R_SUCCESS) {
00354                                 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
00355                                         isc_commandline_argument,
00356                                         isc_result_totext(result));
00357                                 exit(1);
00358                         }
00359                         break;
00360 
00361                 case 'v':
00362                         printf(VERSION "\n");
00363                         exit(0);
00364 
00365                 case 'w':
00366                         workdir = isc_commandline_argument;
00367                         break;
00368 
00369                 case 'D':
00370                         dumpzone++;
00371                         break;
00372 
00373                 case 'M':
00374                         if (ARGCMP("fail")) {
00375                                 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
00376                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
00377                         } else if (ARGCMP("warn")) {
00378                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
00379                                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
00380                         } else if (ARGCMP("ignore")) {
00381                                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
00382                                 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
00383                         } else {
00384                                 fprintf(stderr, "invalid argument to -M: %s\n",
00385                                         isc_commandline_argument);
00386                                 exit(1);
00387                         }
00388                         break;
00389 
00390                 case 'S':
00391                         if (ARGCMP("fail")) {
00392                                 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
00393                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
00394                         } else if (ARGCMP("warn")) {
00395                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
00396                                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
00397                         } else if (ARGCMP("ignore")) {
00398                                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
00399                                 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
00400                         } else {
00401                                 fprintf(stderr, "invalid argument to -S: %s\n",
00402                                         isc_commandline_argument);
00403                                 exit(1);
00404                         }
00405                         break;
00406 
00407                 case 'T':
00408                         if (ARGCMP("warn")) {
00409                                 zone_options |= DNS_ZONEOPT_CHECKSPF;
00410                         } else if (ARGCMP("ignore")) {
00411                                 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
00412                         } else {
00413                                 fprintf(stderr, "invalid argument to -T: %s\n",
00414                                         isc_commandline_argument);
00415                                 exit(1);
00416                         }
00417                         break;
00418 
00419                 case 'W':
00420                         if (ARGCMP("warn"))
00421                                 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
00422                         else if (ARGCMP("ignore"))
00423                                 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
00424                         break;
00425 
00426                 case '?':
00427                         if (isc_commandline_option != '?')
00428                                 fprintf(stderr, "%s: invalid argument -%c\n",
00429                                         prog_name, isc_commandline_option);
00430                         /* FALLTHROUGH */
00431                 case 'h':
00432                         usage();
00433 
00434                 default:
00435                         fprintf(stderr, "%s: unhandled option -%c\n",
00436                                 prog_name, isc_commandline_option);
00437                         exit(1);
00438                 }
00439         }
00440 
00441         if (workdir != NULL) {
00442                 result = isc_dir_chdir(workdir);
00443                 if (result != ISC_R_SUCCESS) {
00444                         fprintf(stderr, "isc_dir_chdir: %s: %s\n",
00445                                 workdir, isc_result_totext(result));
00446                         exit(1);
00447                 }
00448         }
00449 
00450         if (inputformatstr != NULL) {
00451                 if (strcasecmp(inputformatstr, "text") == 0)
00452                         inputformat = dns_masterformat_text;
00453                 else if (strcasecmp(inputformatstr, "raw") == 0)
00454                         inputformat = dns_masterformat_raw;
00455                 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
00456                         inputformat = dns_masterformat_raw;
00457                         fprintf(stderr,
00458                                 "WARNING: input format raw, version ignored\n");
00459                 } else if (strcasecmp(inputformatstr, "map") == 0) {
00460                         inputformat = dns_masterformat_map;
00461                 } else {
00462                         fprintf(stderr, "unknown file format: %s\n",
00463                             inputformatstr);
00464                         exit(1);
00465                 }
00466         }
00467 
00468         if (outputformatstr != NULL) {
00469                 if (strcasecmp(outputformatstr, "text") == 0) {
00470                         outputformat = dns_masterformat_text;
00471                 } else if (strcasecmp(outputformatstr, "raw") == 0) {
00472                         outputformat = dns_masterformat_raw;
00473                 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
00474                         char *end;
00475 
00476                         outputformat = dns_masterformat_raw;
00477                         rawversion = strtol(outputformatstr + 4, &end, 10);
00478                         if (end == outputformatstr + 4 || *end != '\0' ||
00479                             rawversion > 1U) {
00480                                 fprintf(stderr,
00481                                         "unknown raw format version\n");
00482                                 exit(1);
00483                         }
00484                 } else if (strcasecmp(outputformatstr, "map") == 0) {
00485                         outputformat = dns_masterformat_map;
00486                 } else {
00487                         fprintf(stderr, "unknown file format: %s\n",
00488                                 outputformatstr);
00489                         exit(1);
00490                 }
00491         }
00492 
00493         if (progmode == progmode_compile) {
00494                 dumpzone = 1;   /* always dump */
00495                 logdump = !quiet;
00496                 if (output_filename == NULL) {
00497                         fprintf(stderr,
00498                                 "output file required, but not specified\n");
00499                         usage();
00500                 }
00501         }
00502 
00503         if (output_filename != NULL)
00504                 dumpzone = 1;
00505 
00506         /*
00507          * If we are outputing to stdout then send the informational
00508          * output to stderr.
00509          */
00510         if (dumpzone &&
00511             (output_filename == NULL ||
00512              strcmp(output_filename, "-") == 0 ||
00513              strcmp(output_filename, "/dev/fd/1") == 0 ||
00514              strcmp(output_filename, "/dev/stdout") == 0)) {
00515                 errout = stderr;
00516                 logdump = ISC_FALSE;
00517         }
00518 
00519         if (isc_commandline_index + 2 != argc)
00520                 usage();
00521 
00522 #ifdef _WIN32
00523         InitSockets();
00524 #endif
00525 
00526         RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
00527         if (!quiet)
00528                 RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
00529                               == ISC_R_SUCCESS);
00530         RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
00531         RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
00532                       == ISC_R_SUCCESS);
00533 
00534         dns_result_register();
00535 
00536         origin = argv[isc_commandline_index++];
00537         filename = argv[isc_commandline_index++];
00538         result = load_zone(mctx, origin, filename, inputformat, classname,
00539                            maxttl, &zone);
00540 
00541         if (snset) {
00542                 dns_master_initrawheader(&header);
00543                 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
00544                 header.sourceserial = serialnum;
00545                 dns_zone_setrawdata(zone, &header);
00546         }
00547 
00548         if (result == ISC_R_SUCCESS && dumpzone) {
00549                 if (logdump) {
00550                         fprintf(errout, "dump zone to %s...", output_filename);
00551                         fflush(errout);
00552                 }
00553                 result = dump_zone(origin, zone, output_filename,
00554                                    outputformat, outputstyle, rawversion);
00555                 if (logdump)
00556                         fprintf(errout, "done\n");
00557         }
00558 
00559         if (!quiet && result == ISC_R_SUCCESS)
00560                 fprintf(errout, "OK\n");
00561         destroy();
00562         if (lctx != NULL)
00563                 isc_log_destroy(&lctx);
00564         isc_hash_destroy();
00565         isc_entropy_detach(&ectx);
00566         isc_mem_destroy(&mctx);
00567 #ifdef _WIN32
00568         DestroySockets();
00569 #endif
00570         return ((result == ISC_R_SUCCESS) ? 0 : 1);
00571 }

Generated on Tue Apr 28 17:40:53 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha