"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/bin/check/named-checkzone.c" (4 Sep 2020, 14541 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "named-checkzone.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <inttypes.h>
   15 #include <stdbool.h>
   16 #include <stdlib.h>
   17 
   18 #include <isc/app.h>
   19 #include <isc/attributes.h>
   20 #include <isc/commandline.h>
   21 #include <isc/dir.h>
   22 #include <isc/file.h>
   23 #include <isc/hash.h>
   24 #include <isc/log.h>
   25 #include <isc/mem.h>
   26 #include <isc/print.h>
   27 #include <isc/socket.h>
   28 #include <isc/string.h>
   29 #include <isc/task.h>
   30 #include <isc/timer.h>
   31 #include <isc/util.h>
   32 
   33 #include <dns/db.h>
   34 #include <dns/fixedname.h>
   35 #include <dns/log.h>
   36 #include <dns/master.h>
   37 #include <dns/masterdump.h>
   38 #include <dns/name.h>
   39 #include <dns/rdataclass.h>
   40 #include <dns/rdataset.h>
   41 #include <dns/result.h>
   42 #include <dns/types.h>
   43 #include <dns/zone.h>
   44 
   45 #include "check-tool.h"
   46 
   47 static int quiet = 0;
   48 static isc_mem_t *mctx = NULL;
   49 dns_zone_t *zone = NULL;
   50 dns_zonetype_t zonetype = dns_zone_master;
   51 static int dumpzone = 0;
   52 static const char *output_filename;
   53 static const char *prog_name = NULL;
   54 static const dns_master_style_t *outputstyle = NULL;
   55 static enum { progmode_check, progmode_compile } progmode;
   56 
   57 #define ERRRET(result, function)                                              \
   58     do {                                                                  \
   59         if (result != ISC_R_SUCCESS) {                                \
   60             if (!quiet)                                           \
   61                 fprintf(stderr, "%s() returned %s\n",         \
   62                     function, dns_result_totext(result)); \
   63             return (result);                                      \
   64         }                                                             \
   65     } while (0)
   66 
   67 ISC_NORETURN static void
   68 usage(void);
   69 
   70 static void
   71 usage(void) {
   72     fprintf(stderr,
   73         "usage: %s [-djqvD] [-c class] "
   74         "[-f inputformat] [-F outputformat] [-J filename] "
   75         "[-s (full|relative)] [-t directory] [-w directory] "
   76         "[-k (ignore|warn|fail)] [-m (ignore|warn|fail)] "
   77         "[-n (ignore|warn|fail)] [-r (ignore|warn|fail)] "
   78         "[-i (full|full-sibling|local|local-sibling|none)] "
   79         "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
   80         "[-W (ignore|warn)] "
   81         "%s zonename [ (filename|-) ]\n",
   82         prog_name,
   83         progmode == progmode_check ? "[-o filename]" : "-o filename");
   84     exit(1);
   85 }
   86 
   87 static void
   88 destroy(void) {
   89     if (zone != NULL) {
   90         dns_zone_detach(&zone);
   91     }
   92 }
   93 
   94 /*% main processing routine */
   95 int
   96 main(int argc, char **argv) {
   97     int c;
   98     char *origin = NULL;
   99     const char *filename = NULL;
  100     isc_log_t *lctx = NULL;
  101     isc_result_t result;
  102     char classname_in[] = "IN";
  103     char *classname = classname_in;
  104     const char *workdir = NULL;
  105     const char *inputformatstr = NULL;
  106     const char *outputformatstr = NULL;
  107     dns_masterformat_t inputformat = dns_masterformat_text;
  108     dns_masterformat_t outputformat = dns_masterformat_text;
  109     dns_masterrawheader_t header;
  110     uint32_t rawversion = 1, serialnum = 0;
  111     dns_ttl_t maxttl = 0;
  112     bool snset = false;
  113     bool logdump = false;
  114     FILE *errout = stdout;
  115     char *endp;
  116 
  117     /*
  118      * Uncomment the following line if memory debugging is needed:
  119      * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
  120      */
  121 
  122     outputstyle = &dns_master_style_full;
  123 
  124     prog_name = strrchr(argv[0], '/');
  125     if (prog_name == NULL) {
  126         prog_name = strrchr(argv[0], '\\');
  127     }
  128     if (prog_name != NULL) {
  129         prog_name++;
  130     } else {
  131         prog_name = argv[0];
  132     }
  133     /*
  134      * Libtool doesn't preserve the program name prior to final
  135      * installation.  Remove the libtool prefix ("lt-").
  136      */
  137     if (strncmp(prog_name, "lt-", 3) == 0) {
  138         prog_name += 3;
  139     }
  140 
  141 #define PROGCMP(X) \
  142     (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
  143 
  144     if (PROGCMP("named-checkzone")) {
  145         progmode = progmode_check;
  146     } else if (PROGCMP("named-compilezone")) {
  147         progmode = progmode_compile;
  148     } else {
  149         INSIST(0);
  150         ISC_UNREACHABLE();
  151     }
  152 
  153     /* Compilation specific defaults */
  154     if (progmode == progmode_compile) {
  155         zone_options |= (DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_FATALNS |
  156                  DNS_ZONEOPT_CHECKSPF | DNS_ZONEOPT_CHECKDUPRR |
  157                  DNS_ZONEOPT_CHECKNAMES |
  158                  DNS_ZONEOPT_CHECKNAMESFAIL |
  159                  DNS_ZONEOPT_CHECKWILDCARD);
  160     } else {
  161         zone_options |= (DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKSPF);
  162     }
  163 
  164 #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
  165 
  166     isc_commandline_errprint = false;
  167 
  168     while ((c = isc_commandline_parse(argc, argv,
  169                       "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:"
  170                       "M:S:T:W:")) != EOF)
  171     {
  172         switch (c) {
  173         case 'c':
  174             classname = isc_commandline_argument;
  175             break;
  176 
  177         case 'd':
  178             debug++;
  179             break;
  180 
  181         case 'i':
  182             if (ARGCMP("full")) {
  183                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
  184                         DNS_ZONEOPT_CHECKSIBLING;
  185                 docheckmx = true;
  186                 docheckns = true;
  187                 dochecksrv = true;
  188             } else if (ARGCMP("full-sibling")) {
  189                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  190                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  191                 docheckmx = true;
  192                 docheckns = true;
  193                 dochecksrv = true;
  194             } else if (ARGCMP("local")) {
  195                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  196                 zone_options |= DNS_ZONEOPT_CHECKSIBLING;
  197                 docheckmx = false;
  198                 docheckns = false;
  199                 dochecksrv = false;
  200             } else if (ARGCMP("local-sibling")) {
  201                 zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
  202                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  203                 docheckmx = false;
  204                 docheckns = false;
  205                 dochecksrv = false;
  206             } else if (ARGCMP("none")) {
  207                 zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
  208                 zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
  209                 docheckmx = false;
  210                 docheckns = false;
  211                 dochecksrv = false;
  212             } else {
  213                 fprintf(stderr, "invalid argument to -i: %s\n",
  214                     isc_commandline_argument);
  215                 exit(1);
  216             }
  217             break;
  218 
  219         case 'f':
  220             inputformatstr = isc_commandline_argument;
  221             break;
  222 
  223         case 'F':
  224             outputformatstr = isc_commandline_argument;
  225             break;
  226 
  227         case 'j':
  228             nomerge = false;
  229             break;
  230 
  231         case 'J':
  232             journal = isc_commandline_argument;
  233             nomerge = false;
  234             break;
  235 
  236         case 'k':
  237             if (ARGCMP("warn")) {
  238                 zone_options |= DNS_ZONEOPT_CHECKNAMES;
  239                 zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
  240             } else if (ARGCMP("fail")) {
  241                 zone_options |= DNS_ZONEOPT_CHECKNAMES |
  242                         DNS_ZONEOPT_CHECKNAMESFAIL;
  243             } else if (ARGCMP("ignore")) {
  244                 zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
  245                           DNS_ZONEOPT_CHECKNAMESFAIL);
  246             } else {
  247                 fprintf(stderr, "invalid argument to -k: %s\n",
  248                     isc_commandline_argument);
  249                 exit(1);
  250             }
  251             break;
  252 
  253         case 'L':
  254             snset = true;
  255             endp = NULL;
  256             serialnum = strtol(isc_commandline_argument, &endp, 0);
  257             if (*endp != '\0') {
  258                 fprintf(stderr, "source serial number "
  259                         "must be numeric");
  260                 exit(1);
  261             }
  262             break;
  263 
  264         case 'l':
  265             zone_options |= DNS_ZONEOPT_CHECKTTL;
  266             endp = NULL;
  267             maxttl = strtol(isc_commandline_argument, &endp, 0);
  268             if (*endp != '\0') {
  269                 fprintf(stderr, "maximum TTL "
  270                         "must be numeric");
  271                 exit(1);
  272             }
  273             break;
  274 
  275         case 'n':
  276             if (ARGCMP("ignore")) {
  277                 zone_options &= ~(DNS_ZONEOPT_CHECKNS |
  278                           DNS_ZONEOPT_FATALNS);
  279             } else if (ARGCMP("warn")) {
  280                 zone_options |= DNS_ZONEOPT_CHECKNS;
  281                 zone_options &= ~DNS_ZONEOPT_FATALNS;
  282             } else if (ARGCMP("fail")) {
  283                 zone_options |= DNS_ZONEOPT_CHECKNS |
  284                         DNS_ZONEOPT_FATALNS;
  285             } else {
  286                 fprintf(stderr, "invalid argument to -n: %s\n",
  287                     isc_commandline_argument);
  288                 exit(1);
  289             }
  290             break;
  291 
  292         case 'm':
  293             if (ARGCMP("warn")) {
  294                 zone_options |= DNS_ZONEOPT_CHECKMX;
  295                 zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
  296             } else if (ARGCMP("fail")) {
  297                 zone_options |= DNS_ZONEOPT_CHECKMX |
  298                         DNS_ZONEOPT_CHECKMXFAIL;
  299             } else if (ARGCMP("ignore")) {
  300                 zone_options &= ~(DNS_ZONEOPT_CHECKMX |
  301                           DNS_ZONEOPT_CHECKMXFAIL);
  302             } else {
  303                 fprintf(stderr, "invalid argument to -m: %s\n",
  304                     isc_commandline_argument);
  305                 exit(1);
  306             }
  307             break;
  308 
  309         case 'o':
  310             output_filename = isc_commandline_argument;
  311             break;
  312 
  313         case 'q':
  314             quiet++;
  315             break;
  316 
  317         case 'r':
  318             if (ARGCMP("warn")) {
  319                 zone_options |= DNS_ZONEOPT_CHECKDUPRR;
  320                 zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
  321             } else if (ARGCMP("fail")) {
  322                 zone_options |= DNS_ZONEOPT_CHECKDUPRR |
  323                         DNS_ZONEOPT_CHECKDUPRRFAIL;
  324             } else if (ARGCMP("ignore")) {
  325                 zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
  326                           DNS_ZONEOPT_CHECKDUPRRFAIL);
  327             } else {
  328                 fprintf(stderr, "invalid argument to -r: %s\n",
  329                     isc_commandline_argument);
  330                 exit(1);
  331             }
  332             break;
  333 
  334         case 's':
  335             if (ARGCMP("full")) {
  336                 outputstyle = &dns_master_style_full;
  337             } else if (ARGCMP("relative")) {
  338                 outputstyle = &dns_master_style_default;
  339             } else {
  340                 fprintf(stderr,
  341                     "unknown or unsupported style: %s\n",
  342                     isc_commandline_argument);
  343                 exit(1);
  344             }
  345             break;
  346 
  347         case 't':
  348             result = isc_dir_chroot(isc_commandline_argument);
  349             if (result != ISC_R_SUCCESS) {
  350                 fprintf(stderr, "isc_dir_chroot: %s: %s\n",
  351                     isc_commandline_argument,
  352                     isc_result_totext(result));
  353                 exit(1);
  354             }
  355             break;
  356 
  357         case 'v':
  358             printf("%s\n", PACKAGE_VERSION);
  359             exit(0);
  360 
  361         case 'w':
  362             workdir = isc_commandline_argument;
  363             break;
  364 
  365         case 'D':
  366             dumpzone++;
  367             break;
  368 
  369         case 'M':
  370             if (ARGCMP("fail")) {
  371                 zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
  372                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
  373             } else if (ARGCMP("warn")) {
  374                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
  375                 zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
  376             } else if (ARGCMP("ignore")) {
  377                 zone_options |= DNS_ZONEOPT_WARNMXCNAME;
  378                 zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
  379             } else {
  380                 fprintf(stderr, "invalid argument to -M: %s\n",
  381                     isc_commandline_argument);
  382                 exit(1);
  383             }
  384             break;
  385 
  386         case 'S':
  387             if (ARGCMP("fail")) {
  388                 zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
  389                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
  390             } else if (ARGCMP("warn")) {
  391                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
  392                 zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
  393             } else if (ARGCMP("ignore")) {
  394                 zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
  395                 zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
  396             } else {
  397                 fprintf(stderr, "invalid argument to -S: %s\n",
  398                     isc_commandline_argument);
  399                 exit(1);
  400             }
  401             break;
  402 
  403         case 'T':
  404             if (ARGCMP("warn")) {
  405                 zone_options |= DNS_ZONEOPT_CHECKSPF;
  406             } else if (ARGCMP("ignore")) {
  407                 zone_options &= ~DNS_ZONEOPT_CHECKSPF;
  408             } else {
  409                 fprintf(stderr, "invalid argument to -T: %s\n",
  410                     isc_commandline_argument);
  411                 exit(1);
  412             }
  413             break;
  414 
  415         case 'W':
  416             if (ARGCMP("warn")) {
  417                 zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
  418             } else if (ARGCMP("ignore")) {
  419                 zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
  420             }
  421             break;
  422 
  423         case '?':
  424             if (isc_commandline_option != '?') {
  425                 fprintf(stderr, "%s: invalid argument -%c\n",
  426                     prog_name, isc_commandline_option);
  427             }
  428         /* FALLTHROUGH */
  429         case 'h':
  430             usage();
  431 
  432         default:
  433             fprintf(stderr, "%s: unhandled option -%c\n", prog_name,
  434                 isc_commandline_option);
  435             exit(1);
  436         }
  437     }
  438 
  439     if (workdir != NULL) {
  440         result = isc_dir_chdir(workdir);
  441         if (result != ISC_R_SUCCESS) {
  442             fprintf(stderr, "isc_dir_chdir: %s: %s\n", workdir,
  443                 isc_result_totext(result));
  444             exit(1);
  445         }
  446     }
  447 
  448     if (inputformatstr != NULL) {
  449         if (strcasecmp(inputformatstr, "text") == 0) {
  450             inputformat = dns_masterformat_text;
  451         } else if (strcasecmp(inputformatstr, "raw") == 0) {
  452             inputformat = dns_masterformat_raw;
  453         } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
  454             inputformat = dns_masterformat_raw;
  455             fprintf(stderr, "WARNING: input format raw, version "
  456                     "ignored\n");
  457         } else if (strcasecmp(inputformatstr, "map") == 0) {
  458             inputformat = dns_masterformat_map;
  459         } else {
  460             fprintf(stderr, "unknown file format: %s\n",
  461                 inputformatstr);
  462             exit(1);
  463         }
  464     }
  465 
  466     if (outputformatstr != NULL) {
  467         if (strcasecmp(outputformatstr, "text") == 0) {
  468             outputformat = dns_masterformat_text;
  469         } else if (strcasecmp(outputformatstr, "raw") == 0) {
  470             outputformat = dns_masterformat_raw;
  471         } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
  472             char *end;
  473 
  474             outputformat = dns_masterformat_raw;
  475             rawversion = strtol(outputformatstr + 4, &end, 10);
  476             if (end == outputformatstr + 4 || *end != '\0' ||
  477                 rawversion > 1U) {
  478                 fprintf(stderr, "unknown raw format version\n");
  479                 exit(1);
  480             }
  481         } else if (strcasecmp(outputformatstr, "map") == 0) {
  482             outputformat = dns_masterformat_map;
  483         } else {
  484             fprintf(stderr, "unknown file format: %s\n",
  485                 outputformatstr);
  486             exit(1);
  487         }
  488     }
  489 
  490     if (progmode == progmode_compile) {
  491         dumpzone = 1; /* always dump */
  492         logdump = !quiet;
  493         if (output_filename == NULL) {
  494             fprintf(stderr, "output file required, but not "
  495                     "specified\n");
  496             usage();
  497         }
  498     }
  499 
  500     if (output_filename != NULL) {
  501         dumpzone = 1;
  502     }
  503 
  504     /*
  505      * If we are printing to stdout then send the informational
  506      * output to stderr.
  507      */
  508     if (dumpzone &&
  509         (output_filename == NULL || strcmp(output_filename, "-") == 0 ||
  510          strcmp(output_filename, "/dev/fd/1") == 0 ||
  511          strcmp(output_filename, "/dev/stdout") == 0))
  512     {
  513         errout = stderr;
  514         logdump = false;
  515     }
  516 
  517     if (argc - isc_commandline_index < 1 ||
  518         argc - isc_commandline_index > 2) {
  519         usage();
  520     }
  521 
  522 #ifdef _WIN32
  523     InitSockets();
  524 #endif /* ifdef _WIN32 */
  525 
  526     isc_mem_create(&mctx);
  527     if (!quiet) {
  528         RUNTIME_CHECK(setup_logging(mctx, errout, &lctx) ==
  529                   ISC_R_SUCCESS);
  530     }
  531 
  532     dns_result_register();
  533 
  534     origin = argv[isc_commandline_index++];
  535 
  536     if (isc_commandline_index == argc) {
  537         /* "-" will be interpreted as stdin */
  538         filename = "-";
  539     } else {
  540         filename = argv[isc_commandline_index];
  541     }
  542 
  543     isc_commandline_index++;
  544 
  545     result = load_zone(mctx, origin, filename, inputformat, classname,
  546                maxttl, &zone);
  547 
  548     if (snset) {
  549         dns_master_initrawheader(&header);
  550         header.flags = DNS_MASTERRAW_SOURCESERIALSET;
  551         header.sourceserial = serialnum;
  552         dns_zone_setrawdata(zone, &header);
  553     }
  554 
  555     if (result == ISC_R_SUCCESS && dumpzone) {
  556         if (logdump) {
  557             fprintf(errout, "dump zone to %s...", output_filename);
  558             fflush(errout);
  559         }
  560         result = dump_zone(origin, zone, output_filename, outputformat,
  561                    outputstyle, rawversion);
  562         if (logdump) {
  563             fprintf(errout, "done\n");
  564         }
  565     }
  566 
  567     if (!quiet && result == ISC_R_SUCCESS) {
  568         fprintf(errout, "OK\n");
  569     }
  570     destroy();
  571     if (lctx != NULL) {
  572         isc_log_destroy(&lctx);
  573     }
  574     isc_mem_destroy(&mctx);
  575 #ifdef _WIN32
  576     DestroySockets();
  577 #endif /* ifdef _WIN32 */
  578 
  579     return ((result == ISC_R_SUCCESS) ? 0 : 1);
  580 }