check-tool.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2002  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: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <stdio.h>
00025 
00026 #ifdef _WIN32
00027 #include <Winsock2.h>
00028 #endif
00029 
00030 #include "check-tool.h"
00031 #include <isc/buffer.h>
00032 #include <isc/log.h>
00033 #include <isc/mem.h>
00034 #include <isc/netdb.h>
00035 #include <isc/net.h>
00036 #include <isc/region.h>
00037 #include <isc/stdio.h>
00038 #include <isc/string.h>
00039 #include <isc/symtab.h>
00040 #include <isc/types.h>
00041 #include <isc/util.h>
00042 
00043 #include <dns/db.h>
00044 #include <dns/dbiterator.h>
00045 #include <dns/fixedname.h>
00046 #include <dns/log.h>
00047 #include <dns/name.h>
00048 #include <dns/rdata.h>
00049 #include <dns/rdataclass.h>
00050 #include <dns/rdataset.h>
00051 #include <dns/rdatasetiter.h>
00052 #include <dns/rdatatype.h>
00053 #include <dns/result.h>
00054 #include <dns/types.h>
00055 #include <dns/zone.h>
00056 
00057 #include <isccfg/log.h>
00058 
00059 #ifndef CHECK_SIBLING
00060 #define CHECK_SIBLING 1
00061 #endif
00062 
00063 #ifndef CHECK_LOCAL
00064 #define CHECK_LOCAL 1
00065 #endif
00066 
00067 #ifdef HAVE_ADDRINFO
00068 #ifdef HAVE_GETADDRINFO
00069 #ifdef HAVE_GAISTRERROR
00070 #define USE_GETADDRINFO
00071 #endif
00072 #endif
00073 #endif
00074 
00075 #define CHECK(r) \
00076         do { \
00077                 result = (r); \
00078                 if (result != ISC_R_SUCCESS) \
00079                         goto cleanup; \
00080         } while (0)
00081 
00082 #define ERR_IS_CNAME 1
00083 #define ERR_NO_ADDRESSES 2
00084 #define ERR_LOOKUP_FAILURE 3
00085 #define ERR_EXTRA_A 4
00086 #define ERR_EXTRA_AAAA 5
00087 #define ERR_MISSING_GLUE 5
00088 #define ERR_IS_MXCNAME 6
00089 #define ERR_IS_SRVCNAME 7
00090 
00091 static const char *dbtype[] = { "rbt" };
00092 
00093 int debug = 0;
00094 const char *journal = NULL;
00095 isc_boolean_t nomerge = ISC_TRUE;
00096 #if CHECK_LOCAL
00097 isc_boolean_t docheckmx = ISC_TRUE;
00098 isc_boolean_t dochecksrv = ISC_TRUE;
00099 isc_boolean_t docheckns = ISC_TRUE;
00100 #else
00101 isc_boolean_t docheckmx = ISC_FALSE;
00102 isc_boolean_t dochecksrv = ISC_FALSE;
00103 isc_boolean_t docheckns = ISC_FALSE;
00104 #endif
00105 unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
00106                             DNS_ZONEOPT_CHECKMX |
00107                             DNS_ZONEOPT_MANYERRORS |
00108                             DNS_ZONEOPT_CHECKNAMES |
00109                             DNS_ZONEOPT_CHECKINTEGRITY |
00110 #if CHECK_SIBLING
00111                             DNS_ZONEOPT_CHECKSIBLING |
00112 #endif
00113                             DNS_ZONEOPT_CHECKWILDCARD |
00114                             DNS_ZONEOPT_WARNMXCNAME |
00115                             DNS_ZONEOPT_WARNSRVCNAME;
00116 unsigned int zone_options2 = 0;
00117 
00118 /*
00119  * This needs to match the list in bin/named/log.c.
00120  */
00121 static isc_logcategory_t categories[] = {
00122         { "",                0 },
00123         { "client",          0 },
00124         { "network",         0 },
00125         { "update",          0 },
00126         { "queries",         0 },
00127         { "unmatched",       0 },
00128         { "update-security", 0 },
00129         { "query-errors",    0 },
00130         { NULL,              0 }
00131 };
00132 
00133 static isc_symtab_t *symtab = NULL;
00134 static isc_mem_t *sym_mctx;
00135 
00136 static void
00137 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
00138         UNUSED(type);
00139         UNUSED(value);
00140         isc_mem_free(userarg, key);
00141 }
00142 
00143 static void
00144 add(char *key, int value) {
00145         isc_result_t result;
00146         isc_symvalue_t symvalue;
00147 
00148         if (sym_mctx == NULL) {
00149                 result = isc_mem_create(0, 0, &sym_mctx);
00150                 if (result != ISC_R_SUCCESS)
00151                         return;
00152         }
00153 
00154         if (symtab == NULL) {
00155                 result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
00156                                            ISC_FALSE, &symtab);
00157                 if (result != ISC_R_SUCCESS)
00158                         return;
00159         }
00160 
00161         key = isc_mem_strdup(sym_mctx, key);
00162         if (key == NULL)
00163                 return;
00164 
00165         symvalue.as_pointer = NULL;
00166         result = isc_symtab_define(symtab, key, value, symvalue,
00167                                    isc_symexists_reject);
00168         if (result != ISC_R_SUCCESS)
00169                 isc_mem_free(sym_mctx, key);
00170 }
00171 
00172 static isc_boolean_t
00173 logged(char *key, int value) {
00174         isc_result_t result;
00175 
00176         if (symtab == NULL)
00177                 return (ISC_FALSE);
00178 
00179         result = isc_symtab_lookup(symtab, key, value, NULL);
00180         if (result == ISC_R_SUCCESS)
00181                 return (ISC_TRUE);
00182         return (ISC_FALSE);
00183 }
00184 
00185 static isc_boolean_t
00186 checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
00187         dns_rdataset_t *a, dns_rdataset_t *aaaa)
00188 {
00189 #ifdef USE_GETADDRINFO
00190         dns_rdataset_t *rdataset;
00191         dns_rdata_t rdata = DNS_RDATA_INIT;
00192         struct addrinfo hints, *ai, *cur;
00193         char namebuf[DNS_NAME_FORMATSIZE + 1];
00194         char ownerbuf[DNS_NAME_FORMATSIZE];
00195         char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
00196         isc_boolean_t answer = ISC_TRUE;
00197         isc_boolean_t match;
00198         const char *type;
00199         void *ptr = NULL;
00200         int result;
00201 
00202         REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
00203                 a->type == dns_rdatatype_a);
00204         REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
00205                 aaaa->type == dns_rdatatype_aaaa);
00206 
00207         if (a == NULL || aaaa == NULL)
00208                 return (answer);
00209 
00210         memset(&hints, 0, sizeof(hints));
00211         hints.ai_flags = AI_CANONNAME;
00212         hints.ai_family = PF_UNSPEC;
00213         hints.ai_socktype = SOCK_STREAM;
00214         hints.ai_protocol = IPPROTO_TCP;
00215 
00216         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00217         /*
00218          * Turn off search.
00219          */
00220         if (dns_name_countlabels(name) > 1U)
00221                 strcat(namebuf, ".");
00222         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00223 
00224         result = getaddrinfo(namebuf, NULL, &hints, &ai);
00225         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00226         switch (result) {
00227         case 0:
00228                 /*
00229                  * Work around broken getaddrinfo() implementations that
00230                  * fail to set ai_canonname on first entry.
00231                  */
00232                 cur = ai;
00233                 while (cur != NULL && cur->ai_canonname == NULL &&
00234                        cur->ai_next != NULL)
00235                         cur = cur->ai_next;
00236                 if (cur != NULL && cur->ai_canonname != NULL &&
00237                     strcasecmp(cur->ai_canonname, namebuf) != 0 &&
00238                     !logged(namebuf, ERR_IS_CNAME)) {
00239                         dns_zone_log(zone, ISC_LOG_ERROR,
00240                                      "%s/NS '%s' (out of zone) "
00241                                      "is a CNAME '%s' (illegal)",
00242                                      ownerbuf, namebuf,
00243                                      cur->ai_canonname);
00244                         /* XXX950 make fatal for 9.5.0 */
00245                         /* answer = ISC_FALSE; */
00246                         add(namebuf, ERR_IS_CNAME);
00247                 }
00248                 break;
00249         case EAI_NONAME:
00250 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00251         case EAI_NODATA:
00252 #endif
00253                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00254                         dns_zone_log(zone, ISC_LOG_ERROR,
00255                                      "%s/NS '%s' (out of zone) "
00256                                      "has no addresses records (A or AAAA)",
00257                                      ownerbuf, namebuf);
00258                         add(namebuf, ERR_NO_ADDRESSES);
00259                 }
00260                 /* XXX950 make fatal for 9.5.0 */
00261                 return (ISC_TRUE);
00262 
00263         default:
00264                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00265                         dns_zone_log(zone, ISC_LOG_WARNING,
00266                                      "getaddrinfo(%s) failed: %s",
00267                                      namebuf, gai_strerror(result));
00268                         add(namebuf, ERR_LOOKUP_FAILURE);
00269                 }
00270                 return (ISC_TRUE);
00271         }
00272 
00273         /*
00274          * Check that all glue records really exist.
00275          */
00276         if (!dns_rdataset_isassociated(a))
00277                 goto checkaaaa;
00278         result = dns_rdataset_first(a);
00279         while (result == ISC_R_SUCCESS) {
00280                 dns_rdataset_current(a, &rdata);
00281                 match = ISC_FALSE;
00282                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00283                         if (cur->ai_family != AF_INET)
00284                                 continue;
00285                         ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
00286                         if (memcmp(ptr, rdata.data, rdata.length) == 0) {
00287                                 match = ISC_TRUE;
00288                                 break;
00289                         }
00290                 }
00291                 if (!match && !logged(namebuf, ERR_EXTRA_A)) {
00292                         dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00293                                      "extra GLUE A record (%s)",
00294                                      ownerbuf, namebuf,
00295                                      inet_ntop(AF_INET, rdata.data,
00296                                                addrbuf, sizeof(addrbuf)));
00297                         add(namebuf, ERR_EXTRA_A);
00298                         /* XXX950 make fatal for 9.5.0 */
00299                         /* answer = ISC_FALSE; */
00300                 }
00301                 dns_rdata_reset(&rdata);
00302                 result = dns_rdataset_next(a);
00303         }
00304 
00305  checkaaaa:
00306         if (!dns_rdataset_isassociated(aaaa))
00307                 goto checkmissing;
00308         result = dns_rdataset_first(aaaa);
00309         while (result == ISC_R_SUCCESS) {
00310                 dns_rdataset_current(aaaa, &rdata);
00311                 match = ISC_FALSE;
00312                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00313                         if (cur->ai_family != AF_INET6)
00314                                 continue;
00315                         ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
00316                         if (memcmp(ptr, rdata.data, rdata.length) == 0) {
00317                                 match = ISC_TRUE;
00318                                 break;
00319                         }
00320                 }
00321                 if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
00322                         dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00323                                      "extra GLUE AAAA record (%s)",
00324                                      ownerbuf, namebuf,
00325                                      inet_ntop(AF_INET6, rdata.data,
00326                                                addrbuf, sizeof(addrbuf)));
00327                         add(namebuf, ERR_EXTRA_AAAA);
00328                         /* XXX950 make fatal for 9.5.0. */
00329                         /* answer = ISC_FALSE; */
00330                 }
00331                 dns_rdata_reset(&rdata);
00332                 result = dns_rdataset_next(aaaa);
00333         }
00334 
00335  checkmissing:
00336         /*
00337          * Check that all addresses appear in the glue.
00338          */
00339         if (!logged(namebuf, ERR_MISSING_GLUE)) {
00340                 isc_boolean_t missing_glue = ISC_FALSE;
00341                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00342                         switch (cur->ai_family) {
00343                         case AF_INET:
00344                                 rdataset = a;
00345                                 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
00346                                 type = "A";
00347                                 break;
00348                         case AF_INET6:
00349                                 rdataset = aaaa;
00350                                 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
00351                                 type = "AAAA";
00352                                 break;
00353                         default:
00354                                  continue;
00355                         }
00356                         match = ISC_FALSE;
00357                         if (dns_rdataset_isassociated(rdataset))
00358                                 result = dns_rdataset_first(rdataset);
00359                         else
00360                                 result = ISC_R_FAILURE;
00361                         while (result == ISC_R_SUCCESS && !match) {
00362                                 dns_rdataset_current(rdataset, &rdata);
00363                                 if (memcmp(ptr, rdata.data, rdata.length) == 0)
00364                                         match = ISC_TRUE;
00365                                 dns_rdata_reset(&rdata);
00366                                 result = dns_rdataset_next(rdataset);
00367                         }
00368                         if (!match) {
00369                                 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00370                                              "missing GLUE %s record (%s)",
00371                                              ownerbuf, namebuf, type,
00372                                              inet_ntop(cur->ai_family, ptr,
00373                                                        addrbuf, sizeof(addrbuf)));
00374                                 /* XXX950 make fatal for 9.5.0. */
00375                                 /* answer = ISC_FALSE; */
00376                                 missing_glue = ISC_TRUE;
00377                         }
00378                 }
00379                 if (missing_glue)
00380                         add(namebuf, ERR_MISSING_GLUE);
00381         }
00382         freeaddrinfo(ai);
00383         return (answer);
00384 #else
00385         return (ISC_TRUE);
00386 #endif
00387 }
00388 
00389 static isc_boolean_t
00390 checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
00391 #ifdef USE_GETADDRINFO
00392         struct addrinfo hints, *ai, *cur;
00393         char namebuf[DNS_NAME_FORMATSIZE + 1];
00394         char ownerbuf[DNS_NAME_FORMATSIZE];
00395         int result;
00396         int level = ISC_LOG_ERROR;
00397         isc_boolean_t answer = ISC_TRUE;
00398 
00399         memset(&hints, 0, sizeof(hints));
00400         hints.ai_flags = AI_CANONNAME;
00401         hints.ai_family = PF_UNSPEC;
00402         hints.ai_socktype = SOCK_STREAM;
00403         hints.ai_protocol = IPPROTO_TCP;
00404 
00405         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00406         /*
00407          * Turn off search.
00408          */
00409         if (dns_name_countlabels(name) > 1U)
00410                 strcat(namebuf, ".");
00411         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00412 
00413         result = getaddrinfo(namebuf, NULL, &hints, &ai);
00414         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00415         switch (result) {
00416         case 0:
00417                 /*
00418                  * Work around broken getaddrinfo() implementations that
00419                  * fail to set ai_canonname on first entry.
00420                  */
00421                 cur = ai;
00422                 while (cur != NULL && cur->ai_canonname == NULL &&
00423                        cur->ai_next != NULL)
00424                         cur = cur->ai_next;
00425                 if (cur != NULL && cur->ai_canonname != NULL &&
00426                     strcasecmp(cur->ai_canonname, namebuf) != 0) {
00427                         if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
00428                                 level = ISC_LOG_WARNING;
00429                         if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
00430                                 if (!logged(namebuf, ERR_IS_MXCNAME)) {
00431                                         dns_zone_log(zone, level,
00432                                                      "%s/MX '%s' (out of zone)"
00433                                                      " is a CNAME '%s' "
00434                                                      "(illegal)",
00435                                                      ownerbuf, namebuf,
00436                                                      cur->ai_canonname);
00437                                         add(namebuf, ERR_IS_MXCNAME);
00438                                 }
00439                                 if (level == ISC_LOG_ERROR)
00440                                         answer = ISC_FALSE;
00441                         }
00442                 }
00443                 freeaddrinfo(ai);
00444                 return (answer);
00445 
00446         case EAI_NONAME:
00447 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00448         case EAI_NODATA:
00449 #endif
00450                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00451                         dns_zone_log(zone, ISC_LOG_ERROR,
00452                                      "%s/MX '%s' (out of zone) "
00453                                      "has no addresses records (A or AAAA)",
00454                                      ownerbuf, namebuf);
00455                         add(namebuf, ERR_NO_ADDRESSES);
00456                 }
00457                 /* XXX950 make fatal for 9.5.0. */
00458                 return (ISC_TRUE);
00459 
00460         default:
00461                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00462                         dns_zone_log(zone, ISC_LOG_WARNING,
00463                              "getaddrinfo(%s) failed: %s",
00464                              namebuf, gai_strerror(result));
00465                         add(namebuf, ERR_LOOKUP_FAILURE);
00466                 }
00467                 return (ISC_TRUE);
00468         }
00469 #else
00470         return (ISC_TRUE);
00471 #endif
00472 }
00473 
00474 static isc_boolean_t
00475 checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
00476 #ifdef USE_GETADDRINFO
00477         struct addrinfo hints, *ai, *cur;
00478         char namebuf[DNS_NAME_FORMATSIZE + 1];
00479         char ownerbuf[DNS_NAME_FORMATSIZE];
00480         int result;
00481         int level = ISC_LOG_ERROR;
00482         isc_boolean_t answer = ISC_TRUE;
00483 
00484         memset(&hints, 0, sizeof(hints));
00485         hints.ai_flags = AI_CANONNAME;
00486         hints.ai_family = PF_UNSPEC;
00487         hints.ai_socktype = SOCK_STREAM;
00488         hints.ai_protocol = IPPROTO_TCP;
00489 
00490         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00491         /*
00492          * Turn off search.
00493          */
00494         if (dns_name_countlabels(name) > 1U)
00495                 strcat(namebuf, ".");
00496         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00497 
00498         result = getaddrinfo(namebuf, NULL, &hints, &ai);
00499         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00500         switch (result) {
00501         case 0:
00502                 /*
00503                  * Work around broken getaddrinfo() implementations that
00504                  * fail to set ai_canonname on first entry.
00505                  */
00506                 cur = ai;
00507                 while (cur != NULL && cur->ai_canonname == NULL &&
00508                        cur->ai_next != NULL)
00509                         cur = cur->ai_next;
00510                 if (cur != NULL && cur->ai_canonname != NULL &&
00511                     strcasecmp(cur->ai_canonname, namebuf) != 0) {
00512                         if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
00513                                 level = ISC_LOG_WARNING;
00514                         if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
00515                                 if (!logged(namebuf, ERR_IS_SRVCNAME)) {
00516                                         dns_zone_log(zone, level, "%s/SRV '%s'"
00517                                                      " (out of zone) is a "
00518                                                      "CNAME '%s' (illegal)",
00519                                                      ownerbuf, namebuf,
00520                                                      cur->ai_canonname);
00521                                         add(namebuf, ERR_IS_SRVCNAME);
00522                                 }
00523                                 if (level == ISC_LOG_ERROR)
00524                                         answer = ISC_FALSE;
00525                         }
00526                 }
00527                 freeaddrinfo(ai);
00528                 return (answer);
00529 
00530         case EAI_NONAME:
00531 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00532         case EAI_NODATA:
00533 #endif
00534                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00535                         dns_zone_log(zone, ISC_LOG_ERROR,
00536                                      "%s/SRV '%s' (out of zone) "
00537                                      "has no addresses records (A or AAAA)",
00538                                      ownerbuf, namebuf);
00539                         add(namebuf, ERR_NO_ADDRESSES);
00540                 }
00541                 /* XXX950 make fatal for 9.5.0. */
00542                 return (ISC_TRUE);
00543 
00544         default:
00545                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00546                         dns_zone_log(zone, ISC_LOG_WARNING,
00547                                      "getaddrinfo(%s) failed: %s",
00548                                      namebuf, gai_strerror(result));
00549                         add(namebuf, ERR_LOOKUP_FAILURE);
00550                 }
00551                 return (ISC_TRUE);
00552         }
00553 #else
00554         return (ISC_TRUE);
00555 #endif
00556 }
00557 
00558 isc_result_t
00559 setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
00560         isc_logdestination_t destination;
00561         isc_logconfig_t *logconfig = NULL;
00562         isc_log_t *log = NULL;
00563 
00564         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
00565         isc_log_registercategories(log, categories);
00566         isc_log_setcontext(log);
00567         dns_log_init(log);
00568         dns_log_setcontext(log);
00569         cfg_log_init(log);
00570 
00571         destination.file.stream = errout;
00572         destination.file.name = NULL;
00573         destination.file.versions = ISC_LOG_ROLLNEVER;
00574         destination.file.maximum_size = 0;
00575         RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
00576                                        ISC_LOG_TOFILEDESC,
00577                                        ISC_LOG_DYNAMIC,
00578                                        &destination, 0) == ISC_R_SUCCESS);
00579         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
00580                                          NULL, NULL) == ISC_R_SUCCESS);
00581 
00582         *logp = log;
00583         return (ISC_R_SUCCESS);
00584 }
00585 
00586 /*% scan the zone for oversize TTLs */
00587 static isc_result_t
00588 check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
00589         isc_result_t result;
00590         dns_db_t *db = NULL;
00591         dns_dbversion_t *version = NULL;
00592         dns_dbnode_t *node = NULL;
00593         dns_dbiterator_t *dbiter = NULL;
00594         dns_rdatasetiter_t *rdsiter = NULL;
00595         dns_rdataset_t rdataset;
00596         dns_fixedname_t fname;
00597         dns_name_t *name;
00598         dns_fixedname_init(&fname);
00599         name = dns_fixedname_name(&fname);
00600         dns_rdataset_init(&rdataset);
00601 
00602         CHECK(dns_zone_getdb(zone, &db));
00603         INSIST(db != NULL);
00604 
00605         CHECK(dns_db_newversion(db, &version));
00606         CHECK(dns_db_createiterator(db, 0, &dbiter));
00607 
00608         for (result = dns_dbiterator_first(dbiter);
00609              result == ISC_R_SUCCESS;
00610              result = dns_dbiterator_next(dbiter)) {
00611                 result = dns_dbiterator_current(dbiter, &node, name);
00612                 if (result == DNS_R_NEWORIGIN)
00613                         result = ISC_R_SUCCESS;
00614                 CHECK(result);
00615 
00616                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
00617                 for (result = dns_rdatasetiter_first(rdsiter);
00618                      result == ISC_R_SUCCESS;
00619                      result = dns_rdatasetiter_next(rdsiter)) {
00620                         dns_rdatasetiter_current(rdsiter, &rdataset);
00621                         if (rdataset.ttl > maxttl) {
00622                                 char nbuf[DNS_NAME_FORMATSIZE];
00623                                 char tbuf[255];
00624                                 isc_buffer_t b;
00625                                 isc_region_t r;
00626 
00627                                 dns_name_format(name, nbuf, sizeof(nbuf));
00628                                 isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
00629                                 CHECK(dns_rdatatype_totext(rdataset.type, &b));
00630                                 isc_buffer_usedregion(&b, &r);
00631                                 r.base[r.length] = 0;
00632 
00633                                 dns_zone_log(zone, ISC_LOG_ERROR,
00634                                              "%s/%s TTL %d exceeds "
00635                                              "maximum TTL %d",
00636                                              nbuf, tbuf, rdataset.ttl, maxttl);
00637                                 dns_rdataset_disassociate(&rdataset);
00638                                 CHECK(ISC_R_RANGE);
00639                         }
00640                         dns_rdataset_disassociate(&rdataset);
00641                 }
00642                 if (result == ISC_R_NOMORE)
00643                         result = ISC_R_SUCCESS;
00644                 CHECK(result);
00645 
00646                 dns_rdatasetiter_destroy(&rdsiter);
00647                 dns_db_detachnode(db, &node);
00648         }
00649 
00650         if (result == ISC_R_NOMORE)
00651                 result = ISC_R_SUCCESS;
00652 
00653  cleanup:
00654         if (node != NULL)
00655                 dns_db_detachnode(db, &node);
00656         if (rdsiter != NULL)
00657                 dns_rdatasetiter_destroy(&rdsiter);
00658         if (dbiter != NULL)
00659                 dns_dbiterator_destroy(&dbiter);
00660         if (version != NULL)
00661                 dns_db_closeversion(db, &version, ISC_FALSE);
00662         if (db != NULL)
00663                 dns_db_detach(&db);
00664 
00665         return (result);
00666 }
00667 
00668 /*% load the zone */
00669 isc_result_t
00670 load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
00671           dns_masterformat_t fileformat, const char *classname,
00672           dns_ttl_t maxttl, dns_zone_t **zonep)
00673 {
00674         isc_result_t result;
00675         dns_rdataclass_t rdclass;
00676         isc_textregion_t region;
00677         isc_buffer_t buffer;
00678         dns_fixedname_t fixorigin;
00679         dns_name_t *origin;
00680         dns_zone_t *zone = NULL;
00681 
00682         REQUIRE(zonep == NULL || *zonep == NULL);
00683 
00684         if (debug)
00685                 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
00686                         zonename, filename, classname);
00687 
00688         CHECK(dns_zone_create(&zone, mctx));
00689 
00690         dns_zone_settype(zone, dns_zone_master);
00691 
00692         isc_buffer_constinit(&buffer, zonename, strlen(zonename));
00693         isc_buffer_add(&buffer, strlen(zonename));
00694         dns_fixedname_init(&fixorigin);
00695         origin = dns_fixedname_name(&fixorigin);
00696         CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
00697         CHECK(dns_zone_setorigin(zone, origin));
00698         CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
00699         CHECK(dns_zone_setfile2(zone, filename, fileformat));
00700         if (journal != NULL)
00701                 CHECK(dns_zone_setjournal(zone, journal));
00702 
00703         DE_CONST(classname, region.base);
00704         region.length = strlen(classname);
00705         CHECK(dns_rdataclass_fromtext(&rdclass, &region));
00706 
00707         dns_zone_setclass(zone, rdclass);
00708         dns_zone_setoption(zone, zone_options, ISC_TRUE);
00709         dns_zone_setoption2(zone, zone_options2, ISC_TRUE);
00710         dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
00711 
00712         dns_zone_setmaxttl(zone, maxttl);
00713 
00714         if (docheckmx)
00715                 dns_zone_setcheckmx(zone, checkmx);
00716         if (docheckns)
00717                 dns_zone_setcheckns(zone, checkns);
00718         if (dochecksrv)
00719                 dns_zone_setchecksrv(zone, checksrv);
00720 
00721         CHECK(dns_zone_load(zone));
00722 
00723         /*
00724          * When loading map files we can't catch oversize TTLs during
00725          * load, so we check for them here.
00726          */
00727         if (fileformat == dns_masterformat_map && maxttl != 0) {
00728                 CHECK(check_ttls(zone, maxttl));
00729         }
00730 
00731         if (zonep != NULL) {
00732                 *zonep = zone;
00733                 zone = NULL;
00734         }
00735 
00736  cleanup:
00737         if (zone != NULL)
00738                 dns_zone_detach(&zone);
00739         return (result);
00740 }
00741 
00742 /*% dump the zone */
00743 isc_result_t
00744 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
00745           dns_masterformat_t fileformat, const dns_master_style_t *style,
00746           const isc_uint32_t rawversion)
00747 {
00748         isc_result_t result;
00749         FILE *output = stdout;
00750         const char *flags;
00751 
00752         flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
00753 
00754         if (debug) {
00755                 if (filename != NULL && strcmp(filename, "-") != 0)
00756                         fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
00757                                 zonename, filename);
00758                 else
00759                         fprintf(stderr, "dumping \"%s\"\n", zonename);
00760         }
00761 
00762         if (filename != NULL && strcmp(filename, "-") != 0) {
00763                 result = isc_stdio_open(filename, flags, &output);
00764 
00765                 if (result != ISC_R_SUCCESS) {
00766                         fprintf(stderr, "could not open output "
00767                                 "file \"%s\" for writing\n", filename);
00768                         return (ISC_R_FAILURE);
00769                 }
00770         }
00771 
00772         result = dns_zone_dumptostream3(zone, output, fileformat, style,
00773                                         rawversion);
00774         if (output != stdout)
00775                 (void)isc_stdio_close(output);
00776 
00777         return (result);
00778 }
00779 
00780 #ifdef _WIN32
00781 void
00782 InitSockets(void) {
00783         WORD wVersionRequested;
00784         WSADATA wsaData;
00785         int err;
00786 
00787         wVersionRequested = MAKEWORD(2, 0);
00788 
00789         err = WSAStartup( wVersionRequested, &wsaData );
00790         if (err != 0) {
00791                 fprintf(stderr, "WSAStartup() failed: %d\n", err);
00792                 exit(1);
00793         }
00794 }
00795 
00796 void
00797 DestroySockets(void) {
00798         WSACleanup();
00799 }
00800 #endif
00801 

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