"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/bin/check/named-checkzone.c" (7 Sep 2020, 14277 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


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