"Fossies" - the Fresh Open Source Software Archive

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